Model3 / encoding /README.md
calmresearch-ai's picture GeeeekExplorer's picture
Duplicate from deepseek-ai/DeepSeek-V4.1-Flash
33039e1
|
Raw History Blame Contribute Delete
12.1 kB
# DeepSeek-V4.1 text and vision encoding
`encoding.py` is the standalone prompt-format reference for DeepSeek-V4.1. It
supports multi-turn conversations, tool calls, thinking modes, numeric reasoning
effort, mid-conversation system messages, and interleaved image content blocks,
without importing the inference implementation.
## V4.1 changes relative to V4
Three prompt-format changes distinguish V4.1 from V4:
1. **DSML tag names use a leading space.** Tool calls are wrapped in
`<|DSML| calls>` blocks with `<|DSML| invoke>` / `<|DSML| parameter>` tags
(note the space before `calls`, `invoke`, and `parameter`). The V4 format used
`<|DSML|tool_calls>` without a space.
2. **Reasoning effort is a numeric budget (1–100).** The effort prefix is
rendered as `Reasoning Effort: {budget} (range 1-100, ...)` rather than the
verbose natural-language descriptions used in V4. String aliases map as
follows: `"low"` → 50, `"high"` → 75, `"max"` → 100. The
default is `"high"` (75). The effort prefix is only rendered in
`thinking_mode="thinking"` and only at the beginning of the conversation
(index 0).
3. **Mid-conversation system messages** are supported via the `<|System|>` token.
A mid-conversation system message behaves like a user message for the purpose
of appending the assistant generation header.
## Quick start
```python
from encoding import encode_messages, parse_message_from_completion_text
# Text-only conversation
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"},
]
prompt, media = encode_messages(
messages,
thinking_mode="thinking",
reasoning_effort=75, # integer 1–100, or "low"/"high"/"max"
return_multi_modal_data=True,
)
# prompt:
# '<|begin▁of▁sentence|><|System|>Reasoning Effort: 75 (range 1-100, the higher the
# value, the more thorough the reasoning)\n\nYou are a helpful assistant.
# <|User|>What is 2+2?<|Assistant|><think>'
# Parse model output back to a structured message
completion = "Simple arithmetic.</think>2 + 2 = 4.<|end▁of▁sentence|>"
parsed = parse_message_from_completion_text(completion, thinking_mode="thinking")
# => {"role": "assistant", "reasoning_content": "Simple arithmetic.",
# "content": "2 + 2 = 4.", "tool_calls": []}
```
> **Note:** `parse_message_from_completion_text` is designed to handle
> well-formatted model output only. It does not attempt to correct or recover
> from malformed output that the model might occasionally generate. For
> production use, additional error handling is recommended.
## OpenAI-style messages
```python
from encoding import encode_messages
messages = [{
"role": "user",
"content": [
{"type": "text", "text": "第一张图"},
{
"type": "image_url",
"image_url": {"url": "examples/images/image_1.jpeg"},
},
{"type": "text", "text": "有什么内容?"},
],
}]
prompt, media = encode_messages(
messages,
thinking_mode="chat",
return_multi_modal_data=True,
)
# prompt:
# '<|begin▁of▁sentence|><|User|>第一张图\n\n<|deepseek_image|>\n\n有什么内容?<|Assistant|></think>'
# media["images"] contains the image records in prompt order
```
Images are represented in the prompt by `<|deepseek_image|>`. `media["images"]`
contains the corresponding image records in exactly the same order they appear in
the prompt. Pixel loading and expansion into model image tokens are handled by
`inference/image_processor.py`.
## Compact TXT notation
`parse_tagged_text()` converts a compact prompt such as
```text
第一张图<image>examples/images/image_1.jpeg</image>有什么内容?
```
into the same standard content blocks. It is an input convenience layer, not a
second encoding implementation.
## Message format
### Special tokens
| Token | Purpose |
| :--- | :--- |
| `<|begin▁of▁sentence|>` | Beginning of sequence (BOS) |
| `<|end▁of▁sentence|>` | End of assistant turn (EOS) |
| `<|User|>` | User turn prefix |
| `<|Assistant|>` | Assistant turn prefix |
| `<|System|>` | Mid-conversation system message prefix |
| `<|latest_reminder|>` | Latest reminder (date, locale, etc.) |
| `<think>` / `</think>` | Reasoning block delimiters |
| `|DSML|` | DSML markup token |
| `<|deepseek_image|>` | Image placeholder in the prompt string |
### Roles
The encoding supports the following message roles: `system`, `user`, `assistant`,
`tool`, and `latest_reminder`.
A `tool` message is not rendered directly: `merge_tool_messages()` converts it
into a `<tool_result>` block inside the preceding user message. When multiple
tool results are present, they are sorted by the order of the corresponding
`tool_calls` in the preceding assistant message.
### Basic chat
A simple multi-turn conversation is encoded as:
```
<|begin▁of▁sentence|>{system_prompt}
<|User|>{user_message}<|Assistant|></think>{response}<|end▁of▁sentence|>
<|User|>{user_message_2}<|Assistant|></think>{response_2}<|end▁of▁sentence|>
```
- The BOS token is prepended at the very beginning of the conversation.
- In **chat mode** (`thinking_mode="chat"`), `</think>` is placed right after
`<|Assistant|>` to immediately close the thinking block, so the model generates
content directly.
### Thinking mode
In **thinking mode** (`thinking_mode="thinking"`), the model produces explicit
reasoning inside `<think>...</think>` blocks before responding.
```
<|begin▁of▁sentence|><|System|>{reasoning_effort_prefix}{system_prompt}
<|User|>{message}<|Assistant|><think>{reasoning}</think>{response}<|end▁of▁sentence|>
```
The reasoning effort prefix is injected once, before the system message, as a
`<|System|>` block:
```
<|System|>Reasoning Effort: {budget} (range 1-100, the higher the value, the more thorough the reasoning)
```
The `drop_thinking` parameter (default `True`) controls whether reasoning from
earlier turns is preserved:
- **Without tools**: reasoning content from assistant turns **before** the last
user message is stripped. Only the final assistant turn retains its
`<think>...</think>` block.
- **With tools**: `drop_thinking` is automatically disabled. All turns retain
their reasoning, because tool-calling conversations require full context for
the model to track multi-step reasoning across tool calls.
### Tool calling (DSML format)
Tools are defined on the `system` message via the `tools` field
(OpenAI-compatible format). When tools are present, the following schema block is
injected into the system prompt:
```
## Tools
You 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:
<|DSML| calls>
<|DSML| invoke name="$TOOL_NAME">
<|DSML| parameter name="$PARAMETER_NAME" string="true|false">$PARAMETER_VALUE</|DSML| parameter>
...
</|DSML| invoke>
<|DSML| invoke name="$TOOL_NAME2">
...
</|DSML| invoke>
</|DSML| calls>
String 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"`.
If thinking_mode is enabled (triggered by <think>), you MUST output your complete reasoning inside <think>...</think> BEFORE any tool calls or final response.
Otherwise, output directly after </think> with tool calls or final response.
### Available Tool Schemas
{tool_definitions_json}
You MUST strictly follow the above defined tool name and parameter schemas to invoke tool calls.
```
An actual tool call in the assistant turn looks like:
```xml
<|DSML| calls>
<|DSML| invoke name="function_name">
<|DSML| parameter name="param" string="true">string_value</|DSML| parameter>
<|DSML| parameter name="count" string="false">5</|DSML| parameter>
</|DSML| invoke>
</|DSML| calls><|end▁of▁sentence|>
```
- `string="true"`: the parameter value is a raw string.
- `string="false"`: the parameter value is JSON (number, boolean, array, object).
Tool execution results are wrapped in `<tool_result>` tags within user messages:
```
<|User|><tool_result>{result_json}</tool_result><|Assistant|><think>...
```
### Tool namespaces
Tool definitions may include a `namespace` alongside `function`, either as a
string or as an object with `name` and an optional `description`:
```python
tool = {
"type": "function",
"namespace": {"name": "search", "description": "Search tools."},
"function": {
"name": "lookup",
"description": "Look up a value",
"parameters": {"type": "object", "properties": {"query": {"type": "string"}}},
},
}
tool_call = {
"type": "function",
"namespace": "search",
"function": {"name": "lookup", "arguments": '{"query": "value"}'},
}
```
The tool schema and DSML invocation both use `search::lookup`. The namespace
description is prepended to the tool description, separated by a newline.
The parser returns `function.name="lookup"` and `namespace="search"` on the
tool call, so its output can be passed back to `encode_messages()` directly.
Input also accepts `namespace` inside `function`, or a qualified function name
such as `search::lookup`. A qualified name must agree with any explicit
namespace; `::` separates exactly one namespace from the tool name. Tools
without a namespace retain their original names and output format.
### Reasoning effort
Pass `reasoning_effort` as an integer in `[1, 100]` or as one of `"low"` (50),
`"high"` (75), or `"max"` (100). The default is `"high"` (75).
The setting only affects `thinking_mode="thinking"` and is only rendered at the
start of the conversation (index 0). Intermediate values may be used to elicit
interpolated reasoning behavior.
### Quick instruction special tokens
Quick instruction tokens are used for auxiliary classification and generation
tasks. They are appended to messages via the `"task"` field to trigger
specialized model behavior for a single-token or short-form output.
| Special Token | Description | Format |
|:---|:---|:---|
| `<|action|>` | Determines whether the user prompt requires a web search or can be answered directly. | `...<|User|>{prompt}<|Assistant|><think><|action|>` |
| `<|title|>` | Generates a concise conversation title after the first assistant response. | `...<|Assistant|>{response}<|end▁of▁sentence|><|title|>` |
| `<|query|>` | Generates search queries for the user prompt. | `...<|User|>{prompt}<|query|>` |
| `<|authority|>` | Classifies the user prompt's demand for source authoritativeness. | `...<|User|>{prompt}<|authority|>` |
| `<|domain|>` | Identifies the domain of the user prompt. | `...<|User|>{prompt}<|domain|>` |
| `<|read_url|>` | Determines whether each URL in the user prompt should be fetched and read. | `...<|User|>{prompt}<|read_url|>` |
Usage in message format:
- **`action`** on a user message: the `<|action|>` token is placed after the
assistant prefix and thinking token, triggering a routing decision (e.g.,
"Search" or "Answer").
- **Other tasks** (`query`, `authority`, `domain`, `read_url`) on a user message:
the task token is appended directly after the user content.
- **`title`** on an assistant message: the `<|title|>` token is appended after
the assistant's EOS. The next assistant message provides the generated title.
## Tests
From this directory:
```bash
python -m pytest -q test_encoding.py
```
Test cases are stored as paired JSON input / TXT expected-output files under
`tests/`. The tests cover multi-turn conversations, tool calling, thinking mode,
numeric reasoning effort, mid-conversation system messages, and multimodal image
ordering. They include a check that the TXT and JSON examples encode to the same
prompt and preserve the same image ordering.