Refactor reference selection and simplify AI prompts
This commit is contained in:
1 parent
95079f6c4e
commit
b5656a75ff
6 files changed
+304
-295
No files matched your search
@@ -1,33 +1,63 @@
|
||||
import {
|
||||
buildDirectorPromptUserContext,
|
||||
type IntentPromptInput,
|
||||
JSON_ONLY_INTENT_CONTRACT
|
||||
} from './shared'
|
||||
import { renderLineList } from '../../utils/render'
|
||||
|
||||
export const buildIntentSystemPrompt = (): string =>
|
||||
[
|
||||
'【角色】你是请求分流决策器。',
|
||||
'【目标】在 need_context / to_plan / direct_human 三者中选择唯一模式。',
|
||||
'【背景】你只能依据当前输入字段判断,不得使用未提供信息。',
|
||||
'【流程】先判断信息是否不足,再判断是否需要本地工具执行,最后给出结构化决策。',
|
||||
'【范围】若用户已显式选择参考资料,默认视为优先参考范围;涉及本地资料时优先走本地能力,不要忽略这些选择。',
|
||||
'【约束】不得编造上下文;reason 必须说明判定依据。',
|
||||
'【输出】',
|
||||
JSON_ONLY_INTENT_CONTRACT,
|
||||
'【样例-正】当用户请求“请把 A 文档改成模板并保存”且需要多个业务动作时,输出 mode=to_plan。',
|
||||
'【样例-正】当用户请求“总结这篇文章并按要求输出”且单个 human 可闭环完成时,输出 mode=direct_human。',
|
||||
'【样例-正】当用户问“继续刚才第二步”但缺少指代信息时,输出 mode=need_context。',
|
||||
'【样例-反】不要输出“我觉得应该先查一下”这类自然语言。'
|
||||
].join('\n')
|
||||
|
||||
export const buildIntentUserPrompt = (input: IntentPromptInput): string => {
|
||||
const contextEvidenceText = renderLineList(input.contextEvidence, {
|
||||
fallback: '(none)',
|
||||
style: 'plain'
|
||||
})
|
||||
|
||||
return `
|
||||
<user_context>
|
||||
<user_input>
|
||||
${input.userInput}
|
||||
</user_input>
|
||||
|
||||
<session_summary>
|
||||
${input.sessionSummaryText}
|
||||
</session_summary>
|
||||
|
||||
<recent_turns>
|
||||
${input.recentTurnsText}
|
||||
</recent_turns>
|
||||
|
||||
<selected_context>
|
||||
${input.selectedContextText}
|
||||
</selected_context>
|
||||
|
||||
<context_evidence>
|
||||
${contextEvidenceText}
|
||||
</context_evidence>
|
||||
|
||||
<context_rounds>
|
||||
${input.contextRounds}/${input.maxContextRounds}
|
||||
</context_rounds>
|
||||
</user_context>
|
||||
`.trim()
|
||||
}
|
||||
|
||||
export const buildIntentPrompt = (input: IntentPromptInput) => {
|
||||
return {
|
||||
system: [
|
||||
'【角色】你是请求分流决策器。',
|
||||
'【目标】在 need_context / to_plan / direct_human 三者中选择唯一模式。',
|
||||
'【背景】你只能依据当前输入字段判断,不得使用未提供信息。',
|
||||
'【流程】先判断信息是否不足,再判断是否需要本地工具执行,最后给出结构化决策。',
|
||||
'【范围】若用户已显式选择参考资料,默认视为优先参考范围;涉及本地资料时优先走本地能力,不要忽略这些选择。',
|
||||
'【约束】不得编造上下文;reason 必须说明判定依据。',
|
||||
'【输出】',
|
||||
JSON_ONLY_INTENT_CONTRACT,
|
||||
'【样例-正】当用户请求“请把 A 文档改成模板并保存”且需要多个业务动作时,输出 mode=to_plan。',
|
||||
'【样例-正】当用户请求“总结这篇文章并按要求输出”且单个 human 可闭环完成时,输出 mode=direct_human。',
|
||||
'【样例-正】当用户问“继续刚才第二步”但缺少指代信息时,输出 mode=need_context。',
|
||||
'【样例-反】不要输出“我觉得应该先查一下”这类自然语言。'
|
||||
].join('\n'),
|
||||
user: buildDirectorPromptUserContext({
|
||||
...input,
|
||||
extraSections: [
|
||||
{
|
||||
label: '当前 context rounds',
|
||||
value: `${input.contextRounds}/${input.maxContextRounds}`
|
||||
}
|
||||
]
|
||||
})
|
||||
system: buildIntentSystemPrompt(),
|
||||
user: buildIntentUserPrompt(input)
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,58 @@
|
||||
import {
|
||||
buildDirectorPromptUserContext,
|
||||
type PlanPromptInput,
|
||||
JSON_ONLY_PLAN_CONTRACT
|
||||
} from './shared'
|
||||
import { renderLineList } from '../../utils/render'
|
||||
|
||||
export const buildPlanSystemPrompt = (): string =>
|
||||
[
|
||||
'【角色】你是任务规划器。',
|
||||
'【目标】把用户请求拆成可独立执行的任务列表。',
|
||||
'【背景】执行层是本地工具执行模式,典型能力包括知识库检索、终端执行、docx 处理。',
|
||||
'【运行时约束】最终总结由 runtime 自动追加 synthesis human 负责,不要把“总结答复”写成计划中的业务任务。',
|
||||
'【范围】若已显式选择参考资料,任务规划必须优先围绕这些本地选择取证;不要默认扩大到未选中的本地资料。',
|
||||
'【流程】先识别最终交付物,再拆分最小可行任务,最后检查任务是否可执行可验证。',
|
||||
'【约束】每个 userInput 必须包含“动作 + 对象 + 完成判据”;禁止空泛任务。',
|
||||
'【输出】',
|
||||
JSON_ONLY_PLAN_CONTRACT,
|
||||
'【样例-正】userInput: "读取 /docs/a.docx,提取行动项并输出 owner/due_date/task 字段"。',
|
||||
'【样例-反】userInput: "继续优化文档质量"。'
|
||||
].join('\n')
|
||||
|
||||
export const buildPlanUserPrompt = (input: PlanPromptInput): string => {
|
||||
const contextEvidenceText = renderLineList(input.contextEvidence, {
|
||||
fallback: '(none)',
|
||||
style: 'plain'
|
||||
})
|
||||
|
||||
return `
|
||||
<user_context>
|
||||
<user_input>
|
||||
${input.userInput}
|
||||
</user_input>
|
||||
|
||||
<session_summary>
|
||||
${input.sessionSummaryText}
|
||||
</session_summary>
|
||||
|
||||
<recent_turns>
|
||||
${input.recentTurnsText}
|
||||
</recent_turns>
|
||||
|
||||
<selected_context>
|
||||
${input.selectedContextText}
|
||||
</selected_context>
|
||||
|
||||
<context_evidence>
|
||||
${contextEvidenceText}
|
||||
</context_evidence>
|
||||
</user_context>
|
||||
`.trim()
|
||||
}
|
||||
|
||||
export const buildPlanPrompt = (input: PlanPromptInput) => {
|
||||
return {
|
||||
system: [
|
||||
'【角色】你是任务规划器。',
|
||||
'【目标】把用户请求拆成可独立执行的任务列表。',
|
||||
'【背景】执行层是本地工具执行模式,典型能力包括知识库检索、终端执行、docx 处理。',
|
||||
'【运行时约束】最终总结由 runtime 自动追加 synthesis human 负责,不要把“总结答复”写成计划中的业务任务。',
|
||||
'【范围】若已显式选择参考资料,任务规划必须优先围绕这些本地选择取证;不要默认扩大到未选中的本地资料。',
|
||||
'【流程】先识别最终交付物,再拆分最小可行任务,最后检查任务是否可执行可验证。',
|
||||
'【约束】每个 userInput 必须包含“动作 + 对象 + 完成判据”;禁止空泛任务。',
|
||||
'【输出】',
|
||||
JSON_ONLY_PLAN_CONTRACT,
|
||||
'【样例-正】userInput: "读取 /docs/a.docx,提取行动项并输出 owner/due_date/task 字段"。',
|
||||
'【样例-反】userInput: "继续优化文档质量"。'
|
||||
].join('\n'),
|
||||
user: buildDirectorPromptUserContext(input)
|
||||
system: buildPlanSystemPrompt(),
|
||||
user: buildPlanUserPrompt(input)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import { renderLineList, renderNamedSections } from '../../utils/render'
|
||||
|
||||
export const JSON_ONLY_INTENT_CONTRACT = [
|
||||
'只输出 JSON,不得输出任何额外文字。',
|
||||
'格式:{"mode":"need_context|to_plan|direct_human","reason":"string"}。',
|
||||
@@ -26,29 +24,3 @@ export type IntentPromptInput = DirectorPromptSharedInput & {
|
||||
}
|
||||
|
||||
export type PlanPromptInput = DirectorPromptSharedInput
|
||||
|
||||
export const buildDirectorPromptUserContext = (
|
||||
input: DirectorPromptSharedInput & {
|
||||
extraSections?: Array<{ label: string; value: string }>
|
||||
}
|
||||
) =>
|
||||
renderNamedSections(
|
||||
[
|
||||
{ label: '用户输入', value: input.userInput },
|
||||
{ label: '会话摘要', value: input.sessionSummaryText },
|
||||
{ label: '最近对话', value: input.recentTurnsText },
|
||||
{ label: '用户选择的参考资料', value: input.selectedContextText },
|
||||
{
|
||||
label: '上下文证据',
|
||||
value: renderLineList(input.contextEvidence, {
|
||||
fallback: '(none)',
|
||||
style: 'plain'
|
||||
})
|
||||
},
|
||||
...(input.extraSections || [])
|
||||
],
|
||||
{
|
||||
fallback: '(none)',
|
||||
style: 'plain'
|
||||
}
|
||||
)
|
||||
@@ -1,6 +1,13 @@
|
||||
import type { AiRunContext } from '../../types'
|
||||
import type { HumanState } from '../types'
|
||||
import { buildBrainPromptSections } from './brainContextSections'
|
||||
import { renderLineList } from '../../utils/render'
|
||||
import { getSkillDefinition } from '../skills'
|
||||
import {
|
||||
renderHumanEvidenceLines,
|
||||
renderHumanFactLines,
|
||||
renderHumanOpenQuestionLines
|
||||
} from '../shared/memoryRenderers'
|
||||
import { getToolPromptSpec } from '../tools/registry'
|
||||
import type { HumanState, ToolPromptSpec } from '../types'
|
||||
|
||||
type HumanBrainPromptInput = {
|
||||
userInput: string
|
||||
@@ -12,27 +19,150 @@ type HumanBrainPromptInput = {
|
||||
watchHintText: string
|
||||
}
|
||||
|
||||
export const buildBrainPromptContext = (input: { state: HumanState; ctx: AiRunContext }) => {
|
||||
const sections = buildBrainPromptSections(input)
|
||||
|
||||
return buildHumanBrainPrompt({
|
||||
userInput: input.state.task.userInput,
|
||||
memorySnapshotText: sections.memorySnapshotText,
|
||||
selectedContextText: sections.selectedContextText,
|
||||
skillContextText: sections.skillContextText,
|
||||
recentToolResultsText: sections.recentToolResultsText,
|
||||
recentDecisionHistoryText: sections.recentDecisionHistoryText,
|
||||
watchHintText: [
|
||||
'如果这里是 none,表示当前没有额外的收敛提醒;否则应优先考虑结束任务或纠偏。',
|
||||
'',
|
||||
input.state.watchHint || 'none'
|
||||
].join('\n')
|
||||
const formatPlainList = (items: string[]): string =>
|
||||
renderLineList(items, {
|
||||
fallback: 'none',
|
||||
style: 'plain'
|
||||
})
|
||||
|
||||
const renderLearnedToolSpecLine = (spec: ToolPromptSpec): string => {
|
||||
const requiredArgs = spec.args
|
||||
.filter((arg) => arg.required)
|
||||
.map((arg) => `${arg.name}:${arg.type}`)
|
||||
.join(', ')
|
||||
const example = spec.examples?.[0]
|
||||
? `示例目标=${spec.examples[0].goal};示例参数键=[${Object.keys(spec.examples[0].args).join(', ') || 'none'}]`
|
||||
: '示例=none'
|
||||
|
||||
return `- 工具 ${spec.name}:适用场景=${spec.whenToUse};必填参数=[${requiredArgs || 'none'}];${example}`
|
||||
}
|
||||
|
||||
export const buildHumanBrainPrompt = (input: HumanBrainPromptInput) => {
|
||||
return {
|
||||
system: `
|
||||
const buildRecentToolResultLine = (
|
||||
result: NonNullable<HumanState['lastParallelCallToolResults']>[number],
|
||||
index: number
|
||||
): string => {
|
||||
const diagnosticText = result.diagnostic
|
||||
? `;diagnostic=${result.diagnostic.kind}${result.diagnostic.missingArgs?.length ? `;missingArgs=[${result.diagnostic.missingArgs.join(', ')}]` : ''}`
|
||||
: ''
|
||||
return `- 第${index + 1}项:工具 ${result.toolName} ${result.ok ? '执行成功' : '执行失败'}(code=${result.code});摘要:${result.summary}${diagnosticText}`
|
||||
}
|
||||
|
||||
const buildMemorySnapshotText = (state: HumanState): string =>
|
||||
[
|
||||
'下面是你之前沉淀下来的记忆。这些内容代表当前已经确认、可以直接复用或仍影响推进的信息。',
|
||||
'',
|
||||
'已确认的事实:',
|
||||
renderHumanFactLines(state, 'brain_prompt'),
|
||||
'',
|
||||
'支撑这些事实的关键证据:',
|
||||
renderHumanEvidenceLines(state, 'brain_prompt'),
|
||||
'',
|
||||
'仍未解决的问题:',
|
||||
renderHumanOpenQuestionLines(state, 'brain_prompt')
|
||||
].join('\n')
|
||||
|
||||
const buildSelectedContextPromptText = (ctx: AiRunContext): string =>
|
||||
[
|
||||
'下面是当前用户明确给出的参考资料上下文。后续判断、检索和文件定位都必须先对齐这段信息。',
|
||||
'',
|
||||
ctx.selectedContextText
|
||||
].join('\n')
|
||||
|
||||
const buildSkillContextText = (state: HumanState): string => {
|
||||
const learnedSkillIds = state.brainMemory.outside.learnedSkillIds
|
||||
const learnedSkillDefinitions = learnedSkillIds.map((skillId) => getSkillDefinition(skillId))
|
||||
const learnedToolNames = Array.from(
|
||||
new Set(learnedSkillDefinitions.flatMap((definition) => definition.toolNames))
|
||||
)
|
||||
const learnedToolSpecLines =
|
||||
learnedToolNames.length > 0
|
||||
? learnedToolNames
|
||||
.map((toolName) => getToolPromptSpec(toolName))
|
||||
.filter((spec): spec is ToolPromptSpec => Boolean(spec))
|
||||
.map(renderLearnedToolSpecLine)
|
||||
: ['none']
|
||||
|
||||
const skillCatalogLines =
|
||||
state.brainMemory.outside.skillCatalog.length > 0
|
||||
? state.brainMemory.outside.skillCatalog.map(
|
||||
(item) =>
|
||||
`- ${item.skillId}:${item.summary};可提供工具=[${item.toolNames.join(', ')}];适用场景=${item.whenToUse}`
|
||||
)
|
||||
: ['none']
|
||||
|
||||
const learnedSkillIdLines =
|
||||
learnedSkillIds.length > 0 ? learnedSkillIds.map((skillId) => `- ${skillId}`) : ['none']
|
||||
|
||||
const learnedSkillDetailLines =
|
||||
learnedSkillDefinitions.length > 0
|
||||
? learnedSkillDefinitions.map((definition) => `- ${definition.skillId}:${definition.detail}`)
|
||||
: ['none']
|
||||
|
||||
return [
|
||||
'下面是当前可用的技能信息。技能目录摘要只用于判断要不要学习;只有已学习 skill 的详细说明和工具要点,才代表你当前可以直接依赖的能力。',
|
||||
'',
|
||||
'当前可用技能目录摘要:',
|
||||
formatPlainList(skillCatalogLines),
|
||||
'',
|
||||
'已经学习的 skill id:',
|
||||
formatPlainList(learnedSkillIdLines),
|
||||
'',
|
||||
'已学习技能的详细说明:',
|
||||
formatPlainList(learnedSkillDetailLines),
|
||||
'',
|
||||
'已学习技能对应的工具使用要点:',
|
||||
formatPlainList(learnedToolSpecLines)
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
const buildRecentToolResultsText = (state: HumanState): string =>
|
||||
[
|
||||
'下面是最近一轮工具调用刚带回来的新信息。请把这些结果和已有记忆一起判断,不要重复做同样的动作。',
|
||||
'',
|
||||
renderLineList(
|
||||
(state.lastParallelCallToolResults || []).map((result, index) =>
|
||||
buildRecentToolResultLine(result, index)
|
||||
),
|
||||
{
|
||||
fallback: 'none',
|
||||
style: 'plain'
|
||||
}
|
||||
)
|
||||
].join('\n')
|
||||
|
||||
const buildRecentDecisionHistoryText = (state: HumanState): string =>
|
||||
[
|
||||
'下面是最近几轮已经做过的正式判断摘要,只用于帮助你理解时间顺序并避免重复决策。',
|
||||
'',
|
||||
renderLineList(
|
||||
state.brainMemory.outside.brainDecisions.map((record, index) => {
|
||||
const ordinal = index + 1
|
||||
const action = record.nextAction.action
|
||||
const nextActionPayload =
|
||||
action === 'learning'
|
||||
? `wantLearnSkillIds=[${record.nextAction.wantLearnSkillIds.join(',')}]`
|
||||
: action === 'hand'
|
||||
? `parallelCallToolParam=${JSON.stringify(record.nextAction.parallelCallToolParam)}`
|
||||
: 'final_delivery=true'
|
||||
|
||||
return `- 第${ordinal}轮(createdAt=${record.createdAt}):决定“${record.decision.summary}”;原因:${record.decision.reason};预期结果:${record.decision.expectedOutcome};nextAction.action=${action};nextAction数据:${nextActionPayload}`
|
||||
}),
|
||||
{
|
||||
fallback: 'none',
|
||||
style: 'plain'
|
||||
}
|
||||
)
|
||||
].join('\n')
|
||||
|
||||
const buildWatchHintText = (state: HumanState): string =>
|
||||
[
|
||||
'如果这里是 none,表示当前没有额外的收敛提醒;否则应优先考虑结束任务或纠偏。',
|
||||
'',
|
||||
state.watchHint || 'none'
|
||||
].join('\n')
|
||||
|
||||
export const buildBrainSystemPrompt = (): string =>
|
||||
`
|
||||
<system>
|
||||
<role>
|
||||
你现在扮演一个负责分析情况、整理记忆、做出下一步判断的大脑角色。
|
||||
@@ -206,8 +336,10 @@ export const buildHumanBrainPrompt = (input: HumanBrainPromptInput) => {
|
||||
</example_mouth>
|
||||
</output_examples>
|
||||
</system>
|
||||
`.trim(),
|
||||
user: `
|
||||
`.trim()
|
||||
|
||||
export const buildBrainUserPrompt = (input: HumanBrainPromptInput): string =>
|
||||
`
|
||||
<user_context>
|
||||
<user_request>
|
||||
${input.userInput}
|
||||
@@ -238,5 +370,22 @@ ${input.watchHintText}
|
||||
</converge_hint>
|
||||
</user_context>
|
||||
`.trim()
|
||||
|
||||
export const buildBrainPromptContext = (input: { state: HumanState; ctx: AiRunContext }) => {
|
||||
return buildHumanBrainPrompt({
|
||||
userInput: input.state.task.userInput,
|
||||
memorySnapshotText: buildMemorySnapshotText(input.state),
|
||||
selectedContextText: buildSelectedContextPromptText(input.ctx),
|
||||
skillContextText: buildSkillContextText(input.state),
|
||||
recentToolResultsText: buildRecentToolResultsText(input.state),
|
||||
recentDecisionHistoryText: buildRecentDecisionHistoryText(input.state),
|
||||
watchHintText: buildWatchHintText(input.state)
|
||||
})
|
||||
}
|
||||
|
||||
export const buildHumanBrainPrompt = (input: HumanBrainPromptInput) => {
|
||||
return {
|
||||
system: buildBrainSystemPrompt(),
|
||||
user: buildBrainUserPrompt(input)
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
import type { AiRunContext } from '../../types'
|
||||
import type { HumanState, ToolPromptSpec } from '../types'
|
||||
import { getSkillDefinition } from '../skills'
|
||||
import { getToolPromptSpec } from '../tools/registry'
|
||||
import { renderLineList } from '../../utils/render'
|
||||
import {
|
||||
renderHumanEvidenceLines,
|
||||
renderHumanFactLines,
|
||||
renderHumanOpenQuestionLines
|
||||
} from '../shared/memoryRenderers'
|
||||
|
||||
const formatList = (items: string[]): string =>
|
||||
renderLineList(items, {
|
||||
fallback: 'none',
|
||||
style: 'plain'
|
||||
})
|
||||
|
||||
type BrainPromptRenderView = {
|
||||
factLines: string
|
||||
evidenceLines: string
|
||||
openQuestionLines: string
|
||||
selectedContextText: string
|
||||
skillCatalogLines: string[]
|
||||
learnedSkillIdLines: string[]
|
||||
learnedSkillDetailLines: string[]
|
||||
learnedToolSpecLines: string[]
|
||||
recentToolResultLines: string
|
||||
recentDecisionHistoryLines: string
|
||||
}
|
||||
|
||||
export type BrainPromptSections = {
|
||||
memorySnapshotText: string
|
||||
selectedContextText: string
|
||||
skillContextText: string
|
||||
recentToolResultsText: string
|
||||
recentDecisionHistoryText: string
|
||||
}
|
||||
|
||||
const renderLearnedToolSpecLine = (spec: ToolPromptSpec): string => {
|
||||
const requiredArgs = spec.args
|
||||
.filter((arg) => arg.required)
|
||||
.map((arg) => `${arg.name}:${arg.type}`)
|
||||
.join(', ')
|
||||
const example = spec.examples?.[0]
|
||||
? `示例目标=${spec.examples[0].goal};示例参数键=[${Object.keys(spec.examples[0].args).join(', ') || 'none'}]`
|
||||
: '示例=none'
|
||||
|
||||
return `- 工具 ${spec.name}:适用场景=${spec.whenToUse};必填参数=[${requiredArgs || 'none'}];${example}`
|
||||
}
|
||||
|
||||
const buildRecentToolResultLine = (
|
||||
result: NonNullable<HumanState['lastParallelCallToolResults']>[number],
|
||||
index: number
|
||||
): string => {
|
||||
const diagnosticText = result.diagnostic
|
||||
? `;diagnostic=${result.diagnostic.kind}${result.diagnostic.missingArgs?.length ? `;missingArgs=[${result.diagnostic.missingArgs.join(', ')}]` : ''}`
|
||||
: ''
|
||||
return `- 第${index + 1}项:工具 ${result.toolName} ${result.ok ? '执行成功' : '执行失败'}(code=${result.code});摘要:${result.summary}${diagnosticText}`
|
||||
}
|
||||
|
||||
const buildBrainPromptRenderView = (input: {
|
||||
state: HumanState
|
||||
ctx: AiRunContext
|
||||
}): BrainPromptRenderView => {
|
||||
const { state, ctx } = input
|
||||
const learnedSkillIds = state.brainMemory.outside.learnedSkillIds
|
||||
const learnedSkillDefinitions = learnedSkillIds.map((skillId) => getSkillDefinition(skillId))
|
||||
const learnedToolNames = Array.from(
|
||||
new Set(learnedSkillDefinitions.flatMap((definition) => definition.toolNames))
|
||||
)
|
||||
const learnedToolSpecLines =
|
||||
learnedToolNames.length > 0
|
||||
? learnedToolNames
|
||||
.map((toolName) => getToolPromptSpec(toolName))
|
||||
.filter((spec): spec is ToolPromptSpec => Boolean(spec))
|
||||
.map(renderLearnedToolSpecLine)
|
||||
: ['none']
|
||||
|
||||
const recentToolResultLines = renderLineList(
|
||||
(state.lastParallelCallToolResults || []).map((result, index) =>
|
||||
buildRecentToolResultLine(result, index)
|
||||
),
|
||||
{
|
||||
fallback: 'none',
|
||||
style: 'plain'
|
||||
}
|
||||
)
|
||||
|
||||
const recentDecisionHistoryLines = renderLineList(
|
||||
state.brainMemory.outside.brainDecisions.map((record, index) => {
|
||||
const ordinal = index + 1
|
||||
const action = record.nextAction.action
|
||||
const nextActionPayload =
|
||||
action === 'learning'
|
||||
? `wantLearnSkillIds=[${record.nextAction.wantLearnSkillIds.join(',')}]`
|
||||
: action === 'hand'
|
||||
? `parallelCallToolParam=${JSON.stringify(record.nextAction.parallelCallToolParam)}`
|
||||
: 'final_delivery=true'
|
||||
|
||||
return `- 第${ordinal}轮(createdAt=${record.createdAt}):决定“${record.decision.summary}”;原因:${record.decision.reason};预期结果:${record.decision.expectedOutcome};nextAction.action=${action};nextAction数据:${nextActionPayload}`
|
||||
}),
|
||||
{
|
||||
fallback: 'none',
|
||||
style: 'plain'
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
factLines: renderHumanFactLines(state, 'brain_prompt'),
|
||||
evidenceLines: renderHumanEvidenceLines(state, 'brain_prompt'),
|
||||
openQuestionLines: renderHumanOpenQuestionLines(state, 'brain_prompt'),
|
||||
selectedContextText: ctx.selectedContextText,
|
||||
skillCatalogLines:
|
||||
state.brainMemory.outside.skillCatalog.length > 0
|
||||
? state.brainMemory.outside.skillCatalog.map(
|
||||
(item) =>
|
||||
`- ${item.skillId}:${item.summary};可提供工具=[${item.toolNames.join(', ')}];适用场景=${item.whenToUse}`
|
||||
)
|
||||
: ['none'],
|
||||
learnedSkillIdLines:
|
||||
learnedSkillIds.length > 0 ? learnedSkillIds.map((skillId) => `- ${skillId}`) : ['none'],
|
||||
learnedSkillDetailLines:
|
||||
learnedSkillDefinitions.length > 0
|
||||
? learnedSkillDefinitions.map((definition) => `- ${definition.skillId}:${definition.detail}`)
|
||||
: ['none'],
|
||||
learnedToolSpecLines,
|
||||
recentToolResultLines,
|
||||
recentDecisionHistoryLines
|
||||
}
|
||||
}
|
||||
|
||||
export const buildBrainPromptSections = (input: {
|
||||
state: HumanState
|
||||
ctx: AiRunContext
|
||||
}): BrainPromptSections => {
|
||||
const view = buildBrainPromptRenderView(input)
|
||||
|
||||
return {
|
||||
memorySnapshotText: [
|
||||
'下面是你之前沉淀下来的记忆。这些内容代表当前已经确认、可以直接复用或仍影响推进的信息。',
|
||||
'',
|
||||
'已确认的事实:',
|
||||
view.factLines,
|
||||
'',
|
||||
'支撑这些事实的关键证据:',
|
||||
view.evidenceLines,
|
||||
'',
|
||||
'仍未解决的问题:',
|
||||
view.openQuestionLines
|
||||
].join('\n'),
|
||||
selectedContextText: [
|
||||
'下面是当前用户明确给出的参考资料上下文。后续判断、检索和文件定位都必须先对齐这段信息。',
|
||||
'',
|
||||
view.selectedContextText
|
||||
].join('\n'),
|
||||
skillContextText: [
|
||||
'下面是当前可用的技能信息。技能目录摘要只用于判断要不要学习;只有已学习 skill 的详细说明和工具要点,才代表你当前可以直接依赖的能力。',
|
||||
'',
|
||||
'当前可用技能目录摘要:',
|
||||
formatList(view.skillCatalogLines),
|
||||
'',
|
||||
'已经学习的 skill id:',
|
||||
formatList(view.learnedSkillIdLines),
|
||||
'',
|
||||
'已学习技能的详细说明:',
|
||||
formatList(view.learnedSkillDetailLines),
|
||||
'',
|
||||
'已学习技能对应的工具使用要点:',
|
||||
formatList(view.learnedToolSpecLines)
|
||||
].join('\n'),
|
||||
recentToolResultsText: [
|
||||
'下面是最近一轮工具调用刚带回来的新信息。请把这些结果和已有记忆一起判断,不要重复做同样的动作。',
|
||||
'',
|
||||
view.recentToolResultLines
|
||||
].join('\n'),
|
||||
recentDecisionHistoryText: [
|
||||
'下面是最近几轮已经做过的正式判断摘要,只用于帮助你理解时间顺序并避免重复决策。',
|
||||
'',
|
||||
view.recentDecisionHistoryLines
|
||||
].join('\n')
|
||||
}
|
||||
}
|
||||
@@ -30,26 +30,8 @@ const buildFinalDecisionText = (state: HumanState): string =>
|
||||
? `最终决定:“${state.lastBrainDecision.decision.summary}”;原因:${state.lastBrainDecision.decision.reason};预期结果:${state.lastBrainDecision.decision.expectedOutcome}`
|
||||
: 'none'
|
||||
|
||||
export const buildMouthPromptContext = (input: {
|
||||
state: HumanState
|
||||
deliveryMode: HumanDeliveryMode
|
||||
}) => {
|
||||
return buildHumanMouthPrompt({
|
||||
deliveryMode: input.deliveryMode,
|
||||
userInput: input.state.task.userInput,
|
||||
finalDecisionText: buildFinalDecisionText(input.state),
|
||||
factsText: renderHumanFactLines(input.state, 'mouth_prompt'),
|
||||
evidencesText: renderHumanEvidenceLines(input.state, 'mouth_prompt'),
|
||||
openQuestionsText: renderHumanOpenQuestionLines(input.state, 'mouth_prompt'),
|
||||
recentToolResultsText: renderHumanRecentToolResultLines(input.state, 'prompt'),
|
||||
runtimeArtifactsText: renderHumanArtifactLines(input.state, 'prompt'),
|
||||
watchHintText: input.state.watchHint || 'none'
|
||||
})
|
||||
}
|
||||
|
||||
export const buildHumanMouthPrompt = (input: HumanMouthPromptInput) => {
|
||||
return {
|
||||
system: `
|
||||
export const buildMouthSystemPrompt = (deliveryMode: HumanDeliveryMode): string =>
|
||||
`
|
||||
<system>
|
||||
<role>
|
||||
你现在扮演一个负责对外表达最终结果的人。
|
||||
@@ -71,7 +53,7 @@ export const buildHumanMouthPrompt = (input: HumanMouthPromptInput) => {
|
||||
</delivery_principles>
|
||||
|
||||
<delivery_mode_rules>
|
||||
${buildDeliveryModePromptRules(input.deliveryMode)}
|
||||
${buildDeliveryModePromptRules(deliveryMode)}
|
||||
</delivery_mode_rules>
|
||||
|
||||
<output_rules>
|
||||
@@ -97,11 +79,13 @@ ${buildDeliveryModePromptRules(input.deliveryMode)}
|
||||
</output_principles>
|
||||
|
||||
<output_example>
|
||||
${buildDeliveryModePromptExample(input.deliveryMode)}
|
||||
${buildDeliveryModePromptExample(deliveryMode)}
|
||||
</output_example>
|
||||
</system>
|
||||
`.trim(),
|
||||
user: `
|
||||
`.trim()
|
||||
|
||||
export const buildMouthUserPrompt = (input: HumanMouthPromptInput): string =>
|
||||
`
|
||||
<user_context>
|
||||
<delivery_mode>
|
||||
${input.deliveryMode}
|
||||
@@ -140,5 +124,27 @@ ${input.watchHintText}
|
||||
</watch_hint>
|
||||
</user_context>
|
||||
`.trim()
|
||||
|
||||
export const buildMouthPromptContext = (input: {
|
||||
state: HumanState
|
||||
deliveryMode: HumanDeliveryMode
|
||||
}) => {
|
||||
return buildHumanMouthPrompt({
|
||||
deliveryMode: input.deliveryMode,
|
||||
userInput: input.state.task.userInput,
|
||||
finalDecisionText: buildFinalDecisionText(input.state),
|
||||
factsText: renderHumanFactLines(input.state, 'mouth_prompt'),
|
||||
evidencesText: renderHumanEvidenceLines(input.state, 'mouth_prompt'),
|
||||
openQuestionsText: renderHumanOpenQuestionLines(input.state, 'mouth_prompt'),
|
||||
recentToolResultsText: renderHumanRecentToolResultLines(input.state, 'prompt'),
|
||||
runtimeArtifactsText: renderHumanArtifactLines(input.state, 'prompt'),
|
||||
watchHintText: input.state.watchHint || 'none'
|
||||
})
|
||||
}
|
||||
|
||||
export const buildHumanMouthPrompt = (input: HumanMouthPromptInput) => {
|
||||
return {
|
||||
system: buildMouthSystemPrompt(input.deliveryMode),
|
||||
user: buildMouthUserPrompt(input)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user