Shago commited on
Commit
84c0505
·
verified ·
1 Parent(s): dcaf29f

Upload 2 files

Browse files
Files changed (2) hide show
  1. agents/__init__.py +4 -0
  2. agents/agents_nodes.py +69 -0
agents/__init__.py CHANGED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # agents/__init__.py
2
+ from .agent_graph import build_graph
3
+
4
+ __all__ = ["build_graph"]
agents/agents_nodes.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from langchain_core.messages import AIMessage, ToolMessage
3
+ from langgraph.prebuilt import ToolNode
4
+ from utils.state_utils import AgentState
5
+ from tools.financial_tools import time_value_tool
6
+ from langchain_ollama import ChatOllama
7
+
8
+
9
+ # LLL instantation
10
+
11
+ llm = ChatOllama(model="qwen3:4b", temperature=0)
12
+ llm_instantiated = llm.bind_tools(
13
+ [time_value_tool],
14
+ tool_choice={"type": "function", "function": {"name": "time_value_tool"}}
15
+ )
16
+
17
+ def agent_node(state: AgentState):
18
+ response = llm_instantiated.invoke(state["messages"])
19
+ if not (hasattr(response, 'tool_calls') and response.tool_calls):
20
+ error_message = AIMessage(content="Error: Model failed to generate tool call.")
21
+ return {"messages": [error_message]}
22
+ return {"messages": [response]}
23
+
24
+ # Tool node executes the tool
25
+ tool_node = ToolNode([time_value_tool])
26
+
27
+ # Factor to output mapping
28
+ F_MAPPING = {
29
+ "P/F": "PV", "P/A": "PV", "P/G": "PV",
30
+ "F/P": "FV", "F/A": "FV", "F/G": "FV",
31
+ "A/P": "Annual", "A/F": "Annual", "A/G": "Annual"
32
+ }
33
+
34
+ def format_output(state: AgentState):
35
+ try:
36
+ # The last message should be the ToolMessage (from the tool node)
37
+ if not state["messages"] or not isinstance(state["messages"][-1], ToolMessage):
38
+ return {"output": {"error": "No tool result found in the last message"}}
39
+
40
+ tool_message = state["messages"][-1]
41
+ # Parse the content of the tool message as JSON
42
+ tool_result = json.loads(tool_message.content)
43
+
44
+ # The second last message should be the AIMessage with the tool call
45
+ if len(state["messages"]) < 2 or not isinstance(state["messages"][-2], AIMessage):
46
+ return {"output": {"error": "No AI message (with tool call) found before the tool message"}}
47
+
48
+ ai_message = state["messages"][-2]
49
+ if not ai_message.tool_calls:
50
+ return {"output": {"error": "The AI message does not contain tool calls"}}
51
+
52
+ # We take the first tool call (since we forced one tool)
53
+ tool_call = ai_message.tool_calls
54
+ args = tool_call["args"]
55
+
56
+ # Get the factor type from the args
57
+ factor_type = args["F"]
58
+ if factor_type not in F_MAPPING:
59
+ return {"output": {"error": f"Unrecognized factor type: {factor_type}"}}
60
+
61
+ result_key = F_MAPPING[factor_type]
62
+ if result_key not in tool_result:
63
+ return {"output": {"error": f"Expected key {result_key} not found in tool result"}}
64
+
65
+ value = tool_result[result_key]
66
+ return {"output": {result_key: round(float(value), 2)}}
67
+
68
+ except (KeyError, TypeError, json.JSONDecodeError, IndexError) as e:
69
+ return {"output": {"error": f"Result formatting failed: {str(e)}"}}