LangGraph 助力代码生成新境界
本文译自LangGraph for Code Generation一文。介绍了基于LangGraph流程来实现代码的生成与分析,并详细介绍了方案的性能评估方案。本系列合集,点击链接查看
必要链接
研究初衷
在大型语言模型(LLMs)的众多应用中,代码生成与分析尤为关键,这从产品 GitHub co-pilot 的广泛应用和 GPT-engineer 等项目的热度可见一斑。AlphaCodium 的最新进展展示出,与传统"提示-应答"方法不同,"流程"式编程通过测试与反思答案,进而迭代改进,能更好地推动代码的生成。
我们最近推出了 LangGraph,这是一种以图表形式表示与设计流程的工具。受到 AlphaCodium 和 Reflexion 工作的激励,我们想借助 LangGraph 在代码生成中实现类似的迭代循环和关键决策点。
具体而言,我们试图构建并比较两种架构:
- 基于提示与上下文填充的代码生成
- 涉及校验执行代码的流程化代码生成,出现错误时能自我纠错
这个尝试旨在探究:这种代码检验能在多大程度上提升代码生成系统的性能?
结果如何呢?
💡
与仅进行单次生成的基本方法相比,涉及校验与自我修正的系统展现出显著进步( 81% 对 55% )
问题背景
为了在有限的文档库上展示代码生成能力,我们选择了 LangChain 的文档子集,着重于 LangChain 表达式语言(LCEL),其范围小(大约 60k 标记)且备受关注。我们筛选了连续 30 天的 chat-langchain
中与 LCEL 相关的问题(代码在此)。从 >60k 聊天记录
共筛选出 ~500
条提到 LCEL 的记录。我们对这约 500 条记录进行聚类,由 LLM(GPT-4,128k)归纳总结,以得出每个类别中的代表性问题。每个问题我们都进行了手动审核,并制定了标准答案(含 20 个问题的评估集在这里)。我们把此数据集加到了 LangSmith。
利用 LangGraph 进行反射式代码生成
我们设计并实践了一个包含如下环节的代码生成流程:
- 受到长上下文 LLMs 的新动向启发,我们利用 GPT-4(128k 令牌上下文窗口)的能力将 60k 令牌的 LCEL 文档详尽填充。我们向经处理过的 LCEL 链条提交 LCEL 相关问题,以启动初步答案的生成。
- 我们使用 OpenAI 工具对成果进行了解析,将输出转化为拥有三个部分的 Pydantic 对象:(1)问题描述,(2)导入模块部分,(3)代码本体。
- 我们首先对 导入模块 进行执行测试,因为我们曾发现在代码生成过程中,幻觉可能悄然渗入导入语句之中。
- 导入模块 测试通过后,我们接着确认代码本身是否可执行。在代码生成时,我们特别指导 LLM 防止代码中出现伪代码或未定义变量,以确保代码能够被执行。
- 其中,若上述任一测试失败,我们就会将错误堆栈与先前的回答一起传回生成环节以供反思。默认我们会重试 3 次,当然这个次数根据需求还可以增加。
利用 LangSmith 进行的评估
我们设立了不涉及 LangGraph 的 "上下文填充" 基准线,即在我们的流程图中这一环节并未执行任何检测或反馈:同样利用 GPT-4 的 128k 令牌上下文窗口,我们将 60k 令牌的 LCEL 文档进行充实。我们提交了与 LCEL 相关的问题以生成答案。
我们为两个部分
- (1)导入模块的评估
- (2)代码执行的评估
实现了 LangSmith 的自定义评价功能。
我们在 "上下文填充" 的 20 个问题评估集上进行了四轮评估。评估结果在此。通过上下文填充进行的评估表明 ~98%
的导入模块测试是准确的,而代码执行成功率约 ~55%
(N=79
次成功尝试)。
我们通过 LangSmith 分析了失败的案例:案例分析,一个典型的错误是没能注意到 RunnableLambda
函数的输入应当是 dict
,反而将其误认为 string
:AttributeError: 'dict' object has no attribute 'upper'
接下来,我们对"通过上下文填充 + LangGraph"的情况进行了测试,通过执行测试以筛查导入和代码执行中的错误,并在生成更新的答案时进行反思。在相同的评估集上,我们观察到 100%
的导入测试是准确的,以及 ~81%
的代码执行测试是成功的(N=78
次尝试)。
以上述失败案例为例,我们可以看到系统是如何进行处理的:完整的错误跟踪显示,我们在回答问题的第二次尝试中遇到了同样的错误详情。在后续的反思环节中,我们提供了先前的解决方案和随之出现的错误:
python
您之前尝试解决过这个问题。
...
--- 最近的运行错误 ---
执行错误:'dict' 对象没有 'upper' 属性
...
请再次尝试回答这个问题。
...
最终的代码正确处理了 RunnableLambda
函数中的输入字典,避免了 上下文填充
情况中出现的错误。总的来看,通过使用 LangGraph 添加这个简单的反思步骤进行重试后,代码执行的准确率得到了 ~47%
的提高:
结论总结
LangGraph 以其流程设计的便捷性,助力了复杂循环和决策点的设置。最新研究证明,这种设计对于代码生成极具价值,能够迭代并利用测试来检验答案,通过反思错误,不断完善最终的解决方案。我们使用 LangGraph 实现了这一流程,并在关于 LCEL 的 20 个问题中进行了代码导入和执行的测试。结果显示,"上下文填充 + LangGraph" 结合反思的模式相比于仅有的"上下文填充",在代码执行方面取得了 ~47%
的显著提升。这一流程的应用案例在这里,并且可以轻松扩展至其他代码库,供相关人员参考。