ARTICLE DETAIL

资讯详情

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

(LangGraph教程)4. Building Your Assistant——Lesson 2:Sub-graphs子图(未索引)

(LangGraph教程)4. Building Your Assistant——Lesson 2:Sub-graphs子图(未索引) https://academy.langchain.com/courses/intro-to-langgraphhttps://github.com/shangxiang0907/langchain-academy文章目录Sub-graphs 子图Review 复习Goals 目标State 状态Input 输入Sub graphs 子图Adding sub graphs to our parent graph 将子图添加到父图LangSmithSub-graphs 子图Review 复习We’re building up to a multi-agent research assistant that ties together all of the modules from this course.我们正在构建一个多功能智能体研究助手该助手将本课程所有模块整合在一起。We just covered parallelization, which is one important LangGraph controllability topic.我们刚刚学习了并行化这是 LangGraph 可控性的一个重要主题。Goals 目标Now, we’re going to cover sub-graphs.接下来我们将学习子图。State 状态Sub-graphs allow you to create and manage different states in different parts of your graph.子图允许你在图的不同部分创建和管理不同的状态。This is particularly useful for multi-agent systems, with teams of agents that each have their own state.这对多智能体系统尤其有用——例如由多个智能体组成的团队每个智能体都拥有自己的状态。Let’s consider a toy example:我们来看一个简化示例I have a system that accepts logs我有一个接收日志的系统It performs two separate sub-tasks by different agents (summarize logs, find failure modes)它由不同智能体执行两项独立的子任务摘要日志、识别故障模式I want to perform these two operations in two different sub-graphs.我希望在这两个不同的子图中分别执行这两项操作。The most critical thing to understand is how the graphs communicate!最关键的是要理解图之间如何通信In short, communication isdone with over-lapping keys:简而言之通信是通过**重叠的键keys**实现的The sub-graphs can accessdocsfrom the parent子图可访问父图中的docsThe parent can accesssummary/failure_reportfrom the sub-graphs父图可访问子图中的summary/failure_reportInput 输入Let’s define a schema for the logs that will be input to our graph.我们来定义将输入到图中的日志的结构。%%capture--no-stderr%pip install-U langgraphWe’ll use LangSmith for tracing.我们将使用 LangSmith 进行追踪tracing。importos,getpassdef_set_env(var:str):ifnotos.environ.get(var):os.environ[var]getpass.getpass(f{var}: )_set_env(LANGSMITH_API_KEY)os.environ[LANGSMITH_TRACING]trueos.environ[LANGSMITH_PROJECT]langchain-academyfromoperatorimportaddfromtyping_extensionsimportTypedDictfromtypingimportList,Optional,Annotated# The structure of the logsclassLog(TypedDict):id:strquestion:strdocs:Optional[List]answer:strgrade:Optional[int]grader:Optional[str]feedback:Optional[str]Sub graphs 子图Here is the failure analysis sub-graph, which usesFailureAnalysisState.以下是故障分析子图它使用FailureAnalysisState。fromIPython.displayimportImage,displayfromlanggraph.graphimportStateGraph,START,END# Failure Analysis Sub-graphclassFailureAnalysisState(TypedDict):cleaned_logs:List[Log]failures:List[Log]fa_summary:strprocessed_logs:List[str]classFailureAnalysisOutputState(TypedDict):fa_summary:strprocessed_logs:List[str]defget_failures(state): Get logs that contain a failure cleaned_logsstate[cleaned_logs]failures[logforlogincleaned_logsifgradeinlog]return{failures:failures}defgenerate_summary(state): Generate summary of failures failuresstate[failures]# Add fxn: fa_summary summarize(failures)fa_summaryPoor quality retrieval of Chroma documentation.return{fa_summary:fa_summary,processed_logs:[ffailure-analysis-on-log-{failure[id]}forfailureinfailures]}fa_builderStateGraph(state_schemaFailureAnalysisState,output_schemaFailureAnalysisOutputState)fa_builder.add_node(get_failures,get_failures)fa_builder.add_node(generate_summary,generate_summary)fa_builder.add_edge(START,get_failures)fa_builder.add_edge(get_failures,generate_summary)fa_builder.add_edge(generate_summary,END)graphfa_builder.compile()display(Image(graph.get_graph().draw_mermaid_png()))Here is the question summarization sub-grap, which usesQuestionSummarizationState.以下是问题摘要子图它使用QuestionSummarizationState。# Summarization subgraphclassQuestionSummarizationState(TypedDict):cleaned_logs:List[Log]qs_summary:strreport:strprocessed_logs:List[str]classQuestionSummarizationOutputState(TypedDict):report:strprocessed_logs:List[str]defgenerate_summary(state):cleaned_logsstate[cleaned_logs]# Add fxn: summary summarize(generate_summary)summaryQuestions focused on usage of ChatOllama and Chroma vector store.return{qs_summary:summary,processed_logs:[fsummary-on-log-{log[id]}forlogincleaned_logs]}defsend_to_slack(state):qs_summarystate[qs_summary]# Add fxn: report report_generation(qs_summary)reportfoo bar bazreturn{report:report}qs_builderStateGraph(QuestionSummarizationState,output_schemaQuestionSummarizationOutputState)qs_builder.add_node(generate_summary,generate_summary)qs_builder.add_node(send_to_slack,send_to_slack)qs_builder.add_edge(START,generate_summary)qs_builder.add_edge(generate_summary,send_to_slack)qs_builder.add_edge(send_to_slack,END)graphqs_builder.compile()display(Image(graph.get_graph().draw_mermaid_png()))Adding sub graphs to our parent graph 将子图添加到父图Now, we can bring it all together.现在我们可以将所有内容整合起来。We create our parent graph withEntryGraphState.我们使用EntryGraphState创建父图。And we add our sub-graphs as nodes!并将我们的子图作为节点添加进去entry_builder.add_node(question_summarization, qs_builder.compile()) entry_builder.add_node(failure_analysis, fa_builder.compile())# Entry GraphclassEntryGraphState(TypedDict):raw_logs:List[Log]cleaned_logs:Annotated[List[Log],add]# This will be USED BY in BOTH sub-graphsfa_summary:str# This will only be generated in the FA sub-graphreport:str# This will only be generated in the QS sub-graphprocessed_logs:Annotated[List[int],add]# This will be generated in BOTH sub-graphsBut, why doescleaned_logshave a reducer if it only goesintoeach sub-graph as an input?但为什么cleaned_logs需要一个归约器reducer而它仅作为输入传入每个子图It is not modified.它并未被修改。cleaned_logs: Annotated[List[Log], add] # This will be USED BY in BOTH sub-graphsThis is because the output state of the subgraphs will containall keys, even if they are unmodified.这是因为子图的输出状态将包含所有键即使它们未被修改。The sub-graphs are run in parallel.子图是并行运行的。Because the parallel sub-graphs return the same key, it needs to have a reducer likeoperator.addto combine the incoming values from each sub-graph.由于并行子图返回相同的键因此需要一个类似operator.add的归约器以合并各子图传入的值。But, we can work around this by using another concept we talked about before.但我们可以借助之前讨论过的另一个概念来规避此问题。We can simply create an output state schema for each sub-graph and ensure that the output state schema contains different keys to publish as output.我们可以为每个子图简单地创建一个输出状态结构并确保该输出状态结构包含不同的键以便作为输出发布。We don’t actually need each sub-graph to outputcleaned_logs.我们实际上并不需要每个子图都输出cleaned_logs。# Entry GraphclassEntryGraphState(TypedDict):raw_logs:List[Log]cleaned_logs:List[Log]fa_summary:str# This will only be generated in the FA sub-graphreport:str# This will only be generated in the QS sub-graphprocessed_logs:Annotated[List[int],add]# This will be generated in BOTH sub-graphsdefclean_logs(state):# Get logsraw_logsstate[raw_logs]# Data cleaning raw_logs - docscleaned_logsraw_logsreturn{cleaned_logs:cleaned_logs}entry_builderStateGraph(EntryGraphState)entry_builder.add_node(clean_logs,clean_logs)entry_builder.add_node(question_summarization,qs_builder.compile())entry_builder.add_node(failure_analysis,fa_builder.compile())entry_builder.add_edge(START,clean_logs)entry_builder.add_edge(clean_logs,failure_analysis)entry_builder.add_edge(clean_logs,question_summarization)entry_builder.add_edge(failure_analysis,END)entry_builder.add_edge(question_summarization,END)graphentry_builder.compile()fromIPython.displayimportImage,display# Setting xray to 1 will show the internal structure of the nested graphdisplay(Image(graph.get_graph(xray1).draw_mermaid_png()))# Dummy logsquestion_answerLog(id1,questionHow can I import ChatOllama?,answerTo import ChatOllama, use: from langchain_community.chat_models import ChatOllama.,)question_answer_feedbackLog(id2,questionHow can I use Chroma vector store?,answerTo use Chroma, define: rag_chain create_retrieval_chain(retriever, question_answer_chain).,grade0,graderDocument Relevance Recall,feedbackThe retrieved documents discuss vector stores in general, but not Chroma specifically,)raw_logs[question_answer,question_answer_feedback]graph.invoke({raw_logs:raw_logs}){raw_logs: [{id: 1, question: How can I import ChatOllama?, answer: To import ChatOllama, use: from langchain_community.chat_models import ChatOllama.}, {id: 2, question: How can I use Chroma vector store?, answer: To use Chroma, define: rag_chain create_retrieval_chain(retriever, question_answer_chain)., grade: 0, grader: Document Relevance Recall, feedback: The retrieved documents discuss vector stores in general, but not Chroma specifically}], cleaned_logs: [{id: 1, question: How can I import ChatOllama?, answer: To import ChatOllama, use: from langchain_community.chat_models import ChatOllama.}, {id: 2, question: How can I use Chroma vector store?, answer: To use Chroma, define: rag_chain create_retrieval_chain(retriever, question_answer_chain)., grade: 0, grader: Document Relevance Recall, feedback: The retrieved documents discuss vector stores in general, but not Chroma specifically}], fa_summary: Poor quality retrieval of Chroma documentation., report: foo bar baz, processed_logs: [failure-analysis-on-log-2, summary-on-log-1, summary-on-log-2]}LangSmithLet’s look at the LangSmith trace:我们来看 LangSmith 追踪结果https://smith.langchain.com/public/f8f86f61-1b30-48cf-b055-3734dfceadf2/rhttps://smith.langchain.com/public/f8f86f61-1b30-48cf-b055-3734dfceadf2/r
返回列表