File size: 13,244 Bytes
1e05108
1669f2b
 
 
fc5e0c3
 
30b4543
1669f2b
 
 
0a05d57
 
 
 
ce842f8
 
 
 
e1d5fc7
1669f2b
 
 
 
042d1d5
a93904c
d37c499
a8f7fb2
1669f2b
 
 
 
 
 
8ca5d55
f55b551
042d1d5
0a05d57
aaf4112
30b4543
1669f2b
 
374dd02
85ecabb
5da0168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152aaf7
 
5da0168
152aaf7
 
 
 
 
 
 
94602b0
9a75fd8
94602b0
e1d5fc7
 
 
94602b0
0ef7839
 
 
 
 
 
 
152aaf7
5da0168
152aaf7
5da0168
9a75fd8
5da0168
 
e1d5fc7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0ef7839
e1d5fc7
 
 
 
 
 
 
 
 
0ef7839
9a75fd8
e1d5fc7
 
 
 
 
5da0168
94602b0
 
e1d5fc7
 
 
9a75fd8
0ef7839
9a75fd8
152aaf7
5da0168
 
 
 
 
 
 
 
 
204c7d9
5da0168
 
 
 
204c7d9
8896d1f
5da0168
 
152aaf7
 
94602b0
 
 
 
 
5da0168
 
 
e1d5fc7
0ef7839
e1d5fc7
 
5da0168
e1d5fc7
94602b0
e1d5fc7
 
5da0168
 
 
85ecabb
 
f00550f
 
 
64434a5
1669f2b
64434a5
1669f2b
 
e1d5fc7
ba0e6f8
d49a17e
e1d5fc7
61cae63
5da0168
d49a17e
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
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,
                   arxiv_search, audio_transcription, compound_interest,
                   convert_temperature, divide, download_file, exponential,
                   extract_text, 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, wikipedia_search)

# Load Constants
load_dotenv()
HUGGINGFACEHUB_API_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN")
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# os.environ["OPENAI_API_KEY"] = OPENAI_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,
    wikipedia_search, analyze_excel_file, arxiv_search,
    audio_transcription, python_code_parser, analyze_csv_file,
    extract_text,
    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 from the complete toolkit
   - **Plan multi-tool sequences** - many questions require 2-5 tools in various combinations
   - **Consider tool order flexibility** - tools can be used in any sequence that makes logical sense
   - **Validate tool choice** - ensure the selected tool is the optimal match for your needs
   - Examples of multi-tool workflows:
     - reserve_sentence -> read the reversed question and answer it.
     - download_file -> analyze_csv_file -> add -> percentage_calculator
     - reverse_sentence -> python_code_parser -> web_search -> extract_text_from_image
     - arvix_search -> web_content_extract -> factorial -> roman_calculator_converter
     - audio_transcription -> wikipedia_search -> compound_interest -> convert_temperature

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

## Available Tools and Their Uses

### Mathematical Operations
- **add**: Addition operations
- **subtract**: Subtraction operations
- **multiply**: Multiplication operations
- **divide**: Division operations
- **floor_divide**: Floor division operations
- **modulus**: Modulo operations
- **power**: Exponentiation operations
- **square_root**: Square root calculations
- **exponential**: Exponential functions
- **logarithm**: Logarithmic calculations
- **absolute**: Absolute value calculations
- **factorial**: Factorial calculations
- **is_prime**: Check if a number is prime
- **greatest_common_divisor**: Find GCD of numbers
- **least_common_multiple**: Find LCM of numbers
- **percentage_calculator**: Calculate percentages
- **compound_interest**: Calculate compound interest
- **roman_calculator_converter**: Convert between Roman numerals and numbers

### File and Data Processing
- **download_file**: Download files from URLs or attachments
- **analyze_csv_file**: Analyze CSV file data
- **analyze_excel_file**: Analyze Excel file data
- **extract_text_from_image**: Extract text from image files
- **audio_transcription**: Transcribe audio files to text

### Text Processing
- **reverse_sentence**: Reverse text or sentences
- **python_code_parser**: Parse and analyze Python code

### Information Retrieval
- **web_search**: Search the web for information
- **web_content_extract**: Extract content from web pages
- **wikipedia_search**: Search Wikipedia for information
- **arvix_search**: Search academic papers on arXiv

### Utilities
- **convert_temperature**: Convert between temperature units
- **get_current_time_in_timezone**: Get current time in specific timezone

## 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
- **Multi-tool Operations**: Questions can require multiple tools in any sequence - plan your tool chain carefully
- **Sequential Processing**: Use outputs from one tool as inputs for another when necessary
- **File Processing Priority**: Always download and process files before attempting to answer questions about them
- **Mathematical Chains**: Combine mathematical operations as needed (e.g., add -> multiply -> percentage_calculator)
- **Information + Processing**: Combine search tools with processing tools (e.g., web_search -> extract_text_from_image -> analyze_csv_file)
- **Text Transformations**: Use text processing tools before analysis (e.g., reverse_sentence -> python_code_parser). In other words, first reverse the text when needed and then re-read the adjusted question.
- **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, keep it as short as possible and stick to the question.

## 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** (use reverse_sentence first)
- **Various tools are available** - evaluate ALL options to find the best match for each step
- **Multi-tool solutions are common** - expect to use 2-5 tools per complex question
- **Tool order is flexible** - arrange tools in the most logical sequence for your specific problem
- Always prioritize accuracy over speed
- If a question has multiple parts, ensure all parts are addressed with appropriate tools
- **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 with download_file first
- **Be prepared to perform complex multi-step operations** across all tool categories
- 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",
        # repo_id="HuggingFaceH4/mistral-7b-anthropic", # wrong id?
        # repo_id="Qwen/Qwen2.5-Coder-32B-Instruct", # this one is poor
        # repo_id="meta-llama/Llama-3.1-8B", # other credential
        huggingfacehub_api_token=HUGGINGFACEHUB_API_TOKEN,
        temperature=0.1,         # Maximum determinism
        max_new_tokens=512,      # Even more restrictive with 128
        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)