langgraph-agent-toolkit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langgraph_agent_toolkit/__init__.py +7 -0
- langgraph_agent_toolkit/agents/__init__.py +0 -0
- langgraph_agent_toolkit/agents/agent.py +14 -0
- langgraph_agent_toolkit/agents/agent_executor.py +415 -0
- langgraph_agent_toolkit/agents/blueprints/__init__.py +0 -0
- langgraph_agent_toolkit/agents/blueprints/bg_task_agent/__init__.py +0 -0
- langgraph_agent_toolkit/agents/blueprints/bg_task_agent/agent.py +69 -0
- langgraph_agent_toolkit/agents/blueprints/bg_task_agent/task.py +52 -0
- langgraph_agent_toolkit/agents/blueprints/bg_task_agent/utils.py +17 -0
- langgraph_agent_toolkit/agents/blueprints/chatbot/__init__.py +0 -0
- langgraph_agent_toolkit/agents/blueprints/chatbot/agent.py +34 -0
- langgraph_agent_toolkit/agents/blueprints/command_agent/__init__.py +0 -0
- langgraph_agent_toolkit/agents/blueprints/command_agent/agent.py +54 -0
- langgraph_agent_toolkit/agents/blueprints/interrupt_agent/__init__.py +0 -0
- langgraph_agent_toolkit/agents/blueprints/interrupt_agent/agent.py +140 -0
- langgraph_agent_toolkit/agents/blueprints/react/__init__.py +0 -0
- langgraph_agent_toolkit/agents/blueprints/react/agent.py +67 -0
- langgraph_agent_toolkit/agents/blueprints/react_so/__init__.py +0 -0
- langgraph_agent_toolkit/agents/blueprints/react_so/agent.py +39 -0
- langgraph_agent_toolkit/agents/blueprints/supervisor_agent/__init__.py +0 -0
- langgraph_agent_toolkit/agents/blueprints/supervisor_agent/agent.py +44 -0
- langgraph_agent_toolkit/agents/components/__init__.py +0 -0
- langgraph_agent_toolkit/agents/components/creators/__init__.py +4 -0
- langgraph_agent_toolkit/agents/components/creators/create_react_agent.py +459 -0
- langgraph_agent_toolkit/agents/components/tools.py +13 -0
- langgraph_agent_toolkit/agents/components/utils.py +42 -0
- langgraph_agent_toolkit/client/__init__.py +4 -0
- langgraph_agent_toolkit/client/client.py +344 -0
- langgraph_agent_toolkit/core/__init__.py +5 -0
- langgraph_agent_toolkit/core/memory/__init__.py +0 -0
- langgraph_agent_toolkit/core/memory/base.py +33 -0
- langgraph_agent_toolkit/core/memory/factory.py +30 -0
- langgraph_agent_toolkit/core/memory/postgres.py +76 -0
- langgraph_agent_toolkit/core/memory/sqlite.py +21 -0
- langgraph_agent_toolkit/core/memory/types.py +6 -0
- langgraph_agent_toolkit/core/models/__init__.py +5 -0
- langgraph_agent_toolkit/core/models/chat_openai.py +21 -0
- langgraph_agent_toolkit/core/models/factory.py +118 -0
- langgraph_agent_toolkit/core/models/fake.py +25 -0
- langgraph_agent_toolkit/core/observability/__init__.py +10 -0
- langgraph_agent_toolkit/core/observability/base.py +331 -0
- langgraph_agent_toolkit/core/observability/empty.py +67 -0
- langgraph_agent_toolkit/core/observability/factory.py +43 -0
- langgraph_agent_toolkit/core/observability/langfuse.py +118 -0
- langgraph_agent_toolkit/core/observability/langsmith.py +131 -0
- langgraph_agent_toolkit/core/observability/types.py +34 -0
- langgraph_agent_toolkit/core/prompts/__init__.py +0 -0
- langgraph_agent_toolkit/core/prompts/chat_prompt_template.py +528 -0
- langgraph_agent_toolkit/core/settings.py +164 -0
- langgraph_agent_toolkit/helper/__init__.py +0 -0
- langgraph_agent_toolkit/helper/constants.py +10 -0
- langgraph_agent_toolkit/helper/logging.py +111 -0
- langgraph_agent_toolkit/helper/types.py +7 -0
- langgraph_agent_toolkit/helper/utils.py +80 -0
- langgraph_agent_toolkit/run_agent.py +68 -0
- langgraph_agent_toolkit/run_client.py +55 -0
- langgraph_agent_toolkit/run_service.py +19 -0
- langgraph_agent_toolkit/schema/__init__.py +28 -0
- langgraph_agent_toolkit/schema/models.py +25 -0
- langgraph_agent_toolkit/schema/schema.py +210 -0
- langgraph_agent_toolkit/schema/task_data.py +72 -0
- langgraph_agent_toolkit/service/__init__.py +0 -0
- langgraph_agent_toolkit/service/exception_handlers.py +46 -0
- langgraph_agent_toolkit/service/factory.py +213 -0
- langgraph_agent_toolkit/service/handler.py +122 -0
- langgraph_agent_toolkit/service/middleware.py +18 -0
- langgraph_agent_toolkit/service/routes.py +169 -0
- langgraph_agent_toolkit/service/types.py +8 -0
- langgraph_agent_toolkit/service/utils.py +136 -0
- langgraph_agent_toolkit/streamlit_app.py +368 -0
- langgraph_agent_toolkit-0.1.0.dist-info/METADATA +424 -0
- langgraph_agent_toolkit-0.1.0.dist-info/RECORD +74 -0
- langgraph_agent_toolkit-0.1.0.dist-info/WHEEL +4 -0
- langgraph_agent_toolkit-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Any, cast
|
|
3
|
+
|
|
4
|
+
from langchain.prompts import SystemMessagePromptTemplate
|
|
5
|
+
from langchain_core.language_models.chat_models import BaseChatModel
|
|
6
|
+
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
|
|
7
|
+
from langchain_core.runnables import RunnableConfig, RunnableLambda, RunnableSerializable
|
|
8
|
+
from langgraph.checkpoint.memory import MemorySaver
|
|
9
|
+
from langgraph.graph import END, MessagesState, StateGraph
|
|
10
|
+
from langgraph.types import interrupt
|
|
11
|
+
from pydantic import BaseModel, Field
|
|
12
|
+
|
|
13
|
+
from langgraph_agent_toolkit.agents.agent import Agent
|
|
14
|
+
from langgraph_agent_toolkit.core import settings
|
|
15
|
+
from langgraph_agent_toolkit.core.models.factory import ModelFactory
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AgentState(MessagesState, total=False):
|
|
19
|
+
"""`total=False` is PEP589 specs.
|
|
20
|
+
|
|
21
|
+
documentation: https://typing.readthedocs.io/en/latest/spec/typeddict.html#totality
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
birthdate: datetime | None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def wrap_model(model: BaseChatModel, system_prompt: BaseMessage) -> RunnableSerializable[Any, BaseMessage]:
|
|
28
|
+
preprocessor = RunnableLambda(
|
|
29
|
+
lambda state: [system_prompt] + state["messages"],
|
|
30
|
+
name="StateModifier",
|
|
31
|
+
)
|
|
32
|
+
return preprocessor | model
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
background_prompt = SystemMessagePromptTemplate.from_template("""
|
|
36
|
+
You are a helpful assistant that tells users there zodiac sign.
|
|
37
|
+
Provide a one paragraph summary of the origin of zodiac signs.
|
|
38
|
+
Don't tell the user what their sign is, you are just demonstrating your knowledge on the topic.
|
|
39
|
+
""")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
async def background(state: AgentState, config: RunnableConfig) -> AgentState:
|
|
43
|
+
"""Demonstrate doing work before the interrupt."""
|
|
44
|
+
m = ModelFactory.create(config["configurable"].get("model", settings.DEFAULT_MODEL))
|
|
45
|
+
model_runnable = wrap_model(m, background_prompt.format())
|
|
46
|
+
response = await model_runnable.ainvoke(state, config)
|
|
47
|
+
|
|
48
|
+
return {"messages": [AIMessage(content=response.content)]}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
birthdate_extraction_prompt = SystemMessagePromptTemplate.from_template("""
|
|
52
|
+
You are an expert at extracting birthdates from conversational text.
|
|
53
|
+
|
|
54
|
+
Rules for extraction:
|
|
55
|
+
- Look for user messages that mention birthdates
|
|
56
|
+
- Consider various date formats (MM/DD/YYYY, YYYY-MM-DD, Month Day, Year)
|
|
57
|
+
- Validate that the date is reasonable (not in the future)
|
|
58
|
+
- If no clear birthdate was provided by the user, return None
|
|
59
|
+
""")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class BirthdateExtraction(BaseModel):
|
|
63
|
+
birthdate: str | None = Field(
|
|
64
|
+
description="The extracted birthdate in YYYY-MM-DD format. If no birthdate is found, this should be None."
|
|
65
|
+
)
|
|
66
|
+
reasoning: str = Field(description="Explanation of how the birthdate was extracted or why no birthdate was found")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
async def determine_birthdate(state: AgentState, config: RunnableConfig) -> AgentState:
|
|
70
|
+
"""Examine the conversation history to determine user's birthdate.
|
|
71
|
+
|
|
72
|
+
If no birthdate is found, it will perform an interrupt before proceeding.
|
|
73
|
+
"""
|
|
74
|
+
m = ModelFactory.create(config["configurable"].get("model", settings.DEFAULT_MODEL))
|
|
75
|
+
model_runnable = wrap_model(
|
|
76
|
+
m.with_structured_output(BirthdateExtraction),
|
|
77
|
+
birthdate_extraction_prompt.format(),
|
|
78
|
+
).with_config(tags=["skip_stream"])
|
|
79
|
+
response = await model_runnable.ainvoke(state, config)
|
|
80
|
+
response = cast(BirthdateExtraction, response)
|
|
81
|
+
|
|
82
|
+
# If no birthdate found, interrupt
|
|
83
|
+
if response.birthdate is None:
|
|
84
|
+
birthdate_input = interrupt(f"{response.reasoning}\nPlease tell me your birthdate?")
|
|
85
|
+
# Re-run extraction with the new input
|
|
86
|
+
state["messages"].append(HumanMessage(birthdate_input))
|
|
87
|
+
return await determine_birthdate(state, config)
|
|
88
|
+
|
|
89
|
+
# Birthdate found - convert string to datetime
|
|
90
|
+
try:
|
|
91
|
+
birthdate = datetime.fromisoformat(response.birthdate)
|
|
92
|
+
except ValueError:
|
|
93
|
+
# If parsing fails, ask for clarification
|
|
94
|
+
birthdate_input = interrupt(
|
|
95
|
+
"I couldn't understand the date format. Please provide your birthdate in YYYY-MM-DD format."
|
|
96
|
+
)
|
|
97
|
+
state["messages"].append(HumanMessage(birthdate_input))
|
|
98
|
+
return await determine_birthdate(state, config)
|
|
99
|
+
|
|
100
|
+
# Birthdate found
|
|
101
|
+
return {
|
|
102
|
+
"birthdate": birthdate,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
sign_prompt = SystemMessagePromptTemplate.from_template("""
|
|
107
|
+
You are a helpful assistant that tells users there zodiac sign.
|
|
108
|
+
What is the sign of somebody born on {birthdate}?
|
|
109
|
+
""")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
async def determine_sign(state: AgentState, config: RunnableConfig) -> AgentState:
|
|
113
|
+
"""Determine the zodiac sign of the user based on their birthdate."""
|
|
114
|
+
if not state.get("birthdate"):
|
|
115
|
+
raise ValueError("No birthdate found in state")
|
|
116
|
+
|
|
117
|
+
m = ModelFactory.create(config["configurable"].get("model", settings.DEFAULT_MODEL))
|
|
118
|
+
model_runnable = wrap_model(m, sign_prompt.format(birthdate=state["birthdate"].strftime("%Y-%m-%d")))
|
|
119
|
+
response = await model_runnable.ainvoke(state, config)
|
|
120
|
+
|
|
121
|
+
return {"messages": [AIMessage(content=response.content)]}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# Define the graph
|
|
125
|
+
agent = StateGraph(AgentState)
|
|
126
|
+
agent.add_node("background", background)
|
|
127
|
+
agent.add_node("determine_birthdate", determine_birthdate)
|
|
128
|
+
agent.add_node("determine_sign", determine_sign)
|
|
129
|
+
|
|
130
|
+
agent.set_entry_point("background")
|
|
131
|
+
agent.add_edge("background", "determine_birthdate")
|
|
132
|
+
agent.add_edge("determine_birthdate", "determine_sign")
|
|
133
|
+
agent.add_edge("determine_sign", END)
|
|
134
|
+
|
|
135
|
+
interrupt_agent = Agent(
|
|
136
|
+
name="interrupt-agent",
|
|
137
|
+
description="An agent the uses interrupts.",
|
|
138
|
+
graph=agent.compile(checkpointer=MemorySaver()),
|
|
139
|
+
)
|
|
140
|
+
interrupt_agent.graph.name = "interrupt-agent"
|
|
File without changes
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from langchain_community.tools import DuckDuckGoSearchResults
|
|
2
|
+
from langgraph.checkpoint.memory import MemorySaver
|
|
3
|
+
|
|
4
|
+
from langgraph_agent_toolkit.agents.agent import Agent
|
|
5
|
+
from langgraph_agent_toolkit.agents.components.creators.create_react_agent import create_react_agent
|
|
6
|
+
from langgraph_agent_toolkit.agents.components.tools import add, multiply
|
|
7
|
+
from langgraph_agent_toolkit.agents.components.utils import AgentStateWithRemainingSteps, pre_model_hook_standard
|
|
8
|
+
from langgraph_agent_toolkit.core.models.factory import ModelFactory
|
|
9
|
+
from langgraph_agent_toolkit.core.observability.factory import ObservabilityFactory
|
|
10
|
+
from langgraph_agent_toolkit.core.observability.types import ChatMessageDict, MessageRole, ObservabilityBackend
|
|
11
|
+
from langgraph_agent_toolkit.core.prompts.chat_prompt_template import ObservabilityChatPromptTemplate
|
|
12
|
+
from langgraph_agent_toolkit.core.settings import settings
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
PROMPT_NAME = "react-assistant"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# observability = ObservabilityFactory.create(settings.OBSERVABILITY_BACKEND)
|
|
19
|
+
observability = ObservabilityFactory.create(ObservabilityBackend.LANGFUSE)
|
|
20
|
+
|
|
21
|
+
# Push the prompt template to the observability platform first
|
|
22
|
+
observability.push_prompt(
|
|
23
|
+
name=PROMPT_NAME,
|
|
24
|
+
prompt_template=[
|
|
25
|
+
ChatMessageDict(
|
|
26
|
+
role=MessageRole.SYSTEM,
|
|
27
|
+
content=(
|
|
28
|
+
"You are a team support agent that can perform calculations and search the web. "
|
|
29
|
+
"You can use the tools provided to help you with your tasks. "
|
|
30
|
+
"You can also ask clarifying questions to the user. "
|
|
31
|
+
),
|
|
32
|
+
),
|
|
33
|
+
ChatMessageDict(
|
|
34
|
+
role=MessageRole.PLACEHOLDER,
|
|
35
|
+
content="messages",
|
|
36
|
+
),
|
|
37
|
+
],
|
|
38
|
+
create_new_version=True,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
print(observability.pull_prompt(name=PROMPT_NAME))
|
|
42
|
+
|
|
43
|
+
# Create ObservabilityChatPromptTemplate that will load from observability platform at runtime
|
|
44
|
+
prompt = ObservabilityChatPromptTemplate.from_observability_platform(
|
|
45
|
+
prompt_name=PROMPT_NAME,
|
|
46
|
+
observability_platform=observability,
|
|
47
|
+
load_at_runtime=True,
|
|
48
|
+
template_format="jinja2",
|
|
49
|
+
input_variables=["messages"],
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
react_agent = Agent(
|
|
53
|
+
name="react-agent",
|
|
54
|
+
description="A react agent.",
|
|
55
|
+
graph=create_react_agent(
|
|
56
|
+
model=ModelFactory.create(settings.DEFAULT_MODEL),
|
|
57
|
+
tools=[add, multiply, DuckDuckGoSearchResults()],
|
|
58
|
+
prompt=prompt,
|
|
59
|
+
pre_model_hook=pre_model_hook_standard,
|
|
60
|
+
state_schema=AgentStateWithRemainingSteps,
|
|
61
|
+
checkpointer=MemorySaver(),
|
|
62
|
+
immediate_step_threshold=5,
|
|
63
|
+
),
|
|
64
|
+
observability=observability,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
__all__ = ["react_agent"]
|
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from langchain_community.tools import DuckDuckGoSearchResults
|
|
2
|
+
from langgraph.checkpoint.memory import MemorySaver
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
from langgraph_agent_toolkit.agents.agent import Agent
|
|
6
|
+
from langgraph_agent_toolkit.agents.components.creators.create_react_agent import create_react_agent
|
|
7
|
+
from langgraph_agent_toolkit.agents.components.tools import add, multiply
|
|
8
|
+
from langgraph_agent_toolkit.agents.components.utils import AgentStateWithRemainingSteps, pre_model_hook_standard
|
|
9
|
+
from langgraph_agent_toolkit.core import settings
|
|
10
|
+
from langgraph_agent_toolkit.core.models.factory import ModelFactory
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ResponseSchema(BaseModel):
|
|
14
|
+
response: list[str] = Field(
|
|
15
|
+
description="The response on user query.",
|
|
16
|
+
)
|
|
17
|
+
alternative_response: str = Field(
|
|
18
|
+
description="The alternative response on user query.",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
react_agent_so = Agent(
|
|
23
|
+
name="react-agent-so",
|
|
24
|
+
description="A react agent with structured output.",
|
|
25
|
+
graph=create_react_agent(
|
|
26
|
+
model=ModelFactory.create(settings.DEFAULT_MODEL),
|
|
27
|
+
tools=[add, multiply, DuckDuckGoSearchResults()],
|
|
28
|
+
prompt=(
|
|
29
|
+
"You are a team support agent that can perform calculations and search the web. "
|
|
30
|
+
"You can use the tools provided to help you with your tasks. "
|
|
31
|
+
"You can also ask clarifying questions to the user. "
|
|
32
|
+
),
|
|
33
|
+
pre_model_hook=pre_model_hook_standard,
|
|
34
|
+
response_format=ResponseSchema,
|
|
35
|
+
state_schema=AgentStateWithRemainingSteps,
|
|
36
|
+
checkpointer=MemorySaver(),
|
|
37
|
+
immediate_step_threshold=5,
|
|
38
|
+
),
|
|
39
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from langchain_community.tools import DuckDuckGoSearchResults
|
|
2
|
+
from langgraph.checkpoint.memory import MemorySaver
|
|
3
|
+
from langgraph.prebuilt import create_react_agent
|
|
4
|
+
from langgraph_supervisor import create_supervisor
|
|
5
|
+
|
|
6
|
+
from langgraph_agent_toolkit.agents.agent import Agent
|
|
7
|
+
from langgraph_agent_toolkit.agents.components.tools import add, multiply
|
|
8
|
+
from langgraph_agent_toolkit.core import settings
|
|
9
|
+
from langgraph_agent_toolkit.core.models.factory import ModelFactory
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
model = ModelFactory.create(settings.DEFAULT_MODEL)
|
|
13
|
+
|
|
14
|
+
math_agent = create_react_agent(
|
|
15
|
+
model=model,
|
|
16
|
+
tools=[add, multiply],
|
|
17
|
+
name="math_expert",
|
|
18
|
+
prompt="You are a math expert. Always use one tool at a time.",
|
|
19
|
+
).with_config(tags=["skip_stream"])
|
|
20
|
+
|
|
21
|
+
research_agent = create_react_agent(
|
|
22
|
+
model=model,
|
|
23
|
+
tools=[DuckDuckGoSearchResults()],
|
|
24
|
+
name="research_expert",
|
|
25
|
+
prompt="You are a world class researcher with access to web search. Do not do any math.",
|
|
26
|
+
).with_config(tags=["skip_stream"])
|
|
27
|
+
|
|
28
|
+
# Create supervisor workflow
|
|
29
|
+
workflow = create_supervisor(
|
|
30
|
+
[research_agent, math_agent],
|
|
31
|
+
model=model,
|
|
32
|
+
prompt=(
|
|
33
|
+
"You are a team supervisor managing a research expert and a math expert. "
|
|
34
|
+
"For current events, use research_agent. "
|
|
35
|
+
"For math problems, use math_agent."
|
|
36
|
+
),
|
|
37
|
+
add_handoff_back_messages=False,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
supervisor_agent = Agent(
|
|
41
|
+
name="supervisor-agent",
|
|
42
|
+
description="A langgraph supervisor agent",
|
|
43
|
+
graph=workflow.compile(checkpointer=MemorySaver()),
|
|
44
|
+
)
|
|
File without changes
|