Skip to content

Commit c78e28c

Browse files
committed
Update lintin
1 parent 5169066 commit c78e28c

File tree

6 files changed

+90
-29
lines changed

6 files changed

+90
-29
lines changed

README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,55 @@
1+
<!--
2+
Configuration auto-generated by `langgraph template lock`. DO NOT EDIT MANUALLY.
3+
{
4+
"config_schemas": {
5+
"agent": {
6+
"type": "object",
7+
"properties": {
8+
"system_prompt": {
9+
"type": "string",
10+
"default": "You are a helpful AI assistant.\nSystem time: {system_time}"
11+
},
12+
"model_name": {
13+
"type": "string",
14+
"default": "claude-3-5-sonnet-20240620",
15+
"environment": [
16+
{
17+
"value": "anthropic",
18+
"variables": "ANTHROPIC_API_KEY"
19+
},
20+
{
21+
"value": "fireworks",
22+
"variables": "FIREWORKS_API_KEY"
23+
},
24+
{
25+
"value": "openai",
26+
"variables": "OPENAI_API_KEY"
27+
}
28+
]
29+
},
30+
"scraper_tool_model_name": {
31+
"type": "string",
32+
"default": "accounts/fireworks/models/firefunction-v2",
33+
"environment": [
34+
{
35+
"value": "anthropic",
36+
"variables": "ANTHROPIC_API_KEY"
37+
},
38+
{
39+
"value": "fireworks",
40+
"variables": "FIREWORKS_API_KEY"
41+
},
42+
{
43+
"value": "openai",
44+
"variables": "OPENAI_API_KEY"
45+
}
46+
]
47+
}
48+
}
49+
}
50+
}
51+
}
52+
-->
153
# LangGraph ReAct Agent Template
254

355
This LangGraph template implements a simple, extensible ReAct agent.

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ requires = ["setuptools>=73.0.0", "wheel"]
2626
build-backend = "setuptools.build_meta"
2727

2828
[tool.setuptools]
29-
packages = ["langgraph.templates.retrieval_graph", "retrieval_graph"]
29+
packages = ["langgraph.templates.react_agent", "react_agent"]
3030
[tool.setuptools.package-dir]
31-
"langgraph.templates.retrieval_graph" = "src/retrieval_graph"
32-
"retrieval_graph" = "src/retrieval_graph"
31+
"langgraph.templates.react_agent" = "src/react_agent"
32+
"react_agent" = "src/react_agent"
3333

3434

3535
[tool.setuptools.package-data]

src/react_agent/configuration.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ class Configuration:
1313
"""The configuration for the agent."""
1414

1515
system_prompt: str = "You are a helpful AI assistant.\nSystem time: {system_time}"
16-
model_name: Annotated[
17-
str, {"__template_metadata__": {"kind": "llm"}}
18-
] = "claude-3-5-sonnet-20240620"
16+
model_name: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = (
17+
"claude-3-5-sonnet-20240620"
18+
)
1919
scraper_tool_model_name: Annotated[
2020
str, {"__template_metadata__": {"kind": "llm"}}
2121
] = "accounts/fireworks/models/firefunction-v2"

src/react_agent/graph.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55

66
from datetime import datetime, timezone
7-
from typing import Literal
7+
from typing import Dict, List, Literal, cast
88

99
from langchain.chat_models import init_chat_model
1010
from langchain_core.messages import AIMessage
@@ -20,7 +20,9 @@
2020
# Define the function that calls the model
2121

2222

