Session Prompt 核心机制解析
2026/4/27大约 3 分钟
Session Prompt 核心机制解析
时间: 2026-03-06
相关文件: packages/opencode/src/session/prompt.ts, packages/opencode/src/session/message-v2.ts
本文档记录了关于 session/prompt.ts 核心调度流程以及数据结构的详细问答与原理解析。
1. system 与 format 参数的区别
问题:
在 PromptInput 中,system 返回 string 类型很好理解(系统指令),但 format: MessageV2.Format.optional() 代表什么含义?
解析:
system(系统提示词):是给模型的建议和约束(例如:“你是一个专业的前端开发”)。它决定了模型“怎么想”和“扮演什么角色”。format(输出格式协议):是对大模型返回结果的强校验模具。它不仅仅是文本提示,而是一个底层约束:- 在
MessageV2.Format中,它被定义为一个辨别联合类型(discriminated union)。 - text 模式:默认模式,允许模型自由输出普通对话文本。
- json_schema 模式:如果传入了具体的 JSON Schema,
prompt.ts底层会触发一个特殊的拦截机制(调用内部的createStructuredOutputTool)。这相当于给模型塞了一个“只能接收该 JSON 结构”的强制工具,通过 tool calls 的机制强迫模型把答案严丝合缝地填入你指定的 JSON 字段中返回,便于程序反序列化读取。
- 在
总结: system 控制的是模型的意图与背景音,而 format 则在接口层面强制约束了模型的最终交差形态。
2. prompt 流程与“跨天持久化对话”场景
问题:export const prompt 这套复杂的流程,对应的场景是不是在已经对话过的 session 中继续对话?比如中间可能已经隔了一天?
解析:
完全正确。prompt 函数处理的核心就是“带记忆的持续对话(Stateful Session)”。
无论你上一条消息是刚才发的,还是昨天甚至几天前发的,针对底层调度逻辑来说是一致的,系统会通过以下几个步骤抹平时间差:
- Session 唤醒与状态锁 (
start):- 当传入一个已有的
sessionID时,流程最开始会调用start(input.sessionID)。 - 第一,它从数据库中唤醒这个 Session 的元数据(当时选用的模型、绑定的 Agent 等)。
- 第二,它建立了一个生命周期内存锁(Mutex Lock)。防止同一个 Session 在同一时刻被频繁操作而导致状态覆写。
- 当传入一个已有的
- 全量历史记录重载 (
history):- 进入核心事件循环
loop之后,processor会基于查出来的 ID,把数据库中留存的历史User、Assistant、甚至之前执行的各种工具Tool记录全部平铺读取出来。
- 进入核心事件循环
- 上下文无缝包裹:
- 对大语言模型 (LLM) 而言,并没有物理的时间流逝概念,它只认你喂给它的上下文。只要系统把昨日的旧梦跟今天的新问题重新打包送发,模型就能完美接续。
- 长历史过载的保护盾 (
SessionCompaction):- 连续跨越多天的密集聊天,其 Token 数量很容易突破 LLM 限定的上下文窗口。
- 在
loop中有一套防御机制预处理分支:如果判定历史数组体积过载,会自动触发记忆压缩(Compaction)。它会召唤一个轻量模型或者走特定的总结流程,将昨天的长篇大论浓缩成几行摘要背景,既保留了因果关联,又释放了 Token 负担。