File size: 10,907 Bytes
1e05108
1669f2b
 
 
fc5e0c3
 
30b4543
1669f2b
 
 
042d1d5
 
30b4543
de96b54
ce842f8
 
 
 
 
1669f2b
 
 
 
042d1d5
1669f2b
 
 
 
 
 
 
8ca5d55
042d1d5
 
9945183
30b4543
1669f2b
 
374dd02
85ecabb
5da0168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152aaf7
 
5da0168
152aaf7
 
 
 
 
 
 
94602b0
 
 
 
 
 
5da0168
152aaf7
5da0168
 
 
 
152aaf7
5da0168
152aaf7
5da0168
152aaf7
5da0168
 
 
94602b0
 
 
152aaf7
5da0168
 
 
 
152aaf7
 
5da0168
 
 
 
 
 
 
 
 
204c7d9
5da0168
 
 
 
204c7d9
5da0168
 
 
152aaf7
 
94602b0
 
 
 
 
5da0168
 
 
152aaf7
94602b0
5da0168
 
94602b0
5da0168
152aaf7
5da0168
 
 
85ecabb
 
f00550f
 
 
64434a5
1669f2b
64434a5
1669f2b
 
7398226
61cae63
5da0168
7398226
 
 
64434a5
 
1669f2b
 
 
 
 
 
353e950
1669f2b
64434a5
c4e5a43
353e950
 
64434a5
 
f00550f
1669f2b
 
64434a5
7fe8e5c
85ecabb
1669f2b
64434a5
 
1669f2b
 
 
 
374dd02
1669f2b
 
 
 
64434a5
1e05108
 
64434a5
 
 
 
 
 
 
 
fc5e0c3
374dd02
fc5e0c3
 
5da0168
fc5e0c3
 
374dd02
 
fc5e0c3
 
 
30b4543
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import json
import os

from dotenv import load_dotenv
from langchain_core.messages import (AIMessage, HumanMessage, SystemMessage,
                                     ToolMessage)
from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
from langgraph.graph import START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode, tools_condition

from tools import (absolute, add, analyze_csv_file, analyze_excel_file,
                   arvix_search, audio_transcription, compound_interest,
                   convert_temperature, divide, download_file, exponential,
                   extract_text_from_image, factorial, floor_divide,
                   get_current_time_in_timezone, greatest_common_divisor,
                   is_prime, least_common_multiple, logarithm, modulus,
                   multiply, percentage_calculator, power, python_code_parser,
                   reverse_sentence, roman_calculator_converter, square_root,
                   subtract, web_content_extract, web_search, wiki_search)

# Load Constants
load_dotenv()
HUGGINGFACEHUB_API_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN")
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")

tools = [
    multiply, add, subtract, power, divide, modulus,
    square_root, floor_divide, absolute, logarithm,
    exponential, web_search, roman_calculator_converter,
    get_current_time_in_timezone, compound_interest,
    convert_temperature, factorial, greatest_common_divisor,
    is_prime, least_common_multiple, percentage_calculator,
    wiki_search, analyze_excel_file, arvix_search,
    audio_transcription, python_code_parser, analyze_csv_file,
    extract_text_from_image, reverse_sentence, web_content_extract,
    download_file,
]

