import { TOOL_LABELS } from './tools'
function parseArgs(argsJson: string): Record<string, string> {
try {
return JSON.parse(argsJson) as Record<string, string>
} catch {
return {}
}
}
function pickModelThought(content?: string | null, reasoning?: string | null): string | null {
const reasoningText = reasoning?.trim()
if (reasoningText) return reasoningText
const contentText = content?.trim()
if (!contentText) return null
const tagged = contentText.match(/(?:【思考】|Thought[::]|思考[::])\s*([\s\S]+?)(?=(?:【行动】|Action[::]|$))/i)
if (tagged?.[1]?.trim()) return tagged[1].trim()
if (!contentText.startsWith('{') && contentText.length > 4) return contentText
return null
}
function buildToolThought(
userQuestion: string,
toolName: string,
argsJson: string,
round: number,
): string {
const args = parseArgs(argsJson)
const label = TOOL_LABELS[toolName] ?? toolName
const reasonByTool: Record<string, string> = {
get_weather: `用户问题涉及实时天气(「${userQuestion}」)。训练数据里没有此刻的天气,我不能编造。`,
get_current_datetime: `用户问题涉及当前时间(「${userQuestion}」)。我必须获取系统实时时钟,不能凭记忆猜测。`,
calculate: `用户问题包含精确计算(「${userQuestion}」)。大模型心算容易出错,应交给计算工具。`,
get_exchange_rate: `用户问题涉及汇率换算(「${userQuestion}」)。汇率每天变化,必须查询实时数据。`,
}
const reason = reasonByTool[toolName] ?? `用户问题(「${userQuestion}」)需要外部数据支持,不能凭空回答。`
const argSummary = Object.entries(args)
.map(([k, v]) => `${k}=${v}`)
.join(', ')
return [
`【第 ${round} 轮思考】`,
reason,
`→ 结论:调用工具「${label}」(${toolName})`,
argSummary ? `→ 参数:${argSummary}` : '',
]
.filter(Boolean)
.join('\n')
}
function buildDirectThought(userQuestion: string, round: number): string {
return [
`【第 ${round} 轮思考】`,
`分析问题:「${userQuestion}」`,
'→ 判断:这是知识解释类问题,或已有足够信息,无需调用外部工具。',
'→ 结论:直接基于已有信息组织最终回答。',
].join('\n')
}
function buildSynthesisThought(userQuestion: string, round: number, hadToolCalls: boolean): string {
if (!hadToolCalls) return buildDirectThought(userQuestion, round)
return [
`【第 ${round} 轮思考】`,
'已收到工具返回的真实数据(Observation)。',
'→ 判断:信息足够,可以将观察结果整合为自然语言回答。',
'→ 结论:生成最终答案,并引用工具返回的数据。',
].join('\n')
}
export function resolveThought(params: {
userQuestion: string
toolName?: string
toolArgs?: string
round: number
modelContent?: string | null
modelReasoning?: string | null
phase: 'before_tool' | 'direct_answer' | 'synthesis_answer'
hadToolCalls?: boolean
}): string {
const fromModel = pickModelThought(params.modelContent, params.modelReasoning)
if (fromModel) return `【第 ${params.round} 轮思考】\n${fromModel}`
if (params.phase === 'before_tool' && params.toolName) {
return buildToolThought(params.userQuestion, params.toolName, params.toolArgs ?? '{}', params.round)
}
if (params.phase === 'synthesis_answer') {
return buildSynthesisThought(params.userQuestion, params.round, params.hadToolCalls ?? false)
}
return buildDirectThought(params.userQuestion, params.round)
}