23-
async def call_model(state: State, config: RunnableConfig):
23+
async def call_model(
24+
state: State, config: RunnableConfig
25+
) -> Dict[str, List[AIMessage]]:
2426
"""Call the LLM powering our "agent".
2527
2628
This function prepares the prompt, initializes the model, and processes the response.
@@ -36,22 +38,26 @@ async def call_model(state: State, config: RunnableConfig):
3638

3739
# Create a prompt template. Customize this to change the agent's behavior.
3840
prompt = ChatPromptTemplate.from_messages(
39-
[("system", configuration["system_prompt"]), ("placeholder", "{messages}")]
41+
[("system", configuration.system_prompt), ("placeholder", "{messages}")]
4042
)
4143

4244
# Initialize the model with tool binding. Change the model or add more tools here.
43-
model = init_chat_model(configuration["model_name"]).bind_tools(TOOLS)
45+
model = init_chat_model(configuration.model_name).bind_tools(TOOLS)
4446

4547
# Prepare the input for the model, including the current system time
4648
message_value = await prompt.ainvoke(
47-
{**state, "system_time": datetime.now(tz=timezone.utc).isoformat()}, config
49+
{
50+
"messages": state.messages,
51+
"system_time": datetime.now(tz=timezone.utc).isoformat(),
52+
},
53+
config,
4854
)
4955

5056
# Get the model's response
51-
response: AIMessage = await model.ainvoke(message_value, config)
57+
response = cast(AIMessage, await model.ainvoke(message_value, config))
5258

5359
# Handle the case when it's the last step and the model still wants to use a tool
54-
if state["is_last_step"] and response.tool_calls:
60+
if state.is_last_step and response.tool_calls:
5561
return {
5662
"messages": [
5763
AIMessage(
@@ -89,14 +95,16 @@ def route_model_output(state: State) -> Literal["__end__", "tools"]:
8995
Returns:
9096
str: The name of the next node to call ("__end__" or "tools").
9197
"""
92-
messages = state["messages"]
93-
last_message = messages[-1]
94-
# If there is no function call, then we finish
98+
last_message = state.messages[-1]
99+
if not isinstance(last_message, AIMessage):
100+
raise ValueError(
101+
f"Expected AIMessage in output edges, but got {type(last_message).__name__}"
102+
)
103+
# If there is no tool call, then we finish
95104
if not last_message.tool_calls:
96105
return "__end__"
97-
# Otherwise if there are tools called, we continue
98-
else:
99-
return "tools"
106+
# Otherwise we execute the requested actions
107+
return "tools"
100108

101109

102110
# Add a conditional edge to determine the next step after `call_model`

src/react_agent/tools.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
"""
1010

1111
from datetime import datetime, timezone
12+
from typing import Any, Callable, Dict, List, cast
1213

1314
import httpx
1415
from langchain.chat_models import init_chat_model
1516
from langchain_core.runnables import RunnableConfig
1617

17-
from react_agent.configuration import ensure_configurable
18+
from react_agent.configuration import Configuration
1819
from react_agent.utils import get_message_text
1920

2021

@@ -33,8 +34,8 @@ async def scrape_webpage(url: str, instructions: str, *, config: RunnableConfig)
3334
response = await client.get(url)
3435
web_text = response.text
3536

36-
configuration = ensure_configurable(config)
37-
model = init_chat_model(configuration["model_name"])
37+
configuration = Configuration.from_runnable_config(config)
38+
model = init_chat_model(configuration.model_name)
3839
response_msg = await model.ainvoke(
3940
[
4041
(
@@ -53,7 +54,7 @@ async def scrape_webpage(url: str, instructions: str, *, config: RunnableConfig)
5354

5455

5556
# Note, in a real use case, you'd want to use a more robust search API.
56-
async def search_duckduckgo(query: str) -> dict:
57+
async def search_duckduckgo(query: str) -> Dict[str, Any]:
5758
"""Search DuckDuckGo for the given query and return the JSON response.
5859
5960
Results are limited, as this is the free public API.
@@ -62,13 +63,13 @@ async def search_duckduckgo(query: str) -> dict:
6263
response = await client.get(
6364
"https://api.duckduckgo.com/", params={"q": query, "format": "json"}
6465
)
65-
result = response.json()
66+
result = cast(Dict[str, Any], response.json())
6667

6768
result.pop("meta", None)
6869
return result
6970

7071

71-
async def search_wikipedia(query: str) -> dict:
72+
async def search_wikipedia(query: str) -> Dict[str, Any]:
7273
"""Search Wikipedia for the given query and return the JSON response."""
7374
url = "https://en.wikipedia.org/w/api.php"
7475
async with httpx.AsyncClient() as client:
@@ -81,10 +82,10 @@ async def search_wikipedia(query: str) -> dict:
8182
"format": "json",
8283
},
8384
)
84-
return response.json()
85+
return cast(Dict[str, Any], response.json())
8586

8687

87-
TOOLS = [
88+
TOOLS: List[Callable[..., Any]] = [
8889
scrape_webpage,
8990
search_duckduckgo,
9091
search_wikipedia,

src/react_agent/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""Utility & helper functions."""
22

3-
from langchain_core.messages import AnyMessage
3+
from langchain_core.messages import BaseMessage
44

55

6-
def get_message_text(msg: AnyMessage) -> str:
6+
def get_message_text(msg: BaseMessage) -> str:
77
"""Get the text content of a message."""
88
content = msg.content
99
if isinstance(content, str):

0 commit comments

Comments
 (0)