# yankeexe/llm-function-calling-demo architecture

> Architecture diagram of the GitHub repository yankeexe/llm-function-calling-demo, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/yankeexe/llm-function-calling-demo
- Repository: https://github.com/yankeexe/llm-function-calling-demo

## Overview

1. **Repository shape**
   - This is a very small, single-purpose Python demo repository.
   - The core runtime lives in `app.py`; everything else supports local setup, containerization, and CI.

2. **Primary runtime boundary**
   - The application is a local Python process that talks to a separately running **Ollama** service.
   - Ollama is not embedded in the repo; it is an external runtime dependency that must already be installed and running.

3. **Main execution flow**
   - A user starts the app either locally or in Docker.
   - `app.py` sends prompts to Ollama using the configured model.
   - The model can return a function/tool call request.
   - The app executes the matching local Python function and sends the result back to Ollama.
   - Ollama then produces the final natural-language response.

4. **Function-calling loop**
   - The architectural point of the demo is the interaction between:
     - the LLM response,
     - the application’s function dispatcher,
     - and the returned tool output.
   - This is a request/response loop rather than a long-running server with multiple internal services.

5. **Application responsibilities**
   - `app.py` is responsible for:
     - configuring the model name,
     - connecting to Ollama,
     - defining callable functions,
     - handling model requests for function execution,
     - and printing or returning the final answer.
   - The repo does not show separate modules for API, domain logic, or persistence, so the app is intentionally monolithic.

6. **No persistent data layer**
   - There is no database, queue, cache, or external state store in the repository.
   - All state is transient and lives only during the app’s execution and the ongoing chat/function-calling exchange.

7. **Containerization boundary**
   - The `Dockerfile` packages the Python app for container execution.
   - The container still depends on Ollama running outside the container, on the host machine.
   - The README notes a host networking/DNS nuance: the container uses `host.docker.internal` to reach host Ollama, which is not portable to Linux without extra handling.

8. **Model/runtime configuration**
   - The demo defaults to an Ollama model such as `mistral-nemo`.
   - The README indicates the model can be switched to alternatives like `llama3.1` or `llama3.2` by editing `app.py`.
   - This makes model selection part of application configuration, not infrastructure automation.

9. **Developer workflow**
   - `Makefile` is the main orchestration entry point for local setup, running, linting, and fixes.
   - `requirements/requirements.txt` and `requirements/requirements-dev.txt` separate runtime dependencies from developer tooling.

10. **CI/CD boundary**
   - `.github/workflows/ci.yaml` defines automated checks in GitHub Actions.
   - Based on the repo structure, CI is likely focused on install/test/lint/format verification rather than building deployable services.

11. **How to draw the diagram**
   - The central box should be `app.py` / Python application.
   - Show an external box for `Ollama`.
   - Show Docker as an optional wrapper around the Python app, not around Ollama.
   - Show `Makefile` and GitHub Actions as supporting developer/automation layers around the app, not as part of runtime data flow.

12. **Overall architecture summary**
   - This is a lightweight local LLM function-calling demo: one Python application, one external model server, optional Docker packaging, and simple CI/tooling.
   - The key architectural relationship is the bidirectional exchange between the app’s local functions and Ollama’s tool-call-capable model responses.

