图例
1. 图状态
在 LangGraph 中,每个节点都会更新一个共享的图状态。当任何节点被调用时,状态就是该节点的输入。
下面,我们将定义一个状态字典,用以包含任务、计划、步骤和其他变量。
from typing import List
from typing_extensions import TypedDict
class ReWOO(TypedDict):
task: str
plan_string: str
steps: List
results: dict
result: str
2. Plan 计划节点
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
temperature=0,
model="GLM-4-plus",
openai_api_key="your api key",
openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
)
prompt = """For the following task, make plans that can solve the problem step by step. For each plan, indicate \
which external tool together with tool input to retrieve evidence. You can store the evidence into a \
variable #E that can be called by later tools. (Plan, #E1, Plan, #E2, Plan, ...)
Tools can be one of the following:
(1) Google[input]: Worker that searches results from Google. Useful when you need to find short
and succinct answers about a specific topic. The input should be a search query.
(2) LLM[input]: A pretrained LLM like yourself. Useful when you need to act with general
world knowledge and common sense. Prioritize it when you are confident in solving the problem
yourself. Input can be any instruction.
For example,
Task: Thomas, Toby, and Rebecca worked a total of 157 hours in one week. Thomas worked x
hours. Toby worked 10 hours less than twice what Thomas worked, and Rebecca worked 8 hours
less than Toby. How many hours did Rebecca work?
Plan: Given Thomas worked x hours, translate the problem into algebraic expressions and solve
with Wolfram Alpha. #E1 = WolframAlpha[Solve x + (2x − 10) + ((2x − 10) − 8) = 157]
Plan: Find out the number of hours Thomas worked. #E2 = LLM[What is x, given #E1]
Plan: Calculate the number of hours Rebecca worked. #E3 = Calculator[(2 ∗ #E2 − 10) − 8]
Begin!
Describe your plans with rich details. Each Plan should be followed by only one #E, follow th example format strictly.
Task: {task}"""
task = "what is the exact hometown of the 2024 mens australian open winner"
result = model.invoke(prompt.format(task=task))
print(result.content)
Plan: Search for the winner of the 2024 Men's Australian Open. #E1 = Google["2024 Men's Australian Open winner"]
Plan: Once the winner's name is known, search for his exact hometown. #E2 = Google["[Winner's Name] hometown"]
Plan: Verify the accuracy of the hometown information using a reliable source. #E3 = Google["[Winner's Name] biography site:ausopen.com"]
import re
from langchain_core.prompts import ChatPromptTemplate
# Regex to match expressions of the form E#... = ...[...]
regex_pattern = r"Plan:\s*(.+)\s*(#E\d+)\s*=\s*(\w+)\s*\[([^\]]+)\]"
prompt_template = ChatPromptTemplate.from_messages([("user", prompt)])
planner = prompt_template | model
def get_plan(state: ReWOO):
task = state["task"]
result = planner.invoke({"task": task})
# Find all matches in the sample text
matches = re.findall(regex_pattern, result.content)
return {"steps": matches, "plan_string": result.content}
result = get_plan(ReWOO(task=task))
print(result)
{'steps': [("Search for the winner of the 2024 Men's Australian Open tennis tournament. ", '#E1', 'Google', '"2024 Men\'s Australian Open winner"'), ("Once the winner's name is known, search for his exact hometown. ", '#E2', 'Google', '"[Winner\'s Name'), ('Verify the accuracy of the hometown information using a reliable source. ', '#E3', 'Google', '"[Winner\'s Name')], 'plan_string': 'Plan: Search for the winner of the 2024 Men\'s Australian Open tennis tournament. #E1 = Google["2024 Men\'s Australian Open winner"]\nPlan: Once the winner\'s name is known, search for his exact hometown. #E2 = Google["[Winner\'s Name] hometown"]\nPlan: Verify the accuracy of the hometown information using a reliable source. #E3 = Google["[Winner\'s Name] biography site:officialtournamentwebsite.com"]'}
3. execution 计划执行节点
import os
os.environ["TAVILY_API_KEY"] = "your api key"
from langchain_community.tools.tavily_search import TavilySearchResults
search = TavilySearchResults()
def _get_current_task(state: ReWOO):
if "results" not in state or state["results"] is None:
return 1
if len(state["results"]) == len(state["steps"]):
return None
else:
return len(state["results"]) + 1
def tool_execution(state: ReWOO):
"""Worker node that executes the tools of a given plan."""
_step = _get_current_task(state)
_, step_name, tool, tool_input = state["steps"][_step - 1]
_results = (state["results"] or {}) if "results" in state else {}
for k, v in _results.items():
tool_input = tool_input.replace(k, v)
if tool == "Google":
result = search.invoke(tool_input)
elif tool == "LLM":
result = model.invoke(tool_input)
else:
raise ValueError
_results[step_name] = str(result)
return {"results": _results}
4. solve 问题解决节点
solve_prompt = """Solve the following task or problem. To solve the problem, we have made step-by-step Plan and \
retrieved corresponding Evidence to each Plan. Use them with caution since long evidence might \
contain irrelevant information.
{plan}
Now solve the question or task according to provided Evidence above. Respond with the answer
directly with no extra words.
Task: {task}
Response:"""
def solve(state: ReWOO):
plan = ""
for _plan, step_name, tool, tool_input in state["steps"]:
_results = (state["results"] or {}) if "results" in state else {}
for k, v in _results.items():
tool_input = tool_input.replace(k, v)
step_name = step_name.replace(k, v)
plan += f"Plan: {_plan}\n{step_name} = {tool}[{tool_input}]"
prompt = solve_prompt.format(plan=plan, task=state["task"])
result = model.invoke(prompt)
return {"result": result.content}
5. graph 各个节点连接
def _route(state):
_step = _get_current_task(state)
if _step is None:
# We have executed all tasks
return "solve"
else:
# We are still executing tasks, loop back to the "tool" node
return "tool"
from langgraph.graph import END, StateGraph, START
graph = StateGraph(ReWOO)
graph.add_node("plan", get_plan)
graph.add_node("tool", tool_execution)
graph.add_node("solve", solve)
graph.add_edge("plan", "tool")
graph.add_edge("solve", END)
graph.add_conditional_edges("tool", _route)
graph.add_edge(START, "plan")
app = graph.compile()
graph 可视化
from IPython.display import Image, display
try:
display(Image(app.get_graph(xray=True).draw_mermaid_png()))
except Exception:
# This requires some extra dependencies and is optional
pass
6. 示例
for s in app.stream({"task": task}):
print(s)
print("---")
{'plan': {'plan_string': 'Plan: Search for the winner of the 2024 Men\'s Australian Open. #E1 = Google["2024 Men\'s Australian Open winner"]\nPlan: Once the winner\'s name is known, search for his exact hometown. #E2 = Google["[Winner\'s Name] hometown"]\nPlan: Verify the information to ensure accuracy. #E3 = LLM["Verify the hometown of [Winner\'s Name]"]', 'steps': [("Search for the winner of the 2024 Men's Australian Open. ", '#E1', 'Google', '"2024 Men\'s Australian Open winner"'), ("Once the winner's name is known, search for his exact hometown. ", '#E2', 'Google', '"[Winner\'s Name'), ('Verify the information to ensure accuracy. ', '#E3', 'LLM', '"Verify the hometown of [Winner\'s Name')]}}
---
{'tool': {'results': {'#E1': '[{\'url\': \'https://vsin.com/wp-content/uploads/2024/01/Circa-Betting-Sheets-1-18-24.pdf\', \'content\': "2024 MEN\'S AUSTRALIAN OPEN WINNER. PLAYER VS FIELD ODDS. FIELD. PLAYER. EV 42202 -130 JANNIK SINNER. 42203 +365 42204 -470 DANIIL MEDVEDEV."}, {\'url\': \'https://langchain-ai.github.io/langgraph/tutorials/rewoo/rewoo/\', \'content\': "... 2024 Men\'s Australian Open winner. #E1 = Google[2024 Men\'s Australian Open winner]\\\\nPlan: Once the winner is identified, search for their exact hometown"}, {\'url\': \'https://vsin.com/wp-content/uploads/2024/01/circa-betting-sheets-1-22-24.pdf\', \'content\': "2024 MEN\'S AUSTRALIAN OPEN WINNER. PLAYER. 42201. 42203. PLAYER VS FIELD ODDS. FIELD. EV 42202 -130 JANNIK SINNER. +365 42204 -470 DANIIL"}, {\'url\': \'https://www.bets.com.au/tennis/australian-open/2024-mens-australian-open-winner-betting-odds-20230206-0009/\', \'content\': "2024 Men\'s Australian Open Winner Betting Odds - Who will win the 2024 Australian Open? Randwick Betting Tips for September 21, 2024 - Race-By-Race preview for 7 Stakes day Caulfield Betting Tips for September 21, 2024 - Race-By-Race preview for Underwood Stakes day Belmont Betting Tips for September 21, 2024 - Vast to claim feature Underwood Stakes 2024 Betting Tips - Place vs Pericles Geelong vs Brisbane Tips - Cats to play second Grand Final in three years Melbourne Victory vs Adelaide United Tips, Predictions & Live Stream - Victory backed to make Australia Cup final South Melbourne vs Macarthur FC Tips, Predictions & Live Stream - Macarthur to reach Australia Cup final"}, {\'url\': \'https://www.happi.com/spf-365/\', \'content\': "This long-term collaboration with the 2024 men\'s Australian Open winner will leverage La Roche-Posay\'s Anthelios brand. On the Daily. Live"}]'}}}
---
{'tool': {'results': {'#E1': '[{\'url\': \'https://vsin.com/wp-content/uploads/2024/01/Circa-Betting-Sheets-1-18-24.pdf\', \'content\': "2024 MEN\'S AUSTRALIAN OPEN WINNER. PLAYER VS FIELD ODDS. FIELD. PLAYER. EV 42202 -130 JANNIK SINNER. 42203 +365 42204 -470 DANIIL MEDVEDEV."}, {\'url\': \'https://langchain-ai.github.io/langgraph/tutorials/rewoo/rewoo/\', \'content\': "... 2024 Men\'s Australian Open winner. #E1 = Google[2024 Men\'s Australian Open winner]\\\\nPlan: Once the winner is identified, search for their exact hometown"}, {\'url\': \'https://vsin.com/wp-content/uploads/2024/01/circa-betting-sheets-1-22-24.pdf\', \'content\': "2024 MEN\'S AUSTRALIAN OPEN WINNER. PLAYER. 42201. 42203. PLAYER VS FIELD ODDS. FIELD. EV 42202 -130 JANNIK SINNER. +365 42204 -470 DANIIL"}, {\'url\': \'https://www.bets.com.au/tennis/australian-open/2024-mens-australian-open-winner-betting-odds-20230206-0009/\', \'content\': "2024 Men\'s Australian Open Winner Betting Odds - Who will win the 2024 Australian Open? Randwick Betting Tips for September 21, 2024 - Race-By-Race preview for 7 Stakes day Caulfield Betting Tips for September 21, 2024 - Race-By-Race preview for Underwood Stakes day Belmont Betting Tips for September 21, 2024 - Vast to claim feature Underwood Stakes 2024 Betting Tips - Place vs Pericles Geelong vs Brisbane Tips - Cats to play second Grand Final in three years Melbourne Victory vs Adelaide United Tips, Predictions & Live Stream - Victory backed to make Australia Cup final South Melbourne vs Macarthur FC Tips, Predictions & Live Stream - Macarthur to reach Australia Cup final"}, {\'url\': \'https://www.happi.com/spf-365/\', \'content\': "This long-term collaboration with the 2024 men\'s Australian Open winner will leverage La Roche-Posay\'s Anthelios brand. On the Daily. Live"}]', '#E2': '[{\'url\': \'https://www.randompicker.com/blog/how-to-announce-winners/\', \'content\': \'The winner announcement is not just a formality; it is a key part of the contest lifecycle that can influence the participant experience and brand perception. Include RandomPicker.com’s public record link to announce the giveaway winner. Your entry in our [contest name] has been selected as the winner. Before you publicly announce the winner of a contest, wait for the winner to respond and accept the prize. Winner Announcement Write a detailed post highlighting the contest, the winner, and the prize. Instagram Contest Winner Announcement We are happy to announce that [winner’s name] is the winner of our [contest name]! Keep your contest landing page updated with the winner’s information, drawing information, a link to the public record, and a thank you message to all participants.\'}, {\'url\': \'https://pickerwheel.com/\', \'content\': "It will decide 1 winner among the list of candidates\' names from a contest after spinning the wheel. You can also use the wheel together with a countdown timer to carry out more interactive activities. 12.2. Elimination Mode. It picks a random name alternately by eliminating the inputs one by one. The result will be temporarily removed from"}, {\'url\': \'https://namepicker.net/\', \'content\': \'Name Picker is the free website with giveaways tools for Facebook, Instagram, YouTube and useful online tools. Name Picker is an easy-to-use online tool to quickly select a name from a list of names at random. You can add an unlimited number of entries and draw multiple random winners.\'}, {\'url\': \'https://www.random-name-generator.com/random-name-picker\', \'content\': \'Random Name Picker - Submit a list and draw a winner - Random-Name-Generator.Com Random Name Picker Random Name Picker - Submit a list and draw a winner Fill in the names and draw a winner Picked by: https://www.random-name-generator.com/random-name-picker WHAT CAN I USE THIS RANDOM NAME PICKER FOR? Prize drawings: If you’re running a contest or giveaway, a random name picker can help you choose the winners fairly and efficiently. Whether you’re a teacher, event planner, or just looking for a way to add some excitement to your day, a random name picker is a useful tool to have on hand. Random Name Picker instantly draws one or multiple random winners from your submitted list. IS THIS NAME PICKER REALLY RANDOM?\'}, {\'url\': \'https://www.vancopayments.com/non-profit/blog/raffle-winner-announcement\', \'content\': \'Download eBook](https://www.vancopayments.com/education/the-comprehensive-guide-to-school-budget-planning?utm_campaign=Feature_Resource_CTA&utm_source=Website-CTA&utm_medium=organic&utm_content=Budget-Planning) [![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fwww.vancopayments.com%2Fhs-fs%2Fhubfs%2FMJTW-assets%2Fchild-care%2FChild-CareK12-Pro.jpg%3Fwidth%3D400%26height%3D246%26name%3DChild-CareK12-Pro.jpg&pos_id=img-QyL7FaKF-1733735530387) A Guide to Before and After Care Management Establish strong policies, simplify billing, manage difficult parents, promote student well-being and more with this comprehensive guide. Download eBook](https://www.vancopayments.com/child-care/resource/how-to-manage-before-and-after-school-child-care-for-k12-schools?utm_campaign=Feature_Resource_CTA&utm_source=Website-CTA&utm_medium=organic&utm_content=After-School-eBook) [![Image 5: Nonprofit-Kit_featured_image](https://i-blog.csdnimg.cn/img_convert/fe0a1c232215124dcf928724fde80773.jpeg) 100+ Fundraising Tools to Make Donations Skyrocket Struggling with fundraising? Use our free raffle winner announcement templates and examples to effectively notify participants and celebrate your giveaway success! Email announcements: Use a fun subject line like “You’re a Winner!” Personalize the message by addressing the recipient directly, and include the prize announcement, raffle results and winner notification. We’ve created several vibrant, eye-catching social media announcement images that you can use to highlight raffle or contest winners for your nonprofit.\'}]'}}}
---
{'tool': {'results': {'#E1': '[{\'url\': \'https://vsin.com/wp-content/uploads/2024/01/Circa-Betting-Sheets-1-18-24.pdf\', \'content\': "2024 MEN\'S AUSTRALIAN OPEN WINNER. PLAYER VS FIELD ODDS. FIELD. PLAYER. EV 42202 -130 JANNIK SINNER. 42203 +365 42204 -470 DANIIL MEDVEDEV."}, {\'url\': \'https://langchain-ai.github.io/langgraph/tutorials/rewoo/rewoo/\', \'content\': "... 2024 Men\'s Australian Open winner. #E1 = Google[2024 Men\'s Australian Open winner]\\\\nPlan: Once the winner is identified, search for their exact hometown"}, {\'url\': \'https://vsin.com/wp-content/uploads/2024/01/circa-betting-sheets-1-22-24.pdf\', \'content\': "2024 MEN\'S AUSTRALIAN OPEN WINNER. PLAYER. 42201. 42203. PLAYER VS FIELD ODDS. FIELD. EV 42202 -130 JANNIK SINNER. +365 42204 -470 DANIIL"}, {\'url\': \'https://www.bets.com.au/tennis/australian-open/2024-mens-australian-open-winner-betting-odds-20230206-0009/\', \'content\': "2024 Men\'s Australian Open Winner Betting Odds - Who will win the 2024 Australian Open? Randwick Betting Tips for September 21, 2024 - Race-By-Race preview for 7 Stakes day Caulfield Betting Tips for September 21, 2024 - Race-By-Race preview for Underwood Stakes day Belmont Betting Tips for September 21, 2024 - Vast to claim feature Underwood Stakes 2024 Betting Tips - Place vs Pericles Geelong vs Brisbane Tips - Cats to play second Grand Final in three years Melbourne Victory vs Adelaide United Tips, Predictions & Live Stream - Victory backed to make Australia Cup final South Melbourne vs Macarthur FC Tips, Predictions & Live Stream - Macarthur to reach Australia Cup final"}, {\'url\': \'https://www.happi.com/spf-365/\', \'content\': "This long-term collaboration with the 2024 men\'s Australian Open winner will leverage La Roche-Posay\'s Anthelios brand. On the Daily. Live"}]', '#E2': '[{\'url\': \'https://www.randompicker.com/blog/how-to-announce-winners/\', \'content\': \'The winner announcement is not just a formality; it is a key part of the contest lifecycle that can influence the participant experience and brand perception. Include RandomPicker.com’s public record link to announce the giveaway winner. Your entry in our [contest name] has been selected as the winner. Before you publicly announce the winner of a contest, wait for the winner to respond and accept the prize. Winner Announcement Write a detailed post highlighting the contest, the winner, and the prize. Instagram Contest Winner Announcement We are happy to announce that [winner’s name] is the winner of our [contest name]! Keep your contest landing page updated with the winner’s information, drawing information, a link to the public record, and a thank you message to all participants.\'}, {\'url\': \'https://pickerwheel.com/\', \'content\': "It will decide 1 winner among the list of candidates\' names from a contest after spinning the wheel. You can also use the wheel together with a countdown timer to carry out more interactive activities. 12.2. Elimination Mode. It picks a random name alternately by eliminating the inputs one by one. The result will be temporarily removed from"}, {\'url\': \'https://namepicker.net/\', \'content\': \'Name Picker is the free website with giveaways tools for Facebook, Instagram, YouTube and useful online tools. Name Picker is an easy-to-use online tool to quickly select a name from a list of names at random. You can add an unlimited number of entries and draw multiple random winners.\'}, {\'url\': \'https://www.random-name-generator.com/random-name-picker\', \'content\': \'Random Name Picker - Submit a list and draw a winner - Random-Name-Generator.Com Random Name Picker Random Name Picker - Submit a list and draw a winner Fill in the names and draw a winner Picked by: https://www.random-name-generator.com/random-name-picker WHAT CAN I USE THIS RANDOM NAME PICKER FOR? Prize drawings: If you’re running a contest or giveaway, a random name picker can help you choose the winners fairly and efficiently. Whether you’re a teacher, event planner, or just looking for a way to add some excitement to your day, a random name picker is a useful tool to have on hand. Random Name Picker instantly draws one or multiple random winners from your submitted list. IS THIS NAME PICKER REALLY RANDOM?\'}, {\'url\': \'https://www.vancopayments.com/non-profit/blog/raffle-winner-announcement\', \'content\': \'Download eBook](https://www.vancopayments.com/education/the-comprehensive-guide-to-school-budget-planning?utm_campaign=Feature_Resource_CTA&utm_source=Website-CTA&utm_medium=organic&utm_content=Budget-Planning) [![Image 4: Child Care K12 Pro](https://i-blog.csdnimg.cn/img_convert/27723b77025c8446e833e14f071f9f0d.jpeg) A Guide to Before and After Care Management Establish strong policies, simplify billing, manage difficult parents, promote student well-being and more with this comprehensive guide. Download eBook](https://www.vancopayments.com/child-care/resource/how-to-manage-before-and-after-school-child-care-for-k12-schools?utm_campaign=Feature_Resource_CTA&utm_source=Website-CTA&utm_medium=organic&utm_content=After-School-eBook) [![Image 5: Nonprofit-Kit_featured_image](https://i-blog.csdnimg.cn/img_convert/fe0a1c232215124dcf928724fde80773.jpeg) 100+ Fundraising Tools to Make Donations Skyrocket Struggling with fundraising? Use our free raffle winner announcement templates and examples to effectively notify participants and celebrate your giveaway success! Email announcements: Use a fun subject line like “You’re a Winner!” Personalize the message by addressing the recipient directly, and include the prize announcement, raffle results and winner notification. We’ve created several vibrant, eye-catching social media announcement images that you can use to highlight raffle or contest winners for your nonprofit.\'}]', '#E3': 'content="It seems like your request is incomplete. To verify the hometown of a specific individual, such as a winner of a competition, award, or any other context, I would need the full name of the person you are referring to. Additionally, if there are any specific details or context you can provide, such as the event they won or the field they are known for, it would help in providing a more accurate response.\\n\\nPlease provide the full name and any relevant details, and I\'ll do my best to assist you!" additional_kwargs={\'refusal\': None} response_metadata={\'token_usage\': {\'completion_tokens\': 106, \'prompt_tokens\': 14, \'total_tokens\': 120, \'completion_tokens_details\': None, \'prompt_tokens_details\': None}, \'model_name\': \'GLM-4-plus\', \'system_fingerprint\': None, \'finish_reason\': \'stop\', \'logprobs\': None} id=\'run-860033fb-04db-40b9-9cf5-041c3b14f470-0\' usage_metadata={\'input_tokens\': 14, \'output_tokens\': 106, \'total_tokens\': 120, \'input_token_details\': {}, \'output_token_details\': {}}'}}}
---
{'solve': {'result': "Jannik Sinner's hometown is San Candido, Italy."}}
---
# Print out the final result
print(s["solve"]["result"])
Jannik Sinner's hometown is San Candido, Italy.
用chatglm模型运行时有时候会出错。。。
参考连接:https://langchain-ai.github.io/langgraph/tutorials/rewoo/rewoo/
如果有任何问题,欢迎在评论区提问。