AlphaCodium 提出了一种使用控制流的代码生成方法。
核心思想:迭代式地构建编码问题的答案。
AlphaCodium 通过迭代测试和改进答案,使用公开和 AI 生成的测试来验证特定问题的解决方案。
我们将使用 LangGraph 从头实现其中的一些想法:
首先,安装所需的包并设置所需的 API 密钥。
python! pip install -U langchain_community langchain-openai langchain-anthropic langchain langgraph bs4
import getpass
import os
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{var}: ")
_set_env("OPENAI_API_KEY")
_set_env("ANTHROPIC_API_KEY")
加载 LangChain Expression Language (LCEL) 文档作为示例。
pythonfrom bs4 import BeautifulSoup as Soup
from langchain_community.document_loaders.recursive_url_loader import RecursiveUrlLoader
# LCEL 文档
url = "https://python.langchain.com/docs/concepts/lcel/"
loader = RecursiveUrlLoader(
url=url, max_depth=20, extractor=lambda x: Soup(x, "html.parser").text
)
docs = loader.load()
# 按 URL 排序并获取文本
d_sorted = sorted(docs, key=lambda x: x.metadata["source"])
d_reversed = list(reversed(d_sorted))
concatenated_content = "\n\n\n --- \n\n\n".join(
[doc.page_content for doc in d_reversed]
)
我们将尝试使用 OpenAI 和 Claude3 进行代码生成。
pythonfrom langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
# OpenAI 配置
code_gen_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"""你是精通 LCEL(LangChain 表达式语言)的编码助手。\n
以下是完整的 LCEL 文档:\n ------- \n {context} \n ------- \n
根据提供的文档回答用户问题。确保提供的代码可以执行,并包含所有必需的导入和变量定义。
结构化你的答案:1) 代码解决方案的描述,2) 导入语句,3) 可执行的代码块。用户问题是:""",
),
("placeholder", "{messages}"),
]
)
# 数据模型
class code(BaseModel):
"""LCEL 问题代码解决方案的 Schema"""
prefix: str = Field(description="问题描述和解决方案方法")
imports: str = Field(description="导入语句代码块")
code: str = Field(description="不包括导入语句的代码块")
expt_llm = "gpt-4o-mini"
llm = ChatOpenAI(temperature=0, model=expt_llm)
code_gen_chain_oai = code_gen_prompt | llm.with_structured_output(code)
生成代码并执行单元测试。
pythonfrom langchain_anthropic import ChatAnthropic
# Anthropic 配置
code_gen_prompt_claude = ChatPromptTemplate.from_messages(
[
(
"system",
"""<instructions> 你是精通 LCEL 的编码助手。\n
以下是 LCEL 文档:\n ------- \n {context} \n ------- \n
根据提供的文档回答用户问题。确保提供的代码可以执行,并包含所有必需的导入和变量定义。
结构化你的答案:1) 代码解决方案的描述,2) 导入语句,3) 可执行的代码块。
调用代码工具以正确结构化输出。</instructions> \n 用户问题是:""",
),
("placeholder", "{messages}"),
]
)
expt_llm = "claude-3-opus-20240229"
llm = ChatAnthropic(
model=expt_llm,
default_headers={"anthropic-beta": "tools-2024-04-04"},
)
structured_llm_claude = llm.with_structured_output(code, include_raw=True)
定义代码检查和修正的逻辑。
pythondef code_check(state: GraphState):
"""检查代码"""
print("---CHECKING CODE---")
messages = state["messages"]
code_solution = state["generation"]
iterations = state["iterations"]
# 检查导入
try:
exec(code_solution.imports)
except Exception as e:
print("---CODE IMPORT CHECK: FAILED---")
error_message = [("user", f"导入检查失败: {e}")]
messages += error_message
return {"error": "yes"}
# 检查代码执行
try:
exec(code_solution.imports + "\n" + code_solution.code)
except Exception as e:
print("---CODE BLOCK CHECK: FAILED---")
error_message = [("user", f"代码执行检查失败: {e}")]
messages += error_message
return {"error": "yes"}
print("---NO CODE TEST FAILURES---")
return {"error": "no"}
以下是完整的代码实现,包括 LangGraph 的工作流定义和测试逻辑。
pythonfrom langgraph.graph import END, StateGraph, START
workflow = StateGraph(GraphState)
# 定义节点
workflow.add_node("generate", generate) # 生成解决方案
workflow.add_node("check_code", code_check) # 检查代码
workflow.add_node("reflect", reflect) # 反思错误
# 构建图
workflow.add_edge(START, "generate")
workflow.add_edge("generate", "check_code")
workflow.add_conditional_edges(
"check_code",
decide_to_finish,
{
"end": END,
"reflect": "reflect",
"generate": "generate",
},
)
workflow.add_edge("reflect", "generate")
app = workflow.compile()
使用 LangSmith 进行测试和评估。
pythonfrom langsmith import Client
client = Client()
# 克隆公共数据集
try:
public_dataset = "https://smith.langchain.com/public/326674a6-62bd-462d-88ae-eea49d503f9d/d"
client.clone_public_dataset(public_dataset)
except:
print("请设置 LangSmith")
# 自定义评估
def check_import(run: Run, example: Example) -> dict:
imports = run.outputs.get("imports")
try:
exec(imports)
return {"key": "import_check", "score": 1}
except Exception:
return {"key": "import_check", "score": 0}
def check_execution(run: Run, example: Example) -> dict:
imports = run.outputs.get("imports")
code = run.outputs.get("code")
try:
exec(imports + "\n" + code)
return {"key": "code_execution_check", "score": 1}
except Exception:
return {"key": "code_execution_check", "score": 0}
LangGraph 表现优于基础案例:添加重试循环提高了性能。
反思并未帮助:在重试之前进行反思反而导致性能下降。
GPT-4 优于 Claude3:Claude3 在某些运行中因工具使用错误而失败。
总结:通过 LangGraph 和 RAG,我们能够迭代生成和优化代码解决方案,确保其正确性和可执行性。
本文作者:yowayimono
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!