|
| 1 | +# Chatbot: Fine-tuning & Prompting |
| 2 | + |
| 3 | +_Available from version >= 6.7.0_ |
| 4 | + |
| 5 | +This guide covers choosing and customizing the language model behind the chatbot, tuning the prompt, |
| 6 | +and packaging a custom model. It is aimed at operators who want to change the default model or |
| 7 | +improve answer quality. For the environment variables referenced here see the |
| 8 | +[chatbot configuration](./advanced_configuration.md#chatbot). |
| 9 | + |
| 10 | +## How the model is wired |
| 11 | + |
| 12 | +The chatbot uses [Ollama](https://ollama.com/) as a local LLM runtime and LangChain's native |
| 13 | +**tool-calling** agent. At build time the backend creates a `ChatOllama` client |
| 14 | +(`api_app/chatbot_manager/agent/agent.py`) pointed at `OLLAMA_BASE_URL` (default |
| 15 | +`http://ollama:11434`) with `temperature=0` and a fixed context window, binds the chatbot tools to |
| 16 | +it through the tool-calling API, and runs a tool-call → observation loop until the model replies with |
| 17 | +plain text. |
| 18 | + |
| 19 | +Two consequences matter for tuning: |
| 20 | + |
| 21 | +- The model **must support Ollama tool calling**. A model that cannot emit tool calls will not work. |
| 22 | +- The backend sets the prompt and the key inference parameters itself (see below), so they are the |
| 23 | + levers you tune — not a model's baked-in defaults. |
| 24 | + |
| 25 | +## Choosing a model |
| 26 | + |
| 27 | +The default is **`qwen2.5:3b`**. It is chosen on purpose: it is the smallest model that reliably |
| 28 | +picks the right tool and answers from the tool output with **usable latency on a CPU-only deploy** |
| 29 | +(for comparison, a 7B model such as `mistral` was markedly slower on CPU — minutes per agent round, |
| 30 | +often hitting the turn timeout). On stronger |
| 31 | +hardware you can switch to any larger tool-capable Ollama model for better answer quality. |
| 32 | + |
| 33 | +Requirements for a replacement model: |
| 34 | + |
| 35 | +- it supports tool calling in Ollama; |
| 36 | +- the Ollama server is recent enough to **stream while tools are bound** — IntelOwl pins the Ollama |
| 37 | + image to `ollama/ollama:0.30.7` for this reason (versions older than 0.8.0 cannot stream with |
| 38 | + tools); keep this in mind if you run Ollama yourself. |
| 39 | + |
| 40 | +## Pointing to a different model |
| 41 | + |
| 42 | +Set the `OLLAMA_MODEL` secret to the model tag you want (it is pulled automatically on first start). |
| 43 | +Keep the **three** places that reference the default in sync if you change the baked-in default |
| 44 | +rather than just overriding the secret: |
| 45 | + |
| 46 | +- `intel_owl/settings/chatbot.py` — `OLLAMA_MODEL` default; |
| 47 | +- `docker/env_file_app_template` — `OLLAMA_MODEL`; |
| 48 | +- `docker/entrypoints/ollama.sh` — `DEFAULT_MODEL` (the entrypoint that pulls the model). |
| 49 | + |
| 50 | +For a normal deployment you only set the `OLLAMA_MODEL` secret; the entrypoint pulls it on startup. |
| 51 | + |
| 52 | +## The context window (`num_ctx`) |
| 53 | + |
| 54 | +The backend requests an **8192-token** context window (`_NUM_CTX` in `agent.py`). This is |
| 55 | +deliberate: Ollama's default of 2048 tokens silently truncates the prompt (the system prompt plus |
| 56 | +the tool schemas already approach ~2.2k tokens), which drops tool definitions and wrecks tool |
| 57 | +selection. 8192 fits the prompt, the conversation history and the tool observations comfortably and |
| 58 | +keeps the prompt prefix stable across iterations (so follow-up rounds hit Ollama's KV cache). |
| 59 | + |
| 60 | +If you move to a larger model with a bigger context window and longer conversations, raising |
| 61 | +`_NUM_CTX` is the knob — at the cost of more memory and slower evaluation. |
| 62 | + |
| 63 | +## The system prompt |
| 64 | + |
| 65 | +The assistant's instructions live in plain text at |
| 66 | +`api_app/chatbot_manager/agent/system_prompt.txt`. This — not a model's built-in system message — is |
| 67 | +what shapes the assistant's behavior, because the backend sends it as the agent's system prompt on |
| 68 | +every turn. The file is organized in sections: |
| 69 | + |
| 70 | +- `[Role]` — who the assistant is and its answer style (concise, data-driven, cite the tools used); |
| 71 | +- `[Tools — when to use each]` — one line per tool telling the model when to call it; |
| 72 | +- `[Rules]` — hard constraints (only the current user's data; call the right tool instead of |
| 73 | + guessing; `analyze_observable` only previews and never claims it launched anything); |
| 74 | +- `[Response style]` — formatting expectations. |
| 75 | + |
| 76 | +To tune behavior, edit this file. Practical prompting tips for small local models: |
| 77 | + |
| 78 | +- Keep tool descriptions short and action-oriented ("Use for …"); they compete for context space. |
| 79 | +- State hard guarantees in `[Rules]` (data scoping, the preview-only analysis guardrail) — small |
| 80 | + models follow short imperative rules better than long prose. |
| 81 | +- When you add a new tool, add a matching one-line entry under `[Tools — when to use each]` so the |
| 82 | + model knows when to reach for it (see [adding a chatbot tool](./contribute.md)). |
| 83 | + |
| 84 | +## Building a custom model with a Modelfile |
| 85 | + |
| 86 | +Use an Ollama [Modelfile](https://docs.ollama.com/modelfile) to **package the weights** you want to |
| 87 | +run — for example a specific quantization, or a fine-tuned model imported from a local GGUF file: |
| 88 | + |
| 89 | +```dockerfile |
| 90 | +# Modelfile |
| 91 | +FROM qwen2.5:3b-instruct-q4_K_M |
| 92 | +# or import your own weights: |
| 93 | +# FROM ./my-finetuned-model.gguf |
| 94 | +``` |
| 95 | + |
| 96 | +Build and register it, then point the chatbot at it: |
| 97 | + |
| 98 | +```bash |
| 99 | +ollama create intelowl-llm -f Modelfile |
| 100 | +# then set the secret: |
| 101 | +OLLAMA_MODEL=intelowl-llm |
| 102 | +``` |
| 103 | + |
| 104 | +Important: the backend sets `num_ctx`, `temperature` and the system prompt explicitly on every call, |
| 105 | +so a Modelfile's `SYSTEM` and its `PARAMETER num_ctx` / `PARAMETER temperature` are overridden for the |
| 106 | +chatbot (other `PARAMETER` directives the backend does not set still apply). Use the Modelfile to |
| 107 | +choose *which weights* run; use `system_prompt.txt` (and `_NUM_CTX` in |
| 108 | +`agent.py`) to change *how the assistant behaves*. |
| 109 | + |
| 110 | +## Validating a model before rollout |
| 111 | + |
| 112 | +After switching or building a model, confirm it actually tool-calls before relying on it: |
| 113 | + |
| 114 | +1. Bring up the stack with the Ollama service and wait for the model to finish pulling. |
| 115 | +2. Open the chat and send a question that must use a tool, e.g. **"Show my recent jobs"** or |
| 116 | + **"Summarize job #<id>"**. |
| 117 | +3. Verify the assistant calls a tool (a tool/status indicator appears) and answers from real data, |
| 118 | + rather than replying generically. The same check works through the REST endpoint |
| 119 | + `POST /api/chatbot/sessions/message`. |
| 120 | + |
| 121 | +If the model answers without ever calling a tool, it is not tool-calling reliably — pick a different |
| 122 | +model or a less aggressively quantized variant. |
| 123 | + |
| 124 | +## Out of scope |
| 125 | + |
| 126 | +Actual model training (LoRA/PEFT fine-tuning, dataset preparation, GGUF conversion of trained |
| 127 | +adapters) is outside the scope of this guide. This page covers selecting, configuring, prompting and |
| 128 | +packaging existing tool-capable models. |
0 commit comments