Documentation Index Fetch the complete documentation index at: https://simplellmfunc.cn/llms.txt
Use this file to discover all available pages before exploring further.
编译管道
编译管道将 invocation 配置、基础对话记录和待处理的运行时补丁转换为发送给 LLM 提供商的最终消息。这是一个两阶段的过程,对话记录补丁应用与请求渲染之间有着清晰的边界。
两个阶段
compile_invocation_turn(spec, transcript, pending_mutations, selfref_snapshot)
│
├─► 阶段 1:reduce_turn_context(transcript, mutations, selfref_snapshot)
│ • 将所有待处理的运行时补丁应用到对话记录
│ • 如检测到标记,刷新 selfref 快照
│ • 克隆结果(无共享引用)
│ → 返回:ReducedTurnContext
│
└─► 阶段 2:convert_to_llm_request(reduced, prompt_contract)
• 解析系统提示词(selfref > 显式设置 > 对话记录 > docstring)
• 在对话记录中放置/替换系统消息
• 渲染最终消息(注入工具规格、must_principles)
→ 返回:CompiledTurnContext
阶段 1:归约轮次上下文
reduce_turn_context 接收当前基础对话记录和所有待处理的运行时补丁,输出一份干净的、已应用补丁的对话记录。
def reduce_turn_context (
transcript : NormalizedMessageList,
pending_mutations : List[ContextMutation],
selfref_snapshot : Optional[DataFromSelfRef] = None ,
) -> ReducedTurnContext:
处理过程:
应用运行时补丁 — apply_mutations(transcript, pending_mutations) 按顺序处理每个 mutation:
AssistantMessageMutation → 追加助手消息
ToolResultMutation → 追加工具结果
ContextReplaceMutation → 替换整个列表
ContextSummaryMutation → 替换为摘要,存储经验
ExperienceRemember/Forget → 累积后在下一个非经验 mutation 之前批量提交
等等
刷新 selfref 快照 — 如果 mutation 应用后的对话记录包含 selfref 标记(经验、摘要),则从对话内容重新解析 DataFromSelfRef。这确保快照反映的是刚刚应用的压缩或经验 mutation 的结果。
克隆 — 结果是深拷贝,不存在共享状态的修改。
输出:
@dataclass
class ReducedTurnContext :
transcript: NormalizedMessageList # Mutation-applied, cloned
selfref_snapshot: Optional[DataFromSelfRef] # Refreshed if needed
阶段 2:转换为 LLM 请求
convert_to_llm_request 接收归约后的对话记录和 invocation 的 prompt contract,生成发送给提供商的最终消息。
def convert_to_llm_request (
reduced : ReducedTurnContext,
prompt_contract : PromptContract,
) -> CompiledTurnContext:
处理过程:
解析系统提示词 — 优先级顺序:
如果 selfref_snapshot 存在 → 渲染基础提示词 + 经验块
否则如果 prompt_contract.system_prompt 已设置 → 直接使用
否则如果对话记录中有系统消息 → 提取其内容
否则如果 prompt_contract.base_instruction 存在 → 使用 docstring 兜底
放置系统消息 — 替换对话记录中已有的系统消息,或在开头插入新的系统消息。如果没有解析到系统提示词,则移除已有的系统消息。
渲染 LLM 消息 — render_llm_input_messages() 完成消息的最终处理:
如果挂载了工具,在开头注入 <tool_best_practices> 块
如果需要,追加 <must_principles> 块(指示模型使用原生工具调用)
返回可直接发送给提供商的最终消息列表
输出:
@dataclass
class CompiledTurnContext :
transcript: NormalizedMessageList # The transcript after system prompt resolution
system_prompt: Optional[ str ] # The resolved system prompt text
llm_messages: NormalizedMessageList # Final messages for the provider
selfref_snapshot: Optional[DataFromSelfRef] # Carried forward
在 ReAct 循环中的位置
# Simplified ReAct loop structure
while has_more_work:
# 1. Collect mutations from hooks
hook_mutations = collect_hook_mutations(state)
# 2. Compile context (Stage 1 only — apply mutations)
compiled_context = compile_context(state, hook_mutations + pending)
# 3. Compile for LLM (Stage 1 + Stage 2 — full pipeline)
turn = compile_invocation_turn(spec, compiled_context.messages, [], selfref)
# 4. Send to LLM
llm_result = execute_single_llm_phase(turn.llm_messages, ... )
# 5. Execute tools if needed
tool_result = schedule_tool_batch(llm_result.tool_calls, ... )
# 6. Collect all new mutations for next iteration
pending = llm_result.mutations + tool_result.mutations
每次迭代都经过完整的管道。Runtime 副作用不会“直接追加到 live list”,而是产生补丁并在边界应用。这保证了即使经过 50 次工具调用,对话记录状态依然一致且可审计。
唯一入口点
所有编译流程都经过同一个函数:
def compile_invocation_turn (
spec : InvocationSpec,
transcript : NormalizedMessageList,
pending_mutations : Optional[List[ContextMutation]] = None ,
selfref_snapshot : Optional[DataFromSelfRef] = None ,
) -> CompiledTurnContext:
@llm_function 和 @llm_chat 使用相同的入口点。不同的装饰器模式不存在独立的编译路径。
为什么分两个阶段?
这种拆分带来以下优势:
单独使用阶段 1 用于内部状态管理(例如 ReAct 循环中的 compile_context 更新状态而不渲染给 LLM)
阶段 2 仅在实际调用 LLM 时添加提供商相关的渲染(工具注入、系统提示词放置)
测试 — 可以独立测试 mutation 应用和提示词渲染
SelfRef 刷新 — 发生在两个阶段之间,确保快照在提示词解析之前是最新的
实际意义
对大多数用户来说,这些都是不可见的。你写函数、传 history、挂载工具、消费事件即可。
但当你需要调试内部行为:
调试对话记录问题 → 检查产生了哪些运行时补丁、以什么顺序
理解系统提示词行为 → 了解阶段 2 中的优先级顺序
构建框架扩展 → 使用编译边界,而不是直接修改 live messages
重要区别:mutation 是内部对话记录补丁。它不是 docstring、模板参数、工具 schema 或初始 history 的来源。
下一节:SelfRef 自引用 持久上下文(经验、压缩、分叉)如何通过 SelfReference 系统工作。