Spaces:
Sleeping
Sleeping
Update agentic.py
Browse files- agentic.py +119 -31
agentic.py
CHANGED
|
@@ -11,6 +11,7 @@ from langchain_community.tools import WikipediaQueryRun
|
|
| 11 |
from langchain_community.utilities import WikipediaAPIWrapper
|
| 12 |
from langchain_aws import ChatBedrock
|
| 13 |
from langchain_google_genai import ChatGoogleGenerativeAI
|
|
|
|
| 14 |
# from langchain_google_vertexai import ChatVertexAI
|
| 15 |
|
| 16 |
# from langfuse.callback import CallbackHandler
|
|
@@ -51,25 +52,26 @@ class State(TypedDict):
|
|
| 51 |
video_node_result: AnyMessage
|
| 52 |
audio_node_result: AnyMessage
|
| 53 |
code_node_result: AnyMessage
|
|
|
|
| 54 |
next_node: str
|
| 55 |
|
| 56 |
########################
|
| 57 |
|
| 58 |
######## MODELS ########
|
| 59 |
-
def
|
| 60 |
|
| 61 |
llm_provider = os.getenv("LLM_PROVIDER", "mistral")
|
| 62 |
|
| 63 |
if llm_provider == "mistral":
|
| 64 |
-
|
| 65 |
-
model="mistral-
|
| 66 |
temperature=0,
|
| 67 |
max_retries=2,
|
| 68 |
api_key=os.getenv("MISTRAL_API_KEY")
|
| 69 |
)
|
| 70 |
|
| 71 |
if llm_provider == "aws":
|
| 72 |
-
|
| 73 |
model_id="arn:aws:bedrock:us-east-1:416545197702:inference-profile/us.amazon.nova-lite-v1:0",
|
| 74 |
# provider="amazon",
|
| 75 |
temperature=0,
|
|
@@ -78,7 +80,29 @@ def get_general_model():
|
|
| 78 |
aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY")
|
| 79 |
)
|
| 80 |
|
| 81 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
|
| 83 |
def get_vision_model():
|
| 84 |
|
|
@@ -87,7 +111,7 @@ def get_vision_model():
|
|
| 87 |
if vlm_provider == "openai":
|
| 88 |
print("Spawning Open AI VLM")
|
| 89 |
vision_model = ChatOpenAI(
|
| 90 |
-
model="gpt-4o",
|
| 91 |
temperature=0,
|
| 92 |
max_tokens=None,
|
| 93 |
timeout=None,
|
|
@@ -257,17 +281,19 @@ def download_input_file(task_id: str) -> str:
|
|
| 257 |
|
| 258 |
######## LLM associations ########
|
| 259 |
|
| 260 |
-
|
|
|
|
|
|
|
|
|
|
| 261 |
vision_model = get_vision_model()
|
| 262 |
video_handler_model = get_video_handler_model()
|
| 263 |
audio_handler_model = get_audio_handler_model()
|
| 264 |
|
|
|
|
| 265 |
########################
|
| 266 |
|
| 267 |
######## Nodes Definition ########
|
| 268 |
|
| 269 |
-
general_model = get_general_model()
|
| 270 |
-
|
| 271 |
search_tools = [
|
| 272 |
web_search,
|
| 273 |
wikipedia_search,
|
|
@@ -275,7 +301,7 @@ search_tools = [
|
|
| 275 |
|
| 276 |
download_file_tool = [ download_input_file ]
|
| 277 |
|
| 278 |
-
web_search_node_agent =
|
| 279 |
|
| 280 |
def thinking_node(state: State) -> dict:
|
| 281 |
"""
|
|
@@ -313,7 +339,7 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 313 |
|
| 314 |
sys_msg = SystemMessage(content=prompt)
|
| 315 |
|
| 316 |
-
thinking_node_response = [
|
| 317 |
|
| 318 |
thinking_node_response[-1].pretty_print()
|
| 319 |
|
|
@@ -357,7 +383,7 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 357 |
|
| 358 |
sys_msg = SystemMessage(content=prompt)
|
| 359 |
|
| 360 |
-
code_node_response = [
|
| 361 |
|
| 362 |
code_node_response[-1].pretty_print()
|
| 363 |
|
|
@@ -425,7 +451,6 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 425 |
"web_wiki_search_node_result": web_wiki_search_node_response,
|
| 426 |
}
|
| 427 |
|
| 428 |
-
|
| 429 |
def vision_node(state: State) -> dict:
|
| 430 |
"""
|
| 431 |
Vision model that can analyze images and pictures and answer questions about them.
|
|
@@ -446,9 +471,9 @@ You do not handle videos
|
|
| 446 |
You do not handle audio
|
| 447 |
You do not handle code
|
| 448 |
|
| 449 |
-
1. You need to fully understand the question
|
| 450 |
-
2. You must think hard about what is relevant in the image to make the best answer to the question
|
| 451 |
-
|
| 452 |
|
| 453 |
Here is the question {state['question']}
|
| 454 |
Now provide your response immediately without any preamble in text but not in markdown.
|
|
@@ -532,7 +557,7 @@ You do not handle images or pictures.
|
|
| 532 |
You do not handle audio.
|
| 533 |
You do not handle code.
|
| 534 |
|
| 535 |
-
1. You need to fully understand the question
|
| 536 |
2. Carefully observe the video, paying attention to relevant details, actions, and context.
|
| 537 |
3. Focus on the user's question.
|
| 538 |
4. If the question requires counting, identifying, or describing, be precise and clear in your response.
|
|
@@ -615,7 +640,7 @@ You do not handle images or pictures.
|
|
| 615 |
You do not handle video.
|
| 616 |
You do not handle code.
|
| 617 |
|
| 618 |
-
1. You need to fully understand the question
|
| 619 |
2. Carefully listen to the audio, paying attention to relevant details, actions, and context.
|
| 620 |
3. Focus on the user's question.
|
| 621 |
4. If the question requires counting, identifying, or describing, be precise and clear in your response.
|
|
@@ -669,7 +694,69 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 669 |
"audio_node_result": audio_node_response
|
| 670 |
}
|
| 671 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 672 |
def format_answer_node(state: State):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 673 |
|
| 674 |
prompt = """
|
| 675 |
You are the best assistant for final answer formating.
|
|
@@ -696,7 +783,6 @@ FINAL ANSWER: [YOUR FINAL ANSWER]
|
|
| 696 |
- If asked for a comma-separated list:
|
| 697 |
- Apply the above rules for numbers and strings to each element in the list.
|
| 698 |
- And take care of having a space after each comma.
|
| 699 |
-
- If there is a list with single letter for each item, write them with the same case as the question.
|
| 700 |
|
| 701 |
## Constraints
|
| 702 |
- You must not answer if the constraints above are not respected.
|
|
@@ -710,7 +796,7 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 710 |
|
| 711 |
question = [HumanMessage(content=state["question"])]
|
| 712 |
|
| 713 |
-
for node_result in ["web_wiki_search_node_result", "vision_node_result", "video_node_result", "audio_node_result", "thinking_node_result", "code_node_result"]:
|
| 714 |
result = state.get(node_result, "")
|
| 715 |
if result:
|
| 716 |
# Ensure result is a string. If it's a message object, extract its content.
|
|
@@ -722,7 +808,7 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 722 |
|
| 723 |
sys_msg = SystemMessage(content=prompt)
|
| 724 |
|
| 725 |
-
response = [
|
| 726 |
|
| 727 |
return {
|
| 728 |
"messages": response,
|
|
@@ -748,6 +834,7 @@ You do not handle code
|
|
| 748 |
- .wav or .mp3 is for audio
|
| 749 |
- a youtube url is for video
|
| 750 |
- a .jpg, .png, .jpeg is for image
|
|
|
|
| 751 |
3. You must think hard about what is relevant in the question to make the best choice for the next node
|
| 752 |
4. You must not answer the question by yourself
|
| 753 |
5. Report your thought process in detail, explaining your reasoning step-by-step.
|
|
@@ -759,6 +846,7 @@ Here are the nodes you can choose:
|
|
| 759 |
- video_node: {video_node.__doc__}
|
| 760 |
- audio_node: {audio_node.__doc__}
|
| 761 |
- code_node: {code_node.__doc__}
|
|
|
|
| 762 |
|
| 763 |
Here is the question : {state['question']}
|
| 764 |
Here is the file : {state.get("input_file", "no file to handle")}
|
|
@@ -773,11 +861,11 @@ Now provide your response immediately respecting this format in lower case: 'nex
|
|
| 773 |
|
| 774 |
sys_msg = SystemMessage(content=system_prompt)
|
| 775 |
|
| 776 |
-
entry_node_response = [
|
| 777 |
|
| 778 |
entry_node_response[-1].pretty_print()
|
| 779 |
|
| 780 |
-
regex_result = re.search(r'.*next\s*node
|
| 781 |
|
| 782 |
next_node = "END"
|
| 783 |
if regex_result:
|
|
@@ -805,6 +893,7 @@ def build_graph():
|
|
| 805 |
builder.add_node("audio_node", audio_node)
|
| 806 |
builder.add_node("code_node", code_node)
|
| 807 |
builder.add_node("thinking_node", thinking_node)
|
|
|
|
| 808 |
builder.add_node("format_answer_node", format_answer_node)
|
| 809 |
|
| 810 |
builder.add_edge(START, "entry_node")
|
|
@@ -819,6 +908,7 @@ def build_graph():
|
|
| 819 |
"video_node": "video_node",
|
| 820 |
"audio_node": "audio_node",
|
| 821 |
"code_node": "code_node",
|
|
|
|
| 822 |
"thinking_node": "thinking_node"
|
| 823 |
}
|
| 824 |
)
|
|
@@ -828,6 +918,7 @@ def build_graph():
|
|
| 828 |
builder.add_edge("video_node", "format_answer_node")
|
| 829 |
builder.add_edge("audio_node", "format_answer_node")
|
| 830 |
builder.add_edge("code_node", "format_answer_node")
|
|
|
|
| 831 |
builder.add_edge("thinking_node", "format_answer_node")
|
| 832 |
builder.add_edge("format_answer_node", END)
|
| 833 |
|
|
@@ -848,12 +939,11 @@ if __name__ == "__main__":
|
|
| 848 |
with open("./responses.json", "r") as responses:
|
| 849 |
json_responses = json.loads(responses.read())
|
| 850 |
|
| 851 |
-
#
|
| 852 |
-
# "
|
| 853 |
-
# "
|
| 854 |
-
# "
|
| 855 |
-
#
|
| 856 |
-
# }
|
| 857 |
|
| 858 |
with open("questions.json", "r") as questions:
|
| 859 |
json_questions = json.loads(questions.read())
|
|
@@ -897,5 +987,3 @@ if __name__ == "__main__":
|
|
| 897 |
print(f"Expected: {json_responses.get(task_id, '')}")
|
| 898 |
print(f"Got: {answer}")
|
| 899 |
|
| 900 |
-
time.sleep(10)
|
| 901 |
-
|
|
|
|
| 11 |
from langchain_community.utilities import WikipediaAPIWrapper
|
| 12 |
from langchain_aws import ChatBedrock
|
| 13 |
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 14 |
+
from langchain_community.document_loaders import UnstructuredExcelLoader
|
| 15 |
# from langchain_google_vertexai import ChatVertexAI
|
| 16 |
|
| 17 |
# from langfuse.callback import CallbackHandler
|
|
|
|
| 52 |
video_node_result: AnyMessage
|
| 53 |
audio_node_result: AnyMessage
|
| 54 |
code_node_result: AnyMessage
|
| 55 |
+
excel_node_result: AnyMessage
|
| 56 |
next_node: str
|
| 57 |
|
| 58 |
########################
|
| 59 |
|
| 60 |
######## MODELS ########
|
| 61 |
+
def get_light_model():
|
| 62 |
|
| 63 |
llm_provider = os.getenv("LLM_PROVIDER", "mistral")
|
| 64 |
|
| 65 |
if llm_provider == "mistral":
|
| 66 |
+
light_model = ChatMistralAI(
|
| 67 |
+
model="mistral-small-latest",
|
| 68 |
temperature=0,
|
| 69 |
max_retries=2,
|
| 70 |
api_key=os.getenv("MISTRAL_API_KEY")
|
| 71 |
)
|
| 72 |
|
| 73 |
if llm_provider == "aws":
|
| 74 |
+
light_model = ChatBedrock(
|
| 75 |
model_id="arn:aws:bedrock:us-east-1:416545197702:inference-profile/us.amazon.nova-lite-v1:0",
|
| 76 |
# provider="amazon",
|
| 77 |
temperature=0,
|
|
|
|
| 80 |
aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY")
|
| 81 |
)
|
| 82 |
|
| 83 |
+
return light_model
|
| 84 |
+
|
| 85 |
+
def get_medium_model():
|
| 86 |
+
|
| 87 |
+
medium_model = ChatMistralAI(
|
| 88 |
+
model="ministral-8b-latest",#"mistral-large-2411",
|
| 89 |
+
temperature=0,
|
| 90 |
+
max_retries=2,
|
| 91 |
+
api_key=os.getenv("MISTRAL_API_KEY")
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
return medium_model
|
| 95 |
+
|
| 96 |
+
def get_big_model():
|
| 97 |
+
|
| 98 |
+
big_model = ChatMistralAI(
|
| 99 |
+
model="mistral-medium-2505",#"mistral-large-2411"
|
| 100 |
+
temperature=0,
|
| 101 |
+
max_retries=2,
|
| 102 |
+
api_key=os.getenv("MISTRAL_API_KEY")
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
return big_model
|
| 106 |
|
| 107 |
def get_vision_model():
|
| 108 |
|
|
|
|
| 111 |
if vlm_provider == "openai":
|
| 112 |
print("Spawning Open AI VLM")
|
| 113 |
vision_model = ChatOpenAI(
|
| 114 |
+
model="gpt-4o",
|
| 115 |
temperature=0,
|
| 116 |
max_tokens=None,
|
| 117 |
timeout=None,
|
|
|
|
| 281 |
|
| 282 |
######## LLM associations ########
|
| 283 |
|
| 284 |
+
medium_model = get_medium_model()
|
| 285 |
+
light_model = get_light_model()
|
| 286 |
+
big_model = get_big_model()
|
| 287 |
+
|
| 288 |
vision_model = get_vision_model()
|
| 289 |
video_handler_model = get_video_handler_model()
|
| 290 |
audio_handler_model = get_audio_handler_model()
|
| 291 |
|
| 292 |
+
|
| 293 |
########################
|
| 294 |
|
| 295 |
######## Nodes Definition ########
|
| 296 |
|
|
|
|
|
|
|
| 297 |
search_tools = [
|
| 298 |
web_search,
|
| 299 |
wikipedia_search,
|
|
|
|
| 301 |
|
| 302 |
download_file_tool = [ download_input_file ]
|
| 303 |
|
| 304 |
+
web_search_node_agent = big_model.bind_tools(search_tools, parallel_tool_calls=False)
|
| 305 |
|
| 306 |
def thinking_node(state: State) -> dict:
|
| 307 |
"""
|
|
|
|
| 339 |
|
| 340 |
sys_msg = SystemMessage(content=prompt)
|
| 341 |
|
| 342 |
+
thinking_node_response = [big_model.invoke([sys_msg] + [state["thinking_node_result"]])]
|
| 343 |
|
| 344 |
thinking_node_response[-1].pretty_print()
|
| 345 |
|
|
|
|
| 383 |
|
| 384 |
sys_msg = SystemMessage(content=prompt)
|
| 385 |
|
| 386 |
+
code_node_response = [big_model.invoke([sys_msg])]
|
| 387 |
|
| 388 |
code_node_response[-1].pretty_print()
|
| 389 |
|
|
|
|
| 451 |
"web_wiki_search_node_result": web_wiki_search_node_response,
|
| 452 |
}
|
| 453 |
|
|
|
|
| 454 |
def vision_node(state: State) -> dict:
|
| 455 |
"""
|
| 456 |
Vision model that can analyze images and pictures and answer questions about them.
|
|
|
|
| 471 |
You do not handle audio
|
| 472 |
You do not handle code
|
| 473 |
|
| 474 |
+
1. You need to fully understand the question.
|
| 475 |
+
2. You must think hard about what is relevant in the image to make the best answer to the question.
|
| 476 |
+
3. Report your thought process in detail, explaining your reasoning step-by-step.
|
| 477 |
|
| 478 |
Here is the question {state['question']}
|
| 479 |
Now provide your response immediately without any preamble in text but not in markdown.
|
|
|
|
| 557 |
You do not handle audio.
|
| 558 |
You do not handle code.
|
| 559 |
|
| 560 |
+
1. You need to fully understand the question.
|
| 561 |
2. Carefully observe the video, paying attention to relevant details, actions, and context.
|
| 562 |
3. Focus on the user's question.
|
| 563 |
4. If the question requires counting, identifying, or describing, be precise and clear in your response.
|
|
|
|
| 640 |
You do not handle video.
|
| 641 |
You do not handle code.
|
| 642 |
|
| 643 |
+
1. You need to fully understand the question.
|
| 644 |
2. Carefully listen to the audio, paying attention to relevant details, actions, and context.
|
| 645 |
3. Focus on the user's question.
|
| 646 |
4. If the question requires counting, identifying, or describing, be precise and clear in your response.
|
|
|
|
| 694 |
"audio_node_result": audio_node_response
|
| 695 |
}
|
| 696 |
|
| 697 |
+
def excel_node(state: State):
|
| 698 |
+
"""
|
| 699 |
+
Excel handler model that can analyze excel files and answer questions about it.
|
| 700 |
+
This node does not handle images or pictures.
|
| 701 |
+
This node does not handle video.
|
| 702 |
+
This node does not handle code.
|
| 703 |
+
This node does not handle audio.
|
| 704 |
+
|
| 705 |
+
Args:
|
| 706 |
+
state (State): with question key inside
|
| 707 |
+
|
| 708 |
+
Returns:
|
| 709 |
+
dict: A dictionary containing the response from the excel handler node, with the key 'excel_node_result' holding the list of messages generated by the excel handler model.
|
| 710 |
+
"""
|
| 711 |
+
|
| 712 |
+
loader = UnstructuredExcelLoader(state["downloaded_file"], mode="elements")
|
| 713 |
+
docs = loader.load()
|
| 714 |
+
|
| 715 |
+
prompt = f"""
|
| 716 |
+
You are a powerful assistant which handles excel files.
|
| 717 |
+
You do not handle images or pictures.
|
| 718 |
+
You do not handle video.
|
| 719 |
+
You do not handle code.
|
| 720 |
+
You do not handle audio
|
| 721 |
+
|
| 722 |
+
1. You need to fully understand the question.
|
| 723 |
+
2. You must analyze the excel file to answer the question.
|
| 724 |
+
3. If the question requires counting, identifying, or describing, be precise and clear in your response.
|
| 725 |
+
4. Do not make up information that is not in the excel file.
|
| 726 |
+
|
| 727 |
+
Here is the question {state['question']}
|
| 728 |
+
Here is the excel file loaded in a Document object: {docs}. You will find htlm content of the file in the 'text_as_html' key.
|
| 729 |
+
|
| 730 |
+
Now provide your response immediately without any preamble in text but not in markdown.
|
| 731 |
+
"""
|
| 732 |
+
|
| 733 |
+
response = big_model.invoke(
|
| 734 |
+
input=prompt,
|
| 735 |
+
# config={
|
| 736 |
+
# "callbacks": [langfuse_handler]
|
| 737 |
+
# }
|
| 738 |
+
)
|
| 739 |
+
|
| 740 |
+
response.pretty_print()
|
| 741 |
+
|
| 742 |
+
return {
|
| 743 |
+
"excel_node_result": response
|
| 744 |
+
}
|
| 745 |
+
|
| 746 |
def format_answer_node(state: State):
|
| 747 |
+
"""
|
| 748 |
+
Format answer node that formats the answer of the last node.
|
| 749 |
+
This node does not handle images or pictures.
|
| 750 |
+
This node does not handle video.
|
| 751 |
+
This node does not handle audio.
|
| 752 |
+
This node does not handle code.
|
| 753 |
+
|
| 754 |
+
Args:
|
| 755 |
+
state (State): with question key inside, and all other nodes results
|
| 756 |
+
|
| 757 |
+
Returns:
|
| 758 |
+
dict: A dictionary containing the response from the format answer node, with the key 'format_answer_node_result' holding the list of messages generated by the format answer model.
|
| 759 |
+
"""
|
| 760 |
|
| 761 |
prompt = """
|
| 762 |
You are the best assistant for final answer formating.
|
|
|
|
| 783 |
- If asked for a comma-separated list:
|
| 784 |
- Apply the above rules for numbers and strings to each element in the list.
|
| 785 |
- And take care of having a space after each comma.
|
|
|
|
| 786 |
|
| 787 |
## Constraints
|
| 788 |
- You must not answer if the constraints above are not respected.
|
|
|
|
| 796 |
|
| 797 |
question = [HumanMessage(content=state["question"])]
|
| 798 |
|
| 799 |
+
for node_result in ["web_wiki_search_node_result", "vision_node_result", "video_node_result", "audio_node_result", "thinking_node_result", "code_node_result", "excel_node_result"]:
|
| 800 |
result = state.get(node_result, "")
|
| 801 |
if result:
|
| 802 |
# Ensure result is a string. If it's a message object, extract its content.
|
|
|
|
| 808 |
|
| 809 |
sys_msg = SystemMessage(content=prompt)
|
| 810 |
|
| 811 |
+
response = [big_model.invoke([sys_msg] + state["messages"]+ question + nodes_response)]
|
| 812 |
|
| 813 |
return {
|
| 814 |
"messages": response,
|
|
|
|
| 834 |
- .wav or .mp3 is for audio
|
| 835 |
- a youtube url is for video
|
| 836 |
- a .jpg, .png, .jpeg is for image
|
| 837 |
+
- a .xlsx or .xls is for excel
|
| 838 |
3. You must think hard about what is relevant in the question to make the best choice for the next node
|
| 839 |
4. You must not answer the question by yourself
|
| 840 |
5. Report your thought process in detail, explaining your reasoning step-by-step.
|
|
|
|
| 846 |
- video_node: {video_node.__doc__}
|
| 847 |
- audio_node: {audio_node.__doc__}
|
| 848 |
- code_node: {code_node.__doc__}
|
| 849 |
+
- excel_node: {excel_node.__doc__}
|
| 850 |
|
| 851 |
Here is the question : {state['question']}
|
| 852 |
Here is the file : {state.get("input_file", "no file to handle")}
|
|
|
|
| 861 |
|
| 862 |
sys_msg = SystemMessage(content=system_prompt)
|
| 863 |
|
| 864 |
+
entry_node_response = [light_model.invoke([sys_msg] + state["messages"])]
|
| 865 |
|
| 866 |
entry_node_response[-1].pretty_print()
|
| 867 |
|
| 868 |
+
regex_result = re.search(r'.*next\s*node.*(?P<next_node>thinking_node|web_wiki_search_node|vision_node|video_node|audio_node|code_node|excel_node).*$', entry_node_response[-1].content, re.IGNORECASE)
|
| 869 |
|
| 870 |
next_node = "END"
|
| 871 |
if regex_result:
|
|
|
|
| 893 |
builder.add_node("audio_node", audio_node)
|
| 894 |
builder.add_node("code_node", code_node)
|
| 895 |
builder.add_node("thinking_node", thinking_node)
|
| 896 |
+
builder.add_node("excel_node", excel_node)
|
| 897 |
builder.add_node("format_answer_node", format_answer_node)
|
| 898 |
|
| 899 |
builder.add_edge(START, "entry_node")
|
|
|
|
| 908 |
"video_node": "video_node",
|
| 909 |
"audio_node": "audio_node",
|
| 910 |
"code_node": "code_node",
|
| 911 |
+
"excel_node": "excel_node",
|
| 912 |
"thinking_node": "thinking_node"
|
| 913 |
}
|
| 914 |
)
|
|
|
|
| 918 |
builder.add_edge("video_node", "format_answer_node")
|
| 919 |
builder.add_edge("audio_node", "format_answer_node")
|
| 920 |
builder.add_edge("code_node", "format_answer_node")
|
| 921 |
+
builder.add_edge("excel_node", "format_answer_node")
|
| 922 |
builder.add_edge("thinking_node", "format_answer_node")
|
| 923 |
builder.add_edge("format_answer_node", END)
|
| 924 |
|
|
|
|
| 939 |
with open("./responses.json", "r") as responses:
|
| 940 |
json_responses = json.loads(responses.read())
|
| 941 |
|
| 942 |
+
# json_questions = [{
|
| 943 |
+
# "question": "The attached Excel file contains the sales of menu items for a local fast-food chain. What were the total sales that the chain made from food (not including drinks)? Express your answer in USD with two decimal places.",
|
| 944 |
+
# "file_name": "7bd855d8-463d-4ed5-93ca-5fe35145f733.xlsx",
|
| 945 |
+
# "task_id": "7bd855d8-463d-4ed5-93ca-5fe35145f733"
|
| 946 |
+
# }]
|
|
|
|
| 947 |
|
| 948 |
with open("questions.json", "r") as questions:
|
| 949 |
json_questions = json.loads(questions.read())
|
|
|
|
| 987 |
print(f"Expected: {json_responses.get(task_id, '')}")
|
| 988 |
print(f"Got: {answer}")
|
| 989 |
|
|
|
|
|
|