Main entry points: [`app.py`](https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py) (app.py), [`.github/workflows/ci.yaml`](https://github.com/yankeexe/llm-function-calling-demo/blob/main/.github/workflows/ci.yaml) (CI), [`Makefile`](https://github.com/yankeexe/llm-function-calling-demo/tree/main/Makefile) (Makefile), [`Dockerfile`](https://github.com/yankeexe/llm-function-calling-demo/tree/main/Dockerfile) (Dockerfile)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Runtime"]
  node_user(("User<br/>actor"))
  node_app["app.py<br/>python app<br/>[app.py]"]
  node_model_config["Model cfg<br/>config<br/>[app.py]"]
  node_ollama_client["Ollama client<br/>api client<br/>[app.py]"]
  node_tool_dispatcher{{"Dispatcher<br/>tool router<br/>[app.py]"}}
  node_local_tools["Local tools<br/>python functions<br/>[app.py]"]
  node_response_loop(("Loop<br/>[app.py]"))
  node_ollama["Ollama<br/>external LLM server"]
end

subgraph group_support["Support"]
  node_dockerfile["Dockerfile<br/>container build"]
  node_makefile["Makefile<br/>workflow runner"]
  node_ci["CI<br/>github actions<br/>[ci.yaml]"]
  node_runtime_reqs["Reqs<br/>deps<br/>[requirements.txt]"]
  node_dev_reqs["Dev reqs<br/>dev deps"]
end

node_user -->|"start"| node_app
node_app -->|"uses"| node_model_config
node_app -->|"prompts"| node_ollama_client
node_ollama_client -->|"request"| node_ollama
node_ollama -->|"tool call"| node_response_loop
node_response_loop -->|"routes"| node_tool_dispatcher
node_tool_dispatcher -->|"executes"| node_local_tools
node_local_tools -->|"result"| node_ollama_client
node_ollama_client -->|"final answer"| node_response_loop
node_app -->|"drives"| node_response_loop
node_dockerfile -->|"packages"| node_app
node_makefile -->|"run/lint"| node_app
node_makefile -->|"build"| node_dockerfile
node_ci -->|"invokes"| node_makefile
node_ci -->|"installs"| node_runtime_reqs
node_ci -->|"installs"| node_dev_reqs

click node_app "https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py"
click node_model_config "https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py"
click node_ollama_client "https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py"
click node_tool_dispatcher "https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py"
click node_local_tools "https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py"
click node_response_loop "https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py"
click node_dockerfile "https://github.com/yankeexe/llm-function-calling-demo/tree/main/Dockerfile"
click node_makefile "https://github.com/yankeexe/llm-function-calling-demo/tree/main/Makefile"
click node_ci "https://github.com/yankeexe/llm-function-calling-demo/blob/main/.github/workflows/ci.yaml"
click node_runtime_reqs "https://github.com/yankeexe/llm-function-calling-demo/blob/main/requirements/requirements.txt"
click node_dev_reqs "https://github.com/yankeexe/llm-function-calling-demo/blob/main/requirements/requirements-dev.txt"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_user,node_app,node_model_config,node_ollama_client,node_tool_dispatcher,node_local_tools,node_response_loop,node_ollama toneBlue
class node_dockerfile,node_makefile,node_ci,node_runtime_reqs,node_dev_reqs toneAmber
```

## Components

### Runtime

The local Python demo and its external model dependency

- **User**: actor · Starts the demo and reads the answer
- [app.py](https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py): python app · Monolithic function-calling client and control loop · `app.py`
- [Model cfg](https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py): config · Chooses the Ollama model used by the demo · `app.py`
- [Ollama client](https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py): api client · Sends prompts and tool results to Ollama · `app.py`
- [Dispatcher](https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py): tool router · Matches requested tool calls to local functions · `app.py`
- [Local tools](https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py): python functions · Callable demo functions executed by the app · `app.py`
- [Loop](https://github.com/yankeexe/llm-function-calling-demo/blob/main/app.py): exchange loop · Handles request, tool call, and final response · `app.py`
- **Ollama**: external LLM server · Separate host service that returns tool-call-capable model responses

### Support

Container, automation, and dependency management

- [Dockerfile](https://github.com/yankeexe/llm-function-calling-demo/tree/main/Dockerfile): container build · Packages the Python app for container execution · `Dockerfile`
- [Makefile](https://github.com/yankeexe/llm-function-calling-demo/tree/main/Makefile): workflow runner · Local setup, run, lint, and fix entry point · `Makefile`
- [CI](https://github.com/yankeexe/llm-function-calling-demo/blob/main/.github/workflows/ci.yaml): github actions · Automated install and verification workflow · `.github/workflows/ci.yaml`
- [Reqs](https://github.com/yankeexe/llm-function-calling-demo/blob/main/requirements/requirements.txt): deps · Runtime Python dependencies · `requirements/requirements.txt`
- [Dev reqs](https://github.com/yankeexe/llm-function-calling-demo/blob/main/requirements/requirements-dev.txt): dev deps · Developer tooling dependencies · `requirements/requirements-dev.txt`

## Connections

- User → app.py: start · User launches the local demo
- app.py → Model cfg: uses · App selects the configured Ollama model
- app.py → Ollama client: prompts · App sends chat requests to Ollama
- Ollama client → Ollama: request · Prompt is delivered to the external Ollama service
- Ollama → Loop: tool call · Model may request a local function execution
- Loop → Dispatcher: routes · App inspects the request and selects a callable
- Dispatcher → Local tools: executes · Matching local Python function runs in-process
- Local tools → Ollama client: result · Tool output is sent back into the chat exchange
- Ollama client → Loop: final answer · Ollama returns the natural-language response
- app.py → Loop: drives · Main program orchestrates the function-calling loop
- Dockerfile → app.py: packages · Container image wraps the Python application only
- Makefile → app.py: run/lint · Make targets orchestrate local developer tasks
- Makefile → Dockerfile: build · Make can support container workflows
- CI → Makefile: invokes · CI likely reuses the same project commands
- CI → Reqs: installs · CI validates runtime dependency installation
- CI → Dev reqs: installs · CI validates developer tooling installation
