11"""Test Q&A Agent"""
22
3+ import os
34from typing import Any , cast
45from langchain_openai import ChatOpenAI
6+ from langchain_anthropic import ChatAnthropic
57from langgraph .graph import StateGraph , END
68from langgraph .graph import MessagesState
79from langgraph .checkpoint .memory import MemorySaver
810from langchain_core .runnables import RunnableConfig
9- from langchain_core .messages import SystemMessage , ToolMessage
11+ from langchain_core .messages import HumanMessage , ToolMessage
1012from copilotkit .langchain import (
1113 copilotkit_customize_config , copilotkit_exit , copilotkit_emit_message
1214)
15+ from pydantic import BaseModel , Field
16+
17+
18+ def get_model ():
19+ """
20+ Get a model based on the environment variable.
21+ """
22+ model = os .getenv ("MODEL" , "openai" )
23+
24+ if model == "openai" :
25+ return ChatOpenAI (temperature = 0 , model = "gpt-4o" )
26+ if model == "anthropic" :
27+ return ChatAnthropic (
28+ temperature = 0 ,
29+ model_name = "claude-3-5-sonnet-20240620" ,
30+ timeout = None ,
31+ stop = None
32+ )
33+
34+ raise ValueError ("Invalid model specified" )
35+
1336
1437class EmailAgentState (MessagesState ):
1538 """Email Agent State"""
1639 email : str
1740
41+ class EmailTool (BaseModel ):
42+ """
43+ Write an email.
44+ """
45+ the_email : str = Field (description = "The email to be written." )
46+
47+
1848async def email_node (state : EmailAgentState , config : RunnableConfig ):
1949 """
2050 Write an email.
@@ -25,42 +55,24 @@ async def email_node(state: EmailAgentState, config: RunnableConfig):
2555 emit_tool_calls = True ,
2656 )
2757
28- system_message = "You write emails."
29-
30- email_tool = {
31- 'name' : 'write_email' ,
32- 'description' : """Write an email.""" ,
33- 'parameters' : {
34- 'type' : 'object' ,
35- 'properties' : {
36- 'the_email' : {
37- 'description' : """The email""" ,
38- 'type' : 'string' ,
39- }
40- },
41- 'required' : ['the_email' ]
42- }
43- }
58+ instructions = "You write emails."
4459
45- email_model = ChatOpenAI (model = "gpt-4o" ).bind_tools (
46- [email_tool ],
47- parallel_tool_calls = False ,
48- tool_choice = "write_email"
60+ email_model = get_model ().bind_tools (
61+ [EmailTool ],
62+ tool_choice = "EmailTool"
4963 )
5064
51- print ("GENERATING EMAIL" )
5265 response = await email_model .ainvoke ([
5366 * state ["messages" ],
54- SystemMessage (
55- content = system_message
67+ HumanMessage (
68+ content = instructions
5669 )
5770 ], config )
5871
5972 tool_calls = cast (Any , response ).tool_calls
6073
6174 email = tool_calls [0 ]["args" ]["the_email" ]
6275
63-
6476 return {
6577 "email" : email ,
6678 }
@@ -90,22 +102,11 @@ async def send_email_node(state: EmailAgentState, config: RunnableConfig):
90102 "messages" : state ["messages" ],
91103 }
92104
93- def route (state : EmailAgentState ):
94- """Route to the appropriate node."""
95-
96- print ("ROUTING" )
97- print (state .get ("email" , None ) is not None )
98- print ("---" )
99-
100- if state .get ("email" , None ) is not None :
101- return "send_email_node"
102- return "email_node"
103105
104106workflow = StateGraph (EmailAgentState )
105107workflow .add_node ("email_node" , email_node )
106108workflow .add_node ("send_email_node" , send_email_node )
107109workflow .set_entry_point ("email_node" )
108- workflow .set_conditional_entry_point (route )
109110
110111workflow .add_edge ("email_node" , "send_email_node" )
111112workflow .add_edge ("send_email_node" , END )
0 commit comments