前言
本文主要介绍了基于python langchain 的基础开发概念。是一篇新人入门教程。大模型爆火不得不让大家参与进来,Cursor 刚问世的时候去试用它觉得惊为天人,后来deepseek 面世,又带动了一波热潮。作为一名程序员从开始去使用,到去了解,并试图开发自己的应用,拥抱变化,更新知识才能在这条路上走的更远。
一个最简单的模型调用
代码案例
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
import os
ARK_API_KEY = os.getenv('ARK_API_KEY')
# 1. 构造模型调用
llm = ChatOpenAI(
# 环境变量中配置您的API Key
openai_api_key=ARK_API_KEY,
# 替换为您需要调用的模型服务Base Url
openai_api_base="https://ark.cn-beijing.volces.com/api/v3",
# 替换为您创建推理接入点 ID
model_name="doubao-1-5-lite-32k-250115")
# 2. 准备提示模板
prompt = PromptTemplate(
template="根据用户需求推荐书籍。\n用户需求:{query}\n",
input_variables=["query"])
# 3. 构建处理链
chain = prompt | llm | StrOutputParser()
# 4. 执行查询
try:
result = chain.invoke({"query": "我想找一本2010年后出版的科幻小说,主题关于人工智能,有深刻的哲学思考"})
print(result)
except Exception as e:
print(f"处理出错:{str(e)}")
在上面的代码中我们做了一下几件事
- 构建了一个 大模型 llm 的对象
- 生成了一个提示语模板
- 把以上两个串起来,学术名词叫 LCEL(LangChain Expression Language)
- 最后一步就是执行
AI 运行结束会 打印这样的结果
《三体》 :刘慈欣著。虽然它并非完全聚焦于人工智能哲学探讨,但其中智子这一人工智能角色极具深度,它与人类的互动、对人类社会和宇宙格局的影响,引发了诸多关于科技、伦理、人类命运等深刻哲学思考,出版于2006年。
名词解释
ChatOpenAI() 这里是一个通用大模型 构造函数 我们传入相应的参数就可以使用对应的大模型,我这里例子是 字节 的豆包大模型。当然你把参数换一下就可以无缝切换到其他大模型
prompt 提示词模板,告诉大模型需要做什么,好的提示词能让AI 更好的思考,后面会详细讲。
query 是一个模板占位符 ,通过后续的invoke 把 query 的值替换进去
chain 是一个Langchain 的数据处理链,把大模型,提示词等一系列东西组装起来
增加结构化输出
前面的输出是纯文字的,很多时候我们为了方便后续操作,需要它把返回值变成JSON 格式 类似
{
"title": "三体",
"author": "刘慈欣",
"year": "2006"
}
基于上述需求,我们需要增加一些内容
from pydantic import BaseModel, Field
from langchain_core.output_parsers import PydanticOutputParser
# 1. 定义输出结构
class BookRecommendation(BaseModel):
"""书籍推荐信息"""
title: str = Field(description="推荐书籍的标题")
author: str = Field(description="书籍作者")
year: int = Field(description="出版年份")
genres: List[str] = Field(description="书籍所属的流派列表")
reason: str = Field(description="推荐理由")
# 2. 创建解析器
parser = PydanticOutputParser(pydantic_object=BookRecommendation)
修改提示词模板和处理链
# 3. 准备提示模板
prompt = PromptTemplate(
template="根据用户需求推荐书籍。\n{format_instructions}\n用户需求:{query}\n",
input_variables=["query"],
partial_variables={
"format_instructions": parser.get_format_instructions()
})
# 4. 构建处理链
chain = prompt | llm | StrOutputParser() | parser
增加输出
print("推荐书籍:")
print(f"标题:{result.title}")
print(f"作者:{result.author}")
print(f"年份:{result.year}")
print(f"流派:{', '.join(result.genres)}")
print(f"推荐理由:{result.reason}")
会有如下打印
推荐书籍:
标题:《三体》
作者:刘慈欣
年份:2015
流派:科幻
推荐理由:这部小说包含了人工智能相关元素,如智子等。它有着深刻的哲学思考,探讨了人类文明、道德、生存等诸多哲学层面的问题,对人工智能在宇宙中的角色和影响有着独特的见解,是一部非常经典的科幻作品。
parser.get_format_instructions() 这里实际上就是加了一些预定的提示词,看起来像这样
The output should be formatted as a JSON instance that conforms to the JSON schema below (返回的输出需要按照下面的json格式返回) 填充到 PromptTemplate 里的template 参数中
{
"description": "书籍推荐信息",
"properties": {"title":
{
"description": "推荐书籍的标题",
"title": "Title",
"type": "string"
}
...... 其他字段省略
}
当然我们也可以完全手写它,效果是一样的。我们使用上面的特性就是为了让代码风格更加统一,语义更加明确。
提示工程
提示工程 简单的来说就是告诉大模型要干什么,怎么干,以及注意事项等等
提示模板
PromptTemplate
前面已经用到过了,这里简单讲一下
# 定义模板
template = "用 {language} 回答:请解释什么是 {concept}?"
prompt = PromptTemplate(
input_variables=["concept"], # 运行时需传入 concept
template=template,
partial_variables={"language": "中文"}, # 预填充 language
template_format="f-string",
validate_template=True
)
# 使用
final_prompt = prompt.format(concept="人工智能")
print(final_prompt)
template 模板字符串, 里面包含各种变量
input_variables 运行时变量,在 chain.invoke({concept:”人工智能“}) 作为参数传进来
partial_variables 预填充变量,模板生成时就填充进去了,可以是一段逻辑生成的字符串,例如上面例子的 parser.get_format_instructions()
template_format 模板格式,默认是 f-string 也可以是其他的,暂时没有接触到
validate_template 模板格式强验证
ChatPromptTemplate
作为消息类型的模板,每条消息包含角色 和消息内容
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI
chat_template = ChatPromptTemplate.from_messages([
SystemMessagePromptTemplate.from_template(
"你是一个专业的翻译助手,擅长将{source_lang}翻译成{dest_lang}, 对输入的文本进行翻译"),
HumanMessagePromptTemplate.from_template("{text}")
])
final_prompt = chat_template.format(source_lang="中文",
dest_lang="英语",
text="橘子")
print(final_prompt)
打印结果是
System: 你是一个专业的翻译助手,擅长将中文翻译成英语, 对输入的文本进行翻译
Human: 橘子
System 系统消息,用于设定对话的上下文背景,和设定模型在会话中的角色
Human 用户消息,是用户输入的文字
AI 他是用的 AIMessagePromptTemplate 用于表示AI的 历史消息 (比如多轮对话中的先前回复)这里目前用不到
Few-Shot,One-Shot 和 Zero-Shot
前两个的意思是给大模型一定的提示案例,最后一个是完全不给案例,靠大模型自己理解 举个例子
Zero-Shot
- 任务描述:将英文翻译成中文
- 输入:how are you ?
- 输出 :你好吗
One-Shot
- 任务描述:将英文翻译成中文
- 输入:how are you ? 同时有一个例子可以参考
- English: "Good morning!" → Chinese: "早上好!"
- 输出 :你好吗
Few-Shot
- 任务描述:将英文翻译成中文
- 输入:how are you ? 同时有几个例子可以参考
- English: "Good morning!" → Chinese: "早上好!"
- English: "See you tomorrow." → Chinese: "明天见。"
- 输出 :你好吗
few-shot 和one-shot 会给与大模型相关的例子帮助起思考并解决问题。
具体写法
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_openai import ChatOpenAI
import os
llm = ChatOpenAI(
openai_api_key=os.environ.get("ARK_API_KEY"),
openai_api_base="https://ark.cn-beijing.volces.com/api/v3",
model_name="doubao-1-5-lite-32k-250115",
temperature=0)
sentiment_examples = [{
"input": "这电影太棒了",
"output": "积极"
}, {
"input": "服务非常糟糕",
"output": "消极"
}, {
"input": "中规中矩的体验",
"output": "中性"
}]
sentiment_prompt = PromptTemplate(input_variables=["input", "output"],
template="输入:{input}\n情感:{output}")
sentiment_few_shot = FewShotPromptTemplate(examples=sentiment_examples,
example_prompt=sentiment_prompt,
prefix="根据输入文本判断情感倾向",
suffix="输入:{input}\n情感:",
input_variables=["input"])
if __name__ == "__main__":
full_prompt = sentiment_few_shot.format(input="这餐厅的菜品很有创意")
response = llm.invoke(full_prompt)
print(full_prompt)
print(response.content)
输出
根据输入文本判断情感倾向
输入:这电影太棒了
情感:积极
输入:服务非常糟糕
情感:消极
输入:中规中矩的体验
情感:中性
输入:这餐厅的菜品很有创意
情感:
积极
简单来说就是给 FewShotPromptTemplate 一个格式化的样例帮助其回答问题。 例子是 sentiment_examples ,通过 sentiment_prompt 格式化数据 传给 FewShotPromptTemplate,展现为中间这3个输出。 最后的 "积极" 是 llm.invoke 的结果
举个例子 ragflow 有个默认包含的Text To Sql 模板,想要运行的话里面有3要素
- 数据库定义
- 数据库字段描述
- 数据库QA知识库 (这里就相当于Few-Shot)举例其中一条数据如下
Question: Find the product with the highest price
Answer: SELECT ProductName, Price FROM Products ORDER BY Price DESC LIMIT 1;
思维链
Cot
Chain of Thought 就是给大模型提供一定推理步骤,就能够显著提高它进行复杂推理的能力
下面是一个简单的例子
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
import os
llm = ChatOpenAI(
openai_api_key=os.environ.get("ARK_API_KEY"),
openai_api_base="https://ark.cn-beijing.volces.com/api/v3",
model_name="doubao-1-5-lite-32k-250115",
temperature=0)
cot_prompt = PromptTemplate.from_template(
"分步骤解决这个数学问题:{question}\n"
"首先,分解问题要素:\n"
"其次,应用公式计算:\n"
"最后,验证结果合理性:"
)
cot_chain = cot_prompt | llm | StrOutputParser()
# 执行示例
print(cot_chain.invoke({"question": "如果苹果5元/斤,买3斤送1斤,小明有50元,最多能买多少斤?"}))
输出如下
首先,分解问题要素:
- 苹果单价为5元/斤。
- 存在买3斤送1斤的优惠活动。
- 小明有50元。
其次,应用公式计算:
- 50元原本能买的斤数:50÷5 = 10斤。
- 10斤里面有几个3斤:10÷3 = 3(组)......1(斤),即可以组成3组买3送1。
- 送的斤数:3×1 = 3斤。
- 总共能买的斤数:10 + 3 = 13斤。
最后,验证结果合理性:
- 按照买3送1的规则,买9斤送3斤,此时花费9×5 = 45元,还剩50 - 45 = 5元,还能再买1斤,总共就是9 + 3 + 1 = 13斤,结果合理。
综上,小明最多能买13斤。
就上面这个问题而言,过于简单,不需要推理步骤也能得出正确的结果,后面发现复杂的问题可以试试这种方案
ToT
Tree of Thought 是Cot 的升级版,它的主要运行步骤是
理解问题 -> 生成多个候选方案 -> 评估每个方案 -> 给出最终结果
graph TD
I[问题或任务] --> T1{理解问题}
T1 -->|路径1| R1[结果1]
T1 -->|路径2| R2[结果2]
T1 -->|路径3| R3[结果3]
R1 --> E[选择最佳结果]
R2 --> E
R3 --> E
代理 agent
单agent
在没有AI Agent 之前 LLM 在进行 "推理" 和 "行动" 时候是互相独立的过程。 而现在他们可以是相互作用的过程,推理完成进行行动,然后根据行动结果调整决策再次行动,依次循环直到任务完成
这里就不得不提React框架了,比如煮鸡蛋,这是一个简化版的例子
任务开始
第一轮
思考 用户需要溏心蛋,关键在温度和时间控制。应先确认水是否沸腾
行动 调用「水温检测」工具,
观察 发现当前水温仅70°C
第二轮
思考 水温不足,需要继续加热到100 度
行动 持续检测水温直至100°C 后提醒用户 放入鸡蛋
观察 水温达到100°C
第三轮
思考 现在放入鸡蛋,同时设置好定时闹钟
行动 放入鸡蛋,并设好闹钟
观察 闹钟响
任务结束
LangChain 的 Agent 类是一种ReAct 框架的实现 ,下面就来具体操作一下
from langchain_community.utilities import SearchApiAPIWrapper
from langchain.agents import create_openai_tools_agent
from langchain.agents import AgentExecutor
from langchain.agents import Tool
from langchain_community.agent_toolkits import FileManagementToolkit
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
import os
llm = ChatOpenAI(
openai_api_key=os.environ.get("ARK_API_KEY"),
openai_api_base="https://ark.cn-beijing.volces.com/api/v3",
model_name="doubao-1-5-lite-32k-250115",
temperature=0)
tools = FileManagementToolkit(selected_tools=["write_file"]).get_tools()
write_file_tool = tools[0]
search = SearchApiAPIWrapper(engine="bing")
search_tool = Tool(
name="search_tool",
func=search.run,
description="useful for when you need to ask with search",
)
tools = [write_file_tool, search_tool]
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有用的助手"),
MessagesPlaceholder("chat_history", optional=True), ("human", "{input}"),
MessagesPlaceholder("agent_scratchpad")
])
agent = create_openai_tools_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
response = agent_executor.invoke(
{"input": "网上搜索 langchain 相关资料, 并将结果写入langchain.txt中"})
输出如下
> Entering new AgentExecutor chain...
Invoking: `search_tool` with `网上搜索 langchain 相关资料`
LangChain为RAG应用程序提供了所有的构建模块-从简单到复杂. 本文档部分涵盖了与检索步骤相关的所有内容,例如数据的获取. 虽然听起来很简单,但可能有微妙的复杂性 ...
检索是指根据用户的问题去向量数据库中搜索与问题相关的文档内容,当我们访问和查询向量数据库时可能会运用到如下几种技术:. 基本语义相似度(Basic ...
Invoking: `write_file` with `{'file_path': 'langchain.txt', 'text': 'LangChain为RAG应用程序提供了所有的构建模块-从简单到复杂. 本文档部分涵盖了与检索步骤相关的所有内容,例如数据的获取. 虽然听起来很简单,但可能有微妙的复杂性 ...\n检索是指根据用户的问题去向量数据库中搜索与问题相关的文档内容,当我们访问和查询向量数据库时可能会运用到如下几种技术:. 基本语义相似度(Basic', 'append': False}`
File written successfully to langchain.txt.已成功将网上搜索到的langchain相关资料写入langchain.txt文件中。
> Finished chain.
这里构造了两个tool :
-
search_tool负责搜索 ,使用条件是 searchapi 官网上 注册一个账号,拿到Key 放到 环境变量里 SERPAPI_API_KEY 就可以使用了 -
write_file_tool是一个 文件写入的工具
llm 通过指令解析到2个内容,一个搜索,一个 写入文件并关联上2个tool。我们只是把关联的工具提供给了大模型 ,他会自己去识别用户的意图,以及需要调用哪些工具,并不需要人为设定规则。
上述例子满足了AI Agent 4要素中的3个 分别是 规划、 行动、工具 ,还缺一个就是 记忆,现在我们把记忆 补上。
下面是一个Langgraph 的例子,官方推荐用法
import uuid
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
import os
llm = ChatOpenAI(
openai_api_key=os.environ.get("ARK_API_KEY"),
openai_api_base="https://ark.cn-beijing.volces.com/api/v3",
model_name="doubao-1-5-lite-32k-250115",
temperature=0)
@tool
def get_user_age(name: str) -> str:
"""Use this tool ONLY when explicitly asked about age."""
if "bob" in name.lower():
return "42 years old"
return "41 years old"
memory = MemorySaver()
app = create_react_agent(
llm,
tools=[get_user_age],
checkpointer=memory,
debug=False
)
input_message = HumanMessage(content="hi! I'm bob. What is my age?")
thread_id = uuid.uuid4()
config = {"configurable": {"thread_id": thread_id}}
result = app.invoke(input={"messages": input_message}, config=config)
print(result["messages"][-1].content)
input_message2 = HumanMessage(content="what's my name")
result = app.invoke(input={"messages": input_message2}, config=config)
print(result["messages"][-1].content)
输出
You are 42 years old.
Your name is bob.
当我们把 debug=True打开时 第一个问题有以下输出,下面时简化的
初始化状态
[0:tasks ] 接收到用户信息 HumanMessage("hi! I'm bob. What is my age?")
[0:writes ] 保存用户输入信息
[0:checkpoint] 输出当前所有消息,目前仅有一条
[1:tasks ] 根据当前所有消息进行推理
[1:writes ] 保存推理结果 AIMessage("调用工具 get_user_age")
[1:checkpoint] [HumanMessage("hi! I'm bob. What is my age?"),
AIMessage("调用工具 get_user_age")]
[2:tasks ] 调用工具 get_user_age
[2:writes ] 保存工具返回结果 ToolMessage("2 years old")
[2:checkpoint] [HumanMessage("hi! I'm bob. What is my age?"),
AIMessage("调用工具 get_user_age"),
ToolMessage("2 years old")]
[3:tasks ] 根据工具返回的信息进行推理
[3:writes ] 保存推理结果 AIMessage("You are 42 years old")
[3:checkpoint] [HumanMessage("hi! I'm bob. What is my age?"),
AIMessage("调用工具 get_user_age"),
ToolMessage("2 years old"),
AIMessage("You are 42 years old")]
如果是调用多个工具,类似上面搜索信息然后存入文件里的,运行顺序类似下面的顺序
[1:task ] 使用当前消息进行推理额
[1:writes ] 保存推理结果 AIMessage("调用工具 toolA")
[1:checkpoint ] [AIMessage("调用工具 toolA")]
[2:task ] 调用工具 toolA
[2:writes ] 保存工具返回结果 ToolMessage("toolA result")
[2:checkpoint ] [AIMessage("调用工具 toolA"),
ToolMessage("toolA result")]
[3:task ] 使用当前消息进行推理额
[3:writes ] 保存推理结果 AIMessage("调用工具 toolB")
[3:checkpoint ] [AIMessage("调用工具 toolA"),
ToolMessage("toolA result"),
AIMessage("调用工具 toolB")]
[4:task ] 调用工具 toolB
[4:writes ] 保存工具返回结果 ToolMessage("toolB result")
[4:checkpoint ] [AIMessage("调用工具 toolA"),
ToolMessage("toolA result"),
AIMessage("调用工具 toolB"),
ToolMessage("toolB result")]
[5:task ] 使用当前消息进行推理额
[5:writes ] 保存推理结果 AIMessage("最终结果")
[5:checkpoint ] [AIMessage("调用工具 toolA"),
ToolMessage("toolA result"),
AIMessage("调用工具 toolB"),
ToolMessage("toolB result"),
AIMessage("最终结果")]
sequenceDiagram
participant U as User
participant A as Agent (LLM)
participant T as Tools
U->>A: Initial input
Note over A: Messages modifier + LLM
loop while tool_calls present
A->>T: Execute tools
T-->>A: ToolMessage for each tool_calls
end
A->>U: Return final state
多Agent
我们来尝试有2 个agent 的例子。这里的场景是有两个agent 模拟两个角色互相讨论问题,一个是市场专家,一个是产品经理,讨论产品研发和推广的问题。
先来看代码
from typing import TypedDict, List
from langgraph.prebuilt import create_react_agent
from langgraph.graph import END, StateGraph
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import HumanMessage, AIMessage
from langchain_openai import ChatOpenAI
import os
# 状态定义
class AgentState(TypedDict):
messages: List[dict] # 必须包含 messages 字段
steps: int
# 初始化 LLM
llm = ChatOpenAI(
openai_api_key=os.environ.get("ARK_API_KEY"),
openai_api_base="https://ark.cn-beijing.volces.com/api/v3",
model_name="doubao-1-5-lite-32k-250115",
temperature=0)
# 创建带消息处理的 Agent
def create_agent(system_prompt: str):
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("placeholder", "{messages}") # 使用标准 messages 占位符
])
return create_react_agent(model=llm, tools=[], state_modifier=prompt)
# 初始化两个角色
marketing_agent = create_agent(
"你是资深市场专家,需要提出突破常规的推广方案。特别注意:1. 结合最新趋势 2. 包含具体执行细节 3. 预算控制在100万以内,以简短的语句回答问题")
pm_agent = create_agent(
"你是技术型产品经理,需要评估:1. 开发成本 2. 技术可行性 3. 与现有系统的兼容性。回答需包含风险评估,以简短的语句回答问题")
# 构建工作流
builder = StateGraph(AgentState)
# 添加节点(需包装返回值)
def run_marketing(state: AgentState):
result = marketing_agent.invoke({"messages": state["messages"]})
last_elm = result["messages"][-1]
new_elm = HumanMessage(content=last_elm.content)
return {
"messages": state["messages"] + [new_elm],
"steps": state["steps"] + 1
}
def run_pm(state: AgentState):
result = pm_agent.invoke({"messages": state["messages"]})
last_elm = result["messages"][-1]
new_elm = HumanMessage(content=last_elm.content)
return {
"messages": state["messages"] + [new_elm],
"steps": state["steps"] + 1
}
builder.add_node("marketing", run_marketing)
builder.add_node("product_manager", run_pm)
# 设置流转逻辑
def decide_next(state: AgentState):
step = state["steps"]
if step >= 4:
return END
if step > 1 and step % 2 == 0:
return "marketing"
else:
return "product_manager"
builder.set_entry_point("marketing")
builder.add_conditional_edges("marketing", decide_next)
builder.add_conditional_edges("product_manager", decide_next)
# 编译工作流
collab_workflow = builder.compile()
# 运行示例(注意初始状态格式)
response = collab_workflow.invoke({
"messages": [HumanMessage(content="如何推广我们的新款智能手表?")],
"steps":0
})
# 打印对话记录
print("\n=== 完整对话 ===")
idx = 0
for msg in response["messages"]:
if idx == 0:
role = "提问"
elif idx == 1:
role = "市场专家"
elif idx % 2 == 0:
role = "产品经理"
else:
role = "市场专家"
print(f"[{role}]: {msg.content}")
idx = idx + 1
先看一下返回结果,根据结果看,我们模拟了两个角色,依次讨论问题,目前是两人各回答两次,通过控制会话轮数可以让他们进行更深入的对话
[提问]:如何推广我们的新款智能手表?
[市场专家]: 利用元宇宙概念,打造虚拟试用场景。在社交媒体举办线上竞赛,奖品为新款手表。与健身博主合作,进行产品植入。预算内制作吸睛视频投流。执行:找技术团队搭建元宇宙场景,联系网红合作洽谈,制作高质量视频并精准投流。
[产品经理]: 1. 开发成本:搭建元宇宙场景找技术团队成本较高,需评估具体开发量及团队收费标准,有超预算风险。
2. 技术可行性:技术团队若有元宇宙场景搭建经验则可行,否则可能面临技术难题,存在技术实现风险。
3. 与现有系统的兼容性:未提及现有系统,若后续涉及与其他系统交互,需评估兼容性,有不兼容风险。
[市场专家]: 简化元宇宙场景为虚拟展示页面,降低开发成本。社交媒体竞赛设参与奖吸引更多人。与健身博主合作,让其佩戴手表展示健身场景植入产品。制作创意视频投流,突出手表功能亮点。执行:找简单页面制作团队搭建虚拟展示,联系网红合作,精心制作视频并精准投流。
[产品经理]: 1. 开发成本:找简单页面制作团队成本降低,但仍需明确具体费用,有成本超预期风险。
2. 技术可行性:搭建虚拟展示页面技术难度降低,一般团队可胜任,技术风险较小。
3. 与现有系统的兼容性:未提及现有系统,若后续有交互需求,存在不兼容风险。
程序执行主要结构是这样的
- 定义langgraph 状态对象,包含一个消息历史和一个步数计数器
- 创建两个agent 并输入特定提示语,比如 ”你是资深市场专“ 等
- 使用
StateGraph设置工作流 - 触发工作流
工作流是这样的,可以使用下面的方法直接导出 mermaid 图表
collab_workflow = builder.compile()
collab_workflow.get_graph().draw_mermaid()
---
config:
flowchart:
curve: linear
---
graph LR;
__start__([开始]):::first
marketing(市场专家)
product_manager(产品经理)
final_response(最终结果)
__end__([结束]):::last
__start__ --> marketing;
final_response --> __end__;
marketing -.-> product_manager;
marketing -.-> final_response;
product_manager -.-> marketing;
product_manager -.-> final_response;
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc
具体业务放在 run_pm 和 run_marketing 运行机制相同,把历史消息放进对应的agent里,并把返回结果追加到消息列表中返回。每次运行都基于之前所有的消息历史进行生成新的答案。达到特定轮次后返回结果并终止任务