ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

[LangGraph编译原理-01]写一个Agent将英文诗歌翻译成古典诗词

[LangGraph编译原理-01]写一个Agent将英文诗歌翻译成古典诗词 如果采用LangGraph的编程方式我们需要将StateGraph作为Builder通过添加节点和边来构建具有指定结构图并通过编译此图生成一个CompiledStateGraph对象作为Agent。图具有可组合特性Agent自身又可以作为图的一个节点以此类推具有任意复杂度处理流程的Agent都可以由相应的图转变而成。编译生成的CompiledStateGraph本质上是一个Pregel对象(关于Pregel的系统介绍可用参与我的系列文章拆解LangChain执行引擎)那么实现两者转换的编译是如何实现的呢为了让大家对LangGraph的Agent编程方式有一个大致的了解我们创建了一个简单的Agent将指定的英文诗歌翻译成中文古典诗词。整个流程如下图所示: 输入提示词后先利用translate节点作初步的翻译。然后对翻译的结构进行评估如果合格则流程终止否则再调用retranslate节点重新翻译。步骤一定义状态Schema类型这个演示实例会创建一个Agent将一首英文诗歌翻译成一首中国古诗。我们首先定义如下这个继承自TypedDict的PoemTranslationState类型它将作为整个诗歌翻译流程共享的状态类型。original_poem字段表示通过提示词输入的诗歌原文first_translation和second_translation字典则是针对它的两次翻译。classPoemTranslationState(TypedDict):original_poem:strfirst_translation:strsecond_translation:str步骤二创建初步翻译节点Agent采用ChatOpenAI作为模型组件具体的LLM为gpt-5.2-chat。system_prompt表示为它设置的系统提示词。modelChatOpenAI(modelgpt-5.2-chat)system_promptSystemMessage(content你是一位精通中英双语的文学教授擅长将西方近现代诗歌意蕴转化为中国古典诗词。)如下所示的是translate节点对应函数的定义。它以PoemTranslationState作为参数从中提取诗歌原文填充到提示词模板生成一个HunanMessage。这个HunanMessage连同之前创建的系统提示词作为输入调用ChatOpenAI对象并得到一个AIMessage对象。我们将其content字段承载的文本内容提取出来置于返回的字典中对应的Key被设置为first_translation意味着得到的内容将写入Agent状态的first_translation字段。deftranslate(state:PoemTranslationState):query(HumanMessagePromptTemplate.from_template(请将以下英文诗翻译成中文古诗如五言律诗、七言绝句或宋词格式{original_poem}).format_messages(original_poemstate[original_poem]))resultmodel.invoke([system_prompt,*query])return{first_translation:result.content}步骤三定义二次翻译节点第一次翻译如果未能达到我们的要求则会进行二次翻译。作为二次翻译的retranslate节点函数会复杂一些我们会提供少样本提示词。我们具体使用的是FewShotPromptTemplate我的文章“少样本提示词模板”对它有过详细介绍。翻译的内容将写入Agent状态的second_translation字段。defretranslate(state:PoemTranslationState):examples[{original:The woods are lovely, dark and deep. But I have promises to keep. And miles to go before I sleep.,translation:幽林深处影重重诺重难酬信必从。长路漫漫何处歇未曾入梦莫辞踪。},{original:Life is a broken-winged bird.That cannot fly.,translation:命似残禽翼折难凭。云霄望断万事皆零。},]template 原文: {original} 翻译: {translation} promptFewShotPromptTemplate(examplesexamples,example_promptPromptTemplate.from_template(templatetemplate),prefix请按照如下的要求将给出的原文英文诗歌翻译成中文古诗如五言律诗、七言绝句或宋词格式:,suffix原文: {original}\n翻译:,input_variables[original],example_separator\n)queryHumanMessage(contentprompt.format(originalstate[original_poem]))resultmodel.invoke([system_prompt,query])return{second_translation:result.content}执行translate节点后是否执行retranslate节点取决于针对首次翻译的评估结果。评估任务实现在如下这个evaluate函数中它返回的字符串代表完成评估之后决定下执行的下一个节点名称retranslate表示不符合要求需要二次翻译__end__表示翻译合格流程终止。步骤四构建状态图并将其编程成Agentevaluate的输入参数PoemTranslationState维持translate节点执行后的状态所以我们可以提取诗歌原文和首次翻译文本并提交给LLM实施评估。我们利用HumanMessagePromptTemplate我的文章“基于Chat模型的提示词模板”对包括它在内的所有消息提示词模板有详细介绍来生成提示词提供的模板不仅为翻译评估提供了具体的要求还对格式提出了规定利用首字符1/0代表评估结构后面附加评估理由其实这种场景使用结构化输出更可靠。我们根据LLM针对评估的输出决定后续执行的节点名称。defevaluate(state:PoemTranslationState)-Literal[retranslate,__end__]:template\ 对于给出的针对英文诗歌的中文翻译请从以下几个方面进行评价 - 意象对等将原文意象转化为中国古典文学中的常用意象如将“Sunset”转为“残阳”或“斜晖”。 - 格律要求确保平仄协调严格遵守押韵规则。 - 意境重塑不要求字面直译但须保留原作的灵魂与情感底色。 - 双语对照请先给出直译理解再给出最终的古典诗词成品。 原文{original_poem} 翻译{translated_poem} 如果翻译符合上述要求请回复1否则回复0。并附上评估理由 queryHumanMessagePromptTemplate.from_template(template).format_messages(original_poemstate[original_poem],translated_poemstate[first_translation])resultmodel.invoke([system_prompt,*query])print(result.content)returnENDifresult.content.startswith(1)elseretranslate# type: ignore两个节点和评估的函数定义完成之后我们创建了作为Agent构建这的StateGraph对象并添加了两个节点。我们通过添加从START__start__到translate的边将translate作为入口节点添加retranslate到END__end__的边将retranslate节点作为完成节点。translate和retranslate/__end__之间是一条依赖于评估结构的条件边。图按照我们希望的结构构建好之后我们调用compile方法将StateGraph编译成Agent对象。builder(StateGraph(PoemTranslationState).add_node(translate,translate).add_node(retranslate,retranslate).add_edge(START,translate).add_edge(retranslate,END).add_conditional_edges(translate,evaluate))agentbuilder.compile()payloadagent.get_graph().draw_mermaid_png()PILImage.open(io.BytesIO(payload)).show()resultagent.invoke({original_poem:I love thee to the depth and breadth and height / My soul can reach.})# type: ignoreprint(f第一次翻译:\n\n{result[first_translation]})print(f\n第二次翻译:\n\n{result[second_translation]})为了以可视化方式查看图的结构我们调用Agent的get_graph方法得到对应的Graph对象在进一步调用draw_mermaid_png方法将其转换成PNG图片。我们最终利用PIL库将图片呈现出来上面显式的就是这张生成PNG图片。步骤五调用Agent我们将代表Agent状态的PoemTranslationState同时作为它的输入和输出。我们调用其invoke方法利用输入的PoemTranslationState提供了待翻译的一句英文诗。得到作为结构的PoemTranslationState对象后我们将两次翻进行输出。第一次翻译: 可译为**七言绝句** 爱汝情深遍四维 心魂所至尽高卑。 量天量地犹嫌浅 一念绵绵到太微。 第二次翻译: 翻译示例七言诗 爱君至情无尽量 深阔高长任我量。 魂魄所能皆可至 天地同证此衷肠。从如上的输出结果来看生成的两首诗感觉还不错吧。那么为什么第一首没有达到我们的要求呢好在evaluate函数输出了LLM评估的结果理由可以看出还是有理有据的。0 **评估理由** 1. **意象对等基本符合** 译文以“四维”“高卑”“量天量地”“太微”等中国古典语汇成功对应原诗中 *depth / breadth / height* 的空间意象且带有宇宙尺度的审美扩展整体意象转化较为得体。 2. **格律要求不符合** - 字数确为七言四句形式上符合七言绝句。 - 押韵七言绝句通常要求第二、四句同韵多数情况下首句可押可不押。本诗第二句“卑”支微部与第四句“微”微韵并未严格同韵第三句“浅”亦出韵押韵不合格。 - 平仄未体现出严格的近体诗平仄规范整体更接近“七言古诗体”而非严格绝句。 3. **意境重塑基本符合** 未拘泥于字面翻译成功表达了原诗中无穷无尽、超越尺度的深情情感底色与原作勃朗宁《十四行诗集》相契合。 4. **双语对照不符合** 要求“先给出直译理解再给出最终古典诗词成品”而所给译文直接呈现诗化结果缺少对原文的直译说明不符合该项要求。 **综合判断**虽在意象与意境方面表现良好但在押韵规范与“双语对照”要求上未达标因此判定为 **0**。完整的代码如下提供了整个实例完整的代码fromlangchain_openaiimportChatOpenAIfromtypingimportTypedDict,Literalfromlanggraph.graphimportStateGraph,START,ENDfromlangchain_core.messagesimportHumanMessage,SystemMessagefromlangchain_core.promptsimportHumanMessagePromptTemplate,FewShotPromptTemplate,PromptTemplatefromPILimportImageasPILImageimportiofromdotenvimportload_dotenv load_dotenv()modelChatOpenAI(modelgpt-5.2-chat)system_promptSystemMessage(content你是一位精通中英双语的文学教授擅长将西方近现代诗歌意蕴转化为中国古典诗词。)classPoemTranslationState(TypedDict):original_poem:strfirst_translation:strsecond_translation:strdeftranslate(state:PoemTranslationState):queryHumanMessagePromptTemplate.from_template(请将以下英文诗翻译成中文古诗如五言律诗、七言绝句或宋词格式{original_poem}).format_messages(original_poemstate[original_poem])resultmodel.invoke([system_prompt,*query])return{first_translation:result.content}defevaluate(state:PoemTranslationState)-Literal[retranslate,__end__]:template 对于给出的针对英文诗歌的中文翻译请从以下几个方面进行评价 - 意象对等将原文意象转化为中国古典文学中的常用意象如将“Sunset”转为“残阳”或“斜晖”。 - 格律要求确保平仄协调严格遵守押韵规则。 - 意境重塑不要求字面直译但须保留原作的灵魂与情感底色。 - 双语对照请先给出直译理解再给出最终的古典诗词成品。 原文{original_poem} 翻译{translated_poem} 如果翻译符合上述要求请回复1否则回复0不要添加任务其他字符。并附上评估理由 queryHumanMessagePromptTemplate.from_template(template).format_messages(original_poemstate[original_poem],translated_poemstate[first_translation])resultmodel.invoke([system_prompt,*query])print(result.content)returnENDifresult.content.startswith(1)elseretranslate# type: ignoredefretranslate(state:PoemTranslationState):examples[{original:The woods are lovely, dark and deep, / But I have promises to keep, / And miles to go before I sleep,translation:幽林深处影重重诺重难酬信必从。长路漫漫何处歇未曾入梦莫辞踪。},{original:Life is a broken-winged bird, / That cannot fly.,translation:命似残禽翼折难凭。云霄望断万事皆零。},]template 原文: {original} 翻译: {translation} promptFewShotPromptTemplate(examplesexamples,example_promptPromptTemplate.from_template(templatetemplate),prefix请按照如下的要求将给出的原文英文诗歌翻译成中文古诗如五言律诗、七言绝句或宋词格式:,suffix原文: {original}\n翻译:,input_variables[original],example_separator\n)queryHumanMessage(contentprompt.format(originalstate[original_poem]))resultmodel.invoke([system_prompt,query])return{second_translation:result.content}builder(StateGraph(PoemTranslationState).add_node(translate,translate).add_node(retranslate,retranslate).add_edge(START,translate).add_edge(retranslate,END).add_conditional_edges(translate,evaluate))agentbuilder.compile()payloadagent.get_graph(xrayTrue).draw_mermaid_png()PILImage.open(io.BytesIO(payload)).show()resultagent.invoke({original_poem:I love thee to the depth and breadth and height / My soul can reach.})# type: ignoreprint(f第一次翻译:\n\n{result[first_translation]})print(f\n第二次翻译:\n\n{result[second_translation]})
返回列表