Fileportz/DeepSeek-V4.1-Flash
031
1# DeepSeek-V4.1 text and vision encoding2 3`encoding.py` is the standalone prompt-format reference for DeepSeek-V4.1. It4supports multi-turn conversations, tool calls, thinking modes, numeric reasoning5effort, mid-conversation system messages, and interleaved image content blocks,6without importing the inference implementation.7 8## V4.1 changes relative to V49 10Three prompt-format changes distinguish V4.1 from V4:11 121. **DSML tag names use a leading space.** Tool calls are wrapped in13 `<|DSML| calls>` blocks with `<|DSML| invoke>` / `<|DSML| parameter>` tags14 (note the space before `calls`, `invoke`, and `parameter`). The V4 format used15 `<|DSML|tool_calls>` without a space.16 172. **Reasoning effort is a numeric budget (1–100).** The effort prefix is18 rendered as `Reasoning Effort: {budget} (range 1-100, ...)` rather than the19 verbose natural-language descriptions used in V4. String aliases map as20 follows: `"low"` → 50, `"high"` → 75, `"max"` → 100. The21 default is `"high"` (75). The effort prefix is only rendered in22 `thinking_mode="thinking"` and only at the beginning of the conversation23 (index 0).24 253. **Mid-conversation system messages** are supported via the `<|System|>` token.26 A mid-conversation system message behaves like a user message for the purpose27 of appending the assistant generation header.28 29## Quick start30 31```python32from encoding import encode_messages, parse_message_from_completion_text33 34# Text-only conversation35messages = [36 {"role": "system", "content": "You are a helpful assistant."},37 {"role": "user", "content": "What is 2+2?"},38]39prompt, media = encode_messages(40 messages,41 thinking_mode="thinking",42 reasoning_effort=75, # integer 1–100, or "low"/"high"/"max"43 return_multi_modal_data=True,44)45# prompt:46# '<|begin▁of▁sentence|><|System|>Reasoning Effort: 75 (range 1-100, the higher the47# value, the more thorough the reasoning)\n\nYou are a helpful assistant.48# <|User|>What is 2+2?<|Assistant|><think>'49 50# Parse model output back to a structured message51completion = "Simple arithmetic.</think>2 + 2 = 4.<|end▁of▁sentence|>"52parsed = parse_message_from_completion_text(completion, thinking_mode="thinking")53# => {"role": "assistant", "reasoning_content": "Simple arithmetic.",54# "content": "2 + 2 = 4.", "tool_calls": []}55```56 57> **Note:** `parse_message_from_completion_text` is designed to handle58> well-formatted model output only. It does not attempt to correct or recover59> from malformed output that the model might occasionally generate. For60> production use, additional error handling is recommended.61 62## OpenAI-style messages63 64```python65from encoding import encode_messages66 67messages = [{68 "role": "user",69 "content": [70 {"type": "text", "text": "第一张图"},71 {72 "type": "image_url",73 "image_url": {"url": "examples/images/image_1.jpeg"},74 },75 {"type": "text", "text": "有什么内容?"},76 ],77}]78 79prompt, media = encode_messages(80 messages,81 thinking_mode="chat",82 return_multi_modal_data=True,83)84# prompt:85# '<|begin▁of▁sentence|><|User|>第一张图\n\n<|deepseek_image|>\n\n有什么内容?<|Assistant|></think>'86# media["images"] contains the image records in prompt order87```88 89Images are represented in the prompt by `<|deepseek_image|>`. `media["images"]`90contains the corresponding image records in exactly the same order they appear in91the prompt. Pixel loading and expansion into model image tokens are handled by92`inference/image_processor.py`.93 94## Compact TXT notation95 96`parse_tagged_text()` converts a compact prompt such as97 98```text99第一张图<image>examples/images/image_1.jpeg</image>有什么内容?100```101 102into the same standard content blocks. It is an input convenience layer, not a103second encoding implementation.104 105## Message format106 107### Special tokens108 109| Token | Purpose |110| :--- | :--- |111| `<|begin▁of▁sentence|>` | Beginning of sequence (BOS) |112| `<|end▁of▁sentence|>` | End of assistant turn (EOS) |113| `<|User|>` | User turn prefix |114| `<|Assistant|>` | Assistant turn prefix |115| `<|System|>` | Mid-conversation system message prefix |116| `<|latest_reminder|>` | Latest reminder (date, locale, etc.) |117| `<think>` / `</think>` | Reasoning block delimiters |118| `|DSML|` | DSML markup token |119| `<|deepseek_image|>` | Image placeholder in the prompt string |120 121### Roles122 123The encoding supports the following message roles: `system`, `user`, `assistant`,124`tool`, and `latest_reminder`.125 126A `tool` message is not rendered directly: `merge_tool_messages()` converts it127into a `<tool_result>` block inside the preceding user message. When multiple128tool results are present, they are sorted by the order of the corresponding129`tool_calls` in the preceding assistant message.130 131### Basic chat132 133A simple multi-turn conversation is encoded as:134 135```136<|begin▁of▁sentence|>{system_prompt}137<|User|>{user_message}<|Assistant|></think>{response}<|end▁of▁sentence|>138<|User|>{user_message_2}<|Assistant|></think>{response_2}<|end▁of▁sentence|>139```140 141- The BOS token is prepended at the very beginning of the conversation.142- In **chat mode** (`thinking_mode="chat"`), `</think>` is placed right after143 `<|Assistant|>` to immediately close the thinking block, so the model generates144 content directly.145 146### Thinking mode147 148In **thinking mode** (`thinking_mode="thinking"`), the model produces explicit149reasoning inside `<think>...</think>` blocks before responding.150 151```152<|begin▁of▁sentence|><|System|>{reasoning_effort_prefix}{system_prompt}153<|User|>{message}<|Assistant|><think>{reasoning}</think>{response}<|end▁of▁sentence|>154```155 156The reasoning effort prefix is injected once, before the system message, as a157`<|System|>` block:158 159```160<|System|>Reasoning Effort: {budget} (range 1-100, the higher the value, the more thorough the reasoning)161```162 163The `drop_thinking` parameter (default `True`) controls whether reasoning from164earlier turns is preserved:165 166- **Without tools**: reasoning content from assistant turns **before** the last167 user message is stripped. Only the final assistant turn retains its168 `<think>...</think>` block.169- **With tools**: `drop_thinking` is automatically disabled. All turns retain170 their reasoning, because tool-calling conversations require full context for171 the model to track multi-step reasoning across tool calls.172 173### Tool calling (DSML format)174 175Tools are defined on the `system` message via the `tools` field176(OpenAI-compatible format). When tools are present, the following schema block is177injected into the system prompt:178 179```180## Tools181 182You have access to a set of tools to help answer the user's question. You can invoke tools by writing a "<|DSML| calls>" block like the following:183 184<|DSML| calls>185<|DSML| invoke name="$TOOL_NAME">186<|DSML| parameter name="$PARAMETER_NAME" string="true|false">$PARAMETER_VALUE</|DSML| parameter>187...188</|DSML| invoke>189<|DSML| invoke name="$TOOL_NAME2">190...191</|DSML| invoke>192</|DSML| calls>193 194String parameters should be specified as is and set `string="true"`. For all other types (numbers, booleans, arrays, objects), pass the value in JSON format and set `string="false"`.195 196If thinking_mode is enabled (triggered by <think>), you MUST output your complete reasoning inside <think>...</think> BEFORE any tool calls or final response.197 198Otherwise, output directly after </think> with tool calls or final response.199 200### Available Tool Schemas201 202{tool_definitions_json}203 204You MUST strictly follow the above defined tool name and parameter schemas to invoke tool calls.205```206 207An actual tool call in the assistant turn looks like:208 209```xml210 211<|DSML| calls>212<|DSML| invoke name="function_name">213<|DSML| parameter name="param" string="true">string_value</|DSML| parameter>214<|DSML| parameter name="count" string="false">5</|DSML| parameter>215</|DSML| invoke>216</|DSML| calls><|end▁of▁sentence|>217```218 219- `string="true"`: the parameter value is a raw string.220- `string="false"`: the parameter value is JSON (number, boolean, array, object).221 222Tool execution results are wrapped in `<tool_result>` tags within user messages:223 224```225<|User|><tool_result>{result_json}</tool_result><|Assistant|><think>...226```227 228### Tool namespaces229 230Tool definitions may include a `namespace` alongside `function`, either as a231string or as an object with `name` and an optional `description`:232 233```python234tool = {235 "type": "function",236 "namespace": {"name": "search", "description": "Search tools."},237 "function": {238 "name": "lookup",239 "description": "Look up a value",240 "parameters": {"type": "object", "properties": {"query": {"type": "string"}}},241 },242}243tool_call = {244 "type": "function",245 "namespace": "search",246 "function": {"name": "lookup", "arguments": '{"query": "value"}'},247}248```249 250The tool schema and DSML invocation both use `search::lookup`. The namespace251description is prepended to the tool description, separated by a newline.252The parser returns `function.name="lookup"` and `namespace="search"` on the253tool call, so its output can be passed back to `encode_messages()` directly.254 255Input also accepts `namespace` inside `function`, or a qualified function name256such as `search::lookup`. A qualified name must agree with any explicit257namespace; `::` separates exactly one namespace from the tool name. Tools258without a namespace retain their original names and output format.259 260### Reasoning effort261 262Pass `reasoning_effort` as an integer in `[1, 100]` or as one of `"low"` (50),263`"high"` (75), or `"max"` (100). The default is `"high"` (75).264The setting only affects `thinking_mode="thinking"` and is only rendered at the265start of the conversation (index 0). Intermediate values may be used to elicit266interpolated reasoning behavior.267 268### Quick instruction special tokens269 270Quick instruction tokens are used for auxiliary classification and generation271tasks. They are appended to messages via the `"task"` field to trigger272specialized model behavior for a single-token or short-form output.273 274| Special Token | Description | Format |275|:---|:---|:---|276| `<|action|>` | Determines whether the user prompt requires a web search or can be answered directly. | `...<|User|>{prompt}<|Assistant|><think><|action|>` |277| `<|title|>` | Generates a concise conversation title after the first assistant response. | `...<|Assistant|>{response}<|end▁of▁sentence|><|title|>` |278| `<|query|>` | Generates search queries for the user prompt. | `...<|User|>{prompt}<|query|>` |279| `<|authority|>` | Classifies the user prompt's demand for source authoritativeness. | `...<|User|>{prompt}<|authority|>` |280| `<|domain|>` | Identifies the domain of the user prompt. | `...<|User|>{prompt}<|domain|>` |281| `<|read_url|>` | Determines whether each URL in the user prompt should be fetched and read. | `...<|User|>{prompt}<|read_url|>` |282 283Usage in message format:284 285- **`action`** on a user message: the `<|action|>` token is placed after the286 assistant prefix and thinking token, triggering a routing decision (e.g.,287 "Search" or "Answer").288- **Other tasks** (`query`, `authority`, `domain`, `read_url`) on a user message:289 the task token is appended directly after the user content.290- **`title`** on an assistant message: the `<|title|>` token is appended after291 the assistant's EOS. The next assistant message provides the generated title.292 293## Tests294 295From this directory:296 297```bash298python -m pytest -q test_encoding.py299```300 301Test cases are stored as paired JSON input / TXT expected-output files under302`tests/`. The tests cover multi-turn conversations, tool calling, thinking mode,303numeric reasoning effort, mid-conversation system messages, and multimodal image304ordering. They include a check that the TXT and JSON examples encode to the same305prompt and preserve the same image ordering.306 