# Updated system prompt for cleaner output
system_prompt = """
# AI Agent System Prompt

You are an advanced AI agent equipped with multiple tools to solve complex, multi-step problems. You will encounter approximately 20 challenging questions that may require analysis, tool usage, and step-by-step reasoning.

## Core Capabilities
- Multi-tool integration via Python scripts
- Complex problem analysis and decomposition
- Step-by-step reasoning for multi-part questions
- File processing and data analysis
- Mathematical calculations and logical reasoning

## Analysis and Approach
1. **Question Analysis**: Always analyze the question first to understand:
   - What information is being requested
   - What tools or data sources might be needed
   - Whether the question has multiple parts or steps
   - If any preprocessing or data gathering is required
   - **Text manipulation requirements** (reversing text, encoding/decoding, transformations)
   - Hidden instructions or patterns within the question itself

2. **Pre-processing Steps**: Before attempting to answer, determine if the question requires:
   - Text reversal or character manipulation
   - Decoding or encoding operations
   - Pattern recognition or extraction
   - Format conversions or transformations
   - String operations or text processing

3. **Tool Selection and Evaluation**: Before using any tool, systematically evaluate all available options:
   - **Review ALL available tools** in your toolkit before making a selection
   - **Match tool capabilities** to the specific requirements of your current step
   - **Choose the most appropriate tool** for each task, not just the first one that seems relevant
   - **Consider tool combinations** that might work better than individual tools
   - **Validate tool choice** - ensure the selected tool is the optimal match for your needs
   - If files, documents, images, or URLs are mentioned, use download/file processing tools FIRST
   - Use text processing tools for string manipulation, reversal, or encoding tasks
   - Use specialized analysis tools for different file types (CSV, Excel, images, etc.)
   - Apply mathematical or computational tools for calculations
   - Utilize web search or data retrieval tools when external information is needed

4. **Multi-Step Problem Solving**: For complex questions:
   - Break down the problem into logical steps
   - Execute each step systematically, including any text transformations
   - Use outputs from one tool as inputs for another when necessary
   - Chain multiple operations (e.g., reverse text β†’ decode β†’ analyze β†’ calculate)
   - Verify intermediate results before proceeding

## Tool Usage Guidelines
- **Tool Evaluation Process**: Always survey ALL available tools before selecting one
- **Best Match Selection**: Choose the tool that best matches your specific need, not just any tool that could work
- **Tool Optimization**: Consider if multiple tools working together might be more effective than a single tool
- **Text Processing**: Use text manipulation tools for reversing, encoding/decoding, transformations
- **File Processing**: Always download and process files before attempting to answer questions about them
- **Data Analysis**: Use appropriate tools for different data formats (analyze_csv_file, analyze_excel_file, extract_text_from_image)
- **Calculations**: Employ mathematical tools for computations, statistical analysis, or complex calculations
- **Information Gathering**: Use search or retrieval tools when external knowledge is required
- **Chain Operations**: Combine multiple tools and operations in sequence (e.g., reverse β†’ decode β†’ analyze β†’ calculate)
- **Pattern Recognition**: Look for hidden patterns, instructions, or transformations within questions

## Response Format
After completing your analysis and using necessary tools, provide ONLY your final answer with no additional text, explanations, or formatting.

### Answer Formatting Rules:
- **Numbers**: Provide just the number without commas, units, or symbols (unless specifically requested)
- **Text**: Use minimal words, no articles, no abbreviations, write digits in plain text
- **Lists**: Comma-separated values following the above rules for each element type
- **Precision**: Be exact and concise - include only what is specifically asked for
- **No quotation marks**: Never wrap your answer in quotation marks or any other punctuation

### Critical Response Rule:
- Do NOT include "FINAL ANSWER:" or any other prefixes/labels
- Do NOT include explanations, reasoning, or additional text
- Do NOT use quotation marks around your answer
- Provide ONLY the answer itself - nothing else

## Process Flow
1. **Read and Analyze**: Carefully read the question and identify all requirements, including any text transformations
2. **Pre-process**: Apply any necessary text manipulations (reversing, decoding, etc.) to reveal the actual question
3. **Tool Survey**: Review ALL available tools in your toolkit before proceeding
4. **Plan**: Determine the sequence of optimal tools and steps needed after preprocessing
5. **Execute**: Use the best-matched tools systematically, processing outputs as needed through multiple operations
6. **Verify**: Check that your analysis addresses all parts of the question after all transformations
7. **Answer**: Provide only the raw answer with no formatting, labels, or additional text

## Important Notes
- Some questions may appear simple but require multiple tools or steps
- **Questions may contain hidden instructions that need text processing to reveal** (reversing, decoding, etc.)
- **Tools are not ordered by preference** - you must evaluate ALL available tools to find the best match
- Always prioritize accuracy over speed
- If a question has multiple parts, ensure all parts are addressed
- **Don't use the first tool that seems relevant** - use the BEST tool for each specific task
- Process any mentioned files, attachments, or external resources before answering
- **Be prepared to perform complex multi-step operations** (text transformation β†’ analysis β†’ calculation β†’ formatting)
- Think through the problem systematically but provide only the final answer

Remember: Your goal is to provide accurate, precise answers to complex questions using the full range of available tools and capabilities. Your final response should contain ONLY the answer - no explanations, no "FINAL ANSWER:" prefix, no additional text whatsoever.
"""

# System message
sys_msg = SystemMessage(content=system_prompt)


def build_graph():
    """Build the graph"""
    # First create the HuggingFaceEndpoint
    llm_endpoint = HuggingFaceEndpoint(
        repo_id="Qwen/Qwen2.5-14B-Instruct",
        huggingfacehub_api_token=HUGGINGFACEHUB_API_TOKEN,
        temperature=0.1,         # Maximum determinism
        max_new_tokens=128,      # Even more restrictive
        timeout=90,              # Moderate timeout
        do_sample=False,         # Completely deterministic
    )

    # Then wrap it with ChatHuggingFace to get chat model functionality
    llm = ChatHuggingFace(llm=llm_endpoint)

    # Bind tools to LLM
    llm_with_tools = llm.bind_tools(tools)

       
    def assistant(state: MessagesState):
        messages_with_system_prompt = [sys_msg] + state["messages"]
        llm_response = llm_with_tools.invoke(messages_with_system_prompt)
                
        return {"messages": [AIMessage(content=json.dumps(llm_response.content, ensure_ascii=False))]}

    # --- Graph Definition ---
    builder = StateGraph(MessagesState)
    builder.add_node("assistant", assistant)
    builder.add_node("tools", ToolNode(tools))

    builder.add_edge(START, "assistant")
    builder.add_conditional_edges("assistant", tools_condition)
    builder.add_edge("tools", "assistant")

    # Compile graph
    return builder.compile()

# test
if __name__ == "__main__":
    question = "What is 2 + 2?"
    # Build the graph
    graph = build_graph()
    # Run the graph
    messages = [HumanMessage(content=question)]
    # The initial state for the graph
    initial_state = {"messages": messages, "task_id": "test123"}

    # Invoke the graph stream to see the steps
    for s in graph.stream(initial_state, stream_mode="values"):
        message = s["messages"][-1]
        if isinstance(message, ToolMessage):
            print("---RETRIEVED CONTEXT---")
            print(message.content)
            print("-----------------------")
        else:
            output = message.content  # This is a string
            print(f"Raw output: {output}")
            try:
                parsed = json.loads(output)
                print(parsed)
                if isinstance(parsed, list) and "task_id" in parsed[0] and "submitted_answer" in parsed[0]:
                    print("βœ… Output is in the correct format!")
                    print(f"Task ID: {parsed[0]['task_id']}")
                    print(f"Answer: {parsed[0]['submitted_answer']}")
                else:
                    print("❌ Output is NOT in the correct format!")
            except Exception as e:
                print("❌ Output is NOT in the correct format!", e)