File size: 2,951 Bytes
758f7c7
01ba5f6
758f7c7
 
 
 
 
dcc7bc7
758f7c7
e06c61c
758f7c7
 
bfea96a
1394900
758f7c7
654f1b2
7056471
cdcbc72
654f1b2
cdcbc72
 
654f1b2
e64540d
615bf60
 
bfea96a
a372fc9
615bf60
d716044
615bf60
 
 
 
 
d716044
 
e64540d
 
 
9402140
84e331b
4ddfcdd
9a4d131
758f7c7
654f1b2
758f7c7
 
9a4d131
758f7c7
 
 
 
9a4d131
 
758f7c7
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import os
from langchain_groq import ChatGroq
from langgraph.graph import START, StateGraph, MessagesState
from langgraph.prebuilt import tools_condition
from langgraph.prebuilt import ToolNode
from langchain_core.messages import SystemMessage, HumanMessage
from tools import *
from typing import TypedDict, Optional

tools = [add, multiply, divide, subtract, search_wikipedia, duckduckgo_search, search_papers]

def build_agent():
    llm = ChatGroq(model="llama3-70b-8192", temperature=0) # deepseek-r1-distill-llama-70b
    chat_with_tools = llm.bind_tools(tools)

    def assistant(state: MessagesState):
        response = chat_with_tools.invoke(state["messages"])
        return {
            "messages": [response]
        }

    def enhancer(state: MessagesState):
        system_prompt = """You are a reasoning assistant that can answer complex questions using external tools. You must follow a structured reasoning format and always output a final answer.
                            Always follow this step-by-step structure:
                            - Thought: Describe your reasoning.
                            - Action:  Whenever necessary or recommended, call a tool, using this format → Action: tool_name(input).
                                       If not, use your reasoning for answering the question, using this format → Action: reasoning.
                            - Observation: Describe what the tool returned.
                            - Repeat Thought → Action → Observation as needed until you are SURE you can answer.
                            When you are ready to answer, say:
                            FINAL ANSWER: [your final answer here]
                            Formatting rules for FINAL ANSWER:
                            - If a number: no commas, no units unless explicitly asked.
                            - If a string: no articles, no abbreviations, digits in plain text.
                            - If a comma-separated list: apply the above rules to each element.
                            - Only include the final answer, do not include any reasoning steps."""

        sys_msg = SystemMessage(content=system_prompt)
        
        return {
                "messages": [sys_msg] + state["messages"]
            }

    ## The graph
    builder = StateGraph(MessagesState)
    
    # Define nodes: these do the work
    builder.add_node("enhancer", enhancer)
    builder.add_node("assistant", assistant)
    builder.add_node("tools", ToolNode(tools))
    
    # Define edges: these determine how the control flow moves
    builder.add_edge(START, "enhancer")
    builder.add_edge("enhancer", "assistant")
    builder.add_conditional_edges(
        "assistant",
        # If the latest message requires a tool, route to tools
        # Otherwise, provide a direct response
        tools_condition,
    )
    builder.add_edge("tools", "assistant")

    return builder.compile()