交付产物二次修改
继上个月进行持续迭代,方案二配套服务流程中的“导出 -> IDE 修改 -> 导入获得编译产物”将直接优化为“根据用户需求获得编译产物”。
通过内置 Agent 能力,将 IDE 修改流程全部隐藏在服务内,让用户更轻松的进行二次修改。
经过技术调研采用 deepagents 实现 Agent 相关能力。实现重点主要是文件系统沙箱 + AI 进行 AST 修改后输出结果。
在实现基础功后,为了选用较好的模型来落地,所以对模型进行过一些调试和测试,也很容易发现不同模型的最后呈现效果差异也很大。
目前打算使用 kimi-k2.5 进行进一步测试,不过在这里将测试过程中遇到的问题可以分享一下。
对接过程中会报错:
{
name: 'Error',
cause: {
status: 400,
headers: {},
requestID: null,
error: {
message: 'thinking is enabled but reasoning_content is missing in assistant tool call message at index 2',
type: 'invalid_request_error'
},
type: 'invalid_request_error'
}
}
查阅了相关资料,社区因为考虑所以并没有处理这个问题,本着想提 PR 的思路尝试看看能不能解决。但是最后发现因为对 @langchain 相关生态了解较为浅显,所以暂时放弃提 PR 的操作。
最后决定通过补丁的方式进行解决此问题。
通过 debugger 能找到具体发起模型请求的位置是 ChatOpenAICompletions 类的 _streamResponseChunks 的方法,第一参数 messages 能获得当前请求的消息内容。
通过继承此函数实现 reasoning_content 字段补充,操作下去的你就会发现并没有这么轻松,因为在真实发起请求前会调用 convertMessagesToCompletionsMessageParams 进行格式化(源码 completions.ts#L823),并且没有修改空间。
不过幸运的是所有的参数在最后执行前会调用 completionWithRetry 我们可以通过复写此函数来进行格式重定义,并且观察源码发现 options 会进行透传,那就可以借助这个参数进行字段补充。
接下来是补丁内容:
import { ChatOpenAICompletions } from '@langchain/openai';
interface HankOptionsAttr {
reasoning_content: Array<{ index: number; reasoning_content: string }>;
}
class HankChatOpenAICompletions extends ChatOpenAICompletions {
async *_streamResponseChunks(messages, options, runManager) {
const humanMessageIndex = messages.findIndex(
(message) => message.type === 'human',
);
const humanMessage = messages[humanMessageIndex];
const __hank__: HankOptionsAttr = {
reasoning_content: [],
};
// 步骤二:若最后的用户消息存在 reasoning_content 则表示之前收集成功
if (
humanMessageIndex !== -1 &&
humanMessage?.additional_kwargs?.reasoning_content
) {
// 步骤二:尝试寻找需要补充 reasoning_content 字段的 Assistant Message
for (let i = messages.length - 1; i > humanMessageIndex; i--) {
const message = messages[i];
if (message.type === 'ai') {
__hank__.reasoning_content.push({
index: i,
reasoning_content:
humanMessage?.additional_kwargs?.reasoning_content,
});
}
}
}
// 步骤三:将收集到的信息通过 options 进行透传
options.__hank__ = __hank__;
// 步骤一:尝试收集 reasoning_content
let reasoning_content = '';
const chunks = super._streamResponseChunks(messages, options, runManager);
for await (const chunk of chunks) {
const delta = (chunk.message.additional_kwargs.__raw_response as any)
?.choices?.[0]?.delta;
if (delta?.reasoning_content) {
reasoning_content += delta.reasoning_content;
}
yield chunk;
}
// 步骤一:若 reasoning_content 存在则将其设置到最后一个用户消息内
if (humanMessageIndex !== -1 && reasoning_content) {
humanMessage.additional_kwargs ??= {};
humanMessage.additional_kwargs.reasoning_content = reasoning_content;
}
}
async completionWithRetry(request, requestOptions): Promise<any> {
try {
// 步骤三:根据透传信息补充 reasoning_content
const __hank__: HankOptionsAttr = requestOptions?.__hank__ ?? {};
if (Array.isArray(__hank__.reasoning_content)) {
__hank__.reasoning_content.forEach((hank_rc) => {
request.messages[hank_rc.index].reasoning_content =
hank_rc.reasoning_content;
});
}
} catch {}
return super.completionWithRetry(request, requestOptions);
}
}
const agent = createDeepAgent({
model: new ChatOpenAI({
completions: new HankChatOpenAICompletions(/* ... */),
// ...
}),
// ...
backend: new SafeFileSystem(),
});
通过上述补丁能力,能够成功将此类问题解决。
让我们愉快的进行后续的迭代调试吧。
- 本文链接: https://zongzi531.github.io/2026/03/01/%E9%A9%AC%E5%88%B0%E9%87%91%E6%9D%A5/
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!