Spaces:
Sleeping
Sleeping
Update agentic.py
Browse files- agentic.py +32 -43
agentic.py
CHANGED
|
@@ -46,7 +46,7 @@ class State(TypedDict):
|
|
| 46 |
input_file: str
|
| 47 |
downloaded_file: Optional[str]
|
| 48 |
task_id: str
|
| 49 |
-
|
| 50 |
thinking_node_result: AnyMessage
|
| 51 |
vision_node_result: AnyMessage
|
| 52 |
video_node_result: AnyMessage
|
|
@@ -58,20 +58,20 @@ class State(TypedDict):
|
|
| 58 |
########################
|
| 59 |
|
| 60 |
######## MODELS ########
|
| 61 |
-
def
|
| 62 |
|
| 63 |
llm_provider = os.getenv("LLM_PROVIDER", "mistral")
|
| 64 |
|
| 65 |
if llm_provider == "mistral":
|
| 66 |
-
|
| 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 |
-
|
| 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,23 +80,12 @@ def get_light_model():
|
|
| 80 |
aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY")
|
| 81 |
)
|
| 82 |
|
| 83 |
-
return
|
| 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",
|
| 100 |
temperature=0,
|
| 101 |
max_retries=2,
|
| 102 |
api_key=os.getenv("MISTRAL_API_KEY")
|
|
@@ -281,15 +270,13 @@ def download_input_file(task_id: str) -> str:
|
|
| 281 |
|
| 282 |
######## LLM associations ########
|
| 283 |
|
| 284 |
-
|
| 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 ########
|
|
@@ -329,7 +316,8 @@ You do not handle code
|
|
| 329 |
|
| 330 |
1. You need to fully understand the question
|
| 331 |
2. You must think hard about what is relevant in the question to make the best answer
|
| 332 |
-
3.
|
|
|
|
| 333 |
|
| 334 |
Here is the question {state['question']}
|
| 335 |
Now provide your response immediately without any preamble in text but not in markdown.
|
|
@@ -339,7 +327,7 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 339 |
|
| 340 |
sys_msg = SystemMessage(content=prompt)
|
| 341 |
|
| 342 |
-
thinking_node_response = [
|
| 343 |
|
| 344 |
thinking_node_response[-1].pretty_print()
|
| 345 |
|
|
@@ -391,7 +379,7 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 391 |
"code_node_result": code_node_response,
|
| 392 |
}
|
| 393 |
|
| 394 |
-
def
|
| 395 |
"""
|
| 396 |
A powerful node to answer questions and make research on the web based on the question provided in the state.
|
| 397 |
This node does not handle files
|
|
@@ -404,7 +392,7 @@ Args:
|
|
| 404 |
state (State): A dictionary containing the current state of the agent, including the 'question' key which holds the question to be answered.
|
| 405 |
|
| 406 |
Returns:
|
| 407 |
-
dict: A dictionary containing the response from the web search node, with the key '
|
| 408 |
"""
|
| 409 |
|
| 410 |
prompt = f"""
|
|
@@ -439,16 +427,16 @@ Here is the question {state['question']}
|
|
| 439 |
Now provide your response immediately without any preamble in text but not in markdown.
|
| 440 |
"""
|
| 441 |
|
| 442 |
-
state["
|
| 443 |
|
| 444 |
sys_msg = SystemMessage(content=prompt)
|
| 445 |
|
| 446 |
-
|
| 447 |
|
| 448 |
-
|
| 449 |
|
| 450 |
return {
|
| 451 |
-
"
|
| 452 |
}
|
| 453 |
|
| 454 |
def vision_node(state: State) -> dict:
|
|
@@ -796,7 +784,7 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 796 |
|
| 797 |
question = [HumanMessage(content=state["question"])]
|
| 798 |
|
| 799 |
-
for node_result in ["
|
| 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,7 +796,7 @@ Now provide your response immediately without any preamble in text but not in ma
|
|
| 808 |
|
| 809 |
sys_msg = SystemMessage(content=prompt)
|
| 810 |
|
| 811 |
-
response = [
|
| 812 |
|
| 813 |
return {
|
| 814 |
"messages": response,
|
|
@@ -841,7 +829,7 @@ You do not handle code
|
|
| 841 |
|
| 842 |
Here are the nodes you can choose:
|
| 843 |
- thinking_node: {thinking_node.__doc__}
|
| 844 |
-
-
|
| 845 |
- vision_node: {vision_node.__doc__}
|
| 846 |
- video_node: {video_node.__doc__}
|
| 847 |
- audio_node: {audio_node.__doc__}
|
|
@@ -865,7 +853,7 @@ Now provide your response immediately respecting this format in lower case: 'nex
|
|
| 865 |
|
| 866 |
entry_node_response[-1].pretty_print()
|
| 867 |
|
| 868 |
-
regex_result = re.search(r'.*next\s*node.*(?P<next_node>thinking_node|
|
| 869 |
|
| 870 |
next_node = "END"
|
| 871 |
if regex_result:
|
|
@@ -887,7 +875,7 @@ Now provide your response immediately respecting this format in lower case: 'nex
|
|
| 887 |
def build_graph():
|
| 888 |
builder = StateGraph(State)
|
| 889 |
builder.add_node("entry_node", entry_node)
|
| 890 |
-
builder.add_node("
|
| 891 |
builder.add_node("vision_node", vision_node)
|
| 892 |
builder.add_node("video_node", video_node)
|
| 893 |
builder.add_node("audio_node", audio_node)
|
|
@@ -903,7 +891,7 @@ def build_graph():
|
|
| 903 |
"entry_node",
|
| 904 |
lambda state: state["next_node"],
|
| 905 |
{
|
| 906 |
-
"
|
| 907 |
"vision_node": "vision_node",
|
| 908 |
"video_node": "video_node",
|
| 909 |
"audio_node": "audio_node",
|
|
@@ -913,7 +901,7 @@ def build_graph():
|
|
| 913 |
}
|
| 914 |
)
|
| 915 |
# After specialized node, go to END
|
| 916 |
-
builder.add_edge("
|
| 917 |
builder.add_edge("vision_node", "format_answer_node")
|
| 918 |
builder.add_edge("video_node", "format_answer_node")
|
| 919 |
builder.add_edge("audio_node", "format_answer_node")
|
|
@@ -939,14 +927,15 @@ if __name__ == "__main__":
|
|
| 939 |
with open("./responses.json", "r") as responses:
|
| 940 |
json_responses = json.loads(responses.read())
|
| 941 |
|
| 942 |
-
|
| 943 |
-
|
| 944 |
-
|
| 945 |
-
|
| 946 |
-
|
|
|
|
| 947 |
|
| 948 |
-
with open("questions.json", "r") as questions:
|
| 949 |
-
|
| 950 |
|
| 951 |
for input in json_questions:
|
| 952 |
|
|
|
|
| 46 |
input_file: str
|
| 47 |
downloaded_file: Optional[str]
|
| 48 |
task_id: str
|
| 49 |
+
web_search_node_result: AnyMessage
|
| 50 |
thinking_node_result: AnyMessage
|
| 51 |
vision_node_result: AnyMessage
|
| 52 |
video_node_result: AnyMessage
|
|
|
|
| 58 |
########################
|
| 59 |
|
| 60 |
######## MODELS ########
|
| 61 |
+
def get_general_model():
|
| 62 |
|
| 63 |
llm_provider = os.getenv("LLM_PROVIDER", "mistral")
|
| 64 |
|
| 65 |
if llm_provider == "mistral":
|
| 66 |
+
general_model = ChatMistralAI(
|
| 67 |
+
model="mistral-large-2411",#"ministral-8b-latest",#"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 |
+
general_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 general_model
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
def get_big_model():
|
| 86 |
|
| 87 |
big_model = ChatMistralAI(
|
| 88 |
+
model="mistral-medium-2505",
|
| 89 |
temperature=0,
|
| 90 |
max_retries=2,
|
| 91 |
api_key=os.getenv("MISTRAL_API_KEY")
|
|
|
|
| 270 |
|
| 271 |
######## LLM associations ########
|
| 272 |
|
| 273 |
+
general_model = get_general_model()
|
|
|
|
| 274 |
big_model = get_big_model()
|
| 275 |
|
| 276 |
vision_model = get_vision_model()
|
| 277 |
video_handler_model = get_video_handler_model()
|
| 278 |
audio_handler_model = get_audio_handler_model()
|
| 279 |
|
|
|
|
| 280 |
########################
|
| 281 |
|
| 282 |
######## Nodes Definition ########
|
|
|
|
| 316 |
|
| 317 |
1. You need to fully understand the question
|
| 318 |
2. You must think hard about what is relevant in the question to make the best answer
|
| 319 |
+
3. If there are calculations or maths, you need to verify twice before answering.
|
| 320 |
+
4. Report your thought process in detail, explaining your reasoning step-by-step.
|
| 321 |
|
| 322 |
Here is the question {state['question']}
|
| 323 |
Now provide your response immediately without any preamble in text but not in markdown.
|
|
|
|
| 327 |
|
| 328 |
sys_msg = SystemMessage(content=prompt)
|
| 329 |
|
| 330 |
+
thinking_node_response = [general_model.invoke([sys_msg] + [state["thinking_node_result"]])]
|
| 331 |
|
| 332 |
thinking_node_response[-1].pretty_print()
|
| 333 |
|
|
|
|
| 379 |
"code_node_result": code_node_response,
|
| 380 |
}
|
| 381 |
|
| 382 |
+
def web_search_node(state: State) -> dict:
|
| 383 |
"""
|
| 384 |
A powerful node to answer questions and make research on the web based on the question provided in the state.
|
| 385 |
This node does not handle files
|
|
|
|
| 392 |
state (State): A dictionary containing the current state of the agent, including the 'question' key which holds the question to be answered.
|
| 393 |
|
| 394 |
Returns:
|
| 395 |
+
dict: A dictionary containing the response from the web search node, with the key 'web_search_node_result' holding the list of messages generated by the general model.
|
| 396 |
"""
|
| 397 |
|
| 398 |
prompt = f"""
|
|
|
|
| 427 |
Now provide your response immediately without any preamble in text but not in markdown.
|
| 428 |
"""
|
| 429 |
|
| 430 |
+
state["web_search_node_result"] = state.get("web_search_node_result", "")
|
| 431 |
|
| 432 |
sys_msg = SystemMessage(content=prompt)
|
| 433 |
|
| 434 |
+
web_search_node_response = [web_search_node_agent.invoke([sys_msg] + [state["web_search_node_result"]])]
|
| 435 |
|
| 436 |
+
web_search_node_response[-1].pretty_print()
|
| 437 |
|
| 438 |
return {
|
| 439 |
+
"web_search_node_result": web_search_node_response,
|
| 440 |
}
|
| 441 |
|
| 442 |
def vision_node(state: State) -> dict:
|
|
|
|
| 784 |
|
| 785 |
question = [HumanMessage(content=state["question"])]
|
| 786 |
|
| 787 |
+
for node_result in ["web_search_node_result", "vision_node_result", "video_node_result", "audio_node_result", "thinking_node_result", "code_node_result", "excel_node_result"]:
|
| 788 |
result = state.get(node_result, "")
|
| 789 |
if result:
|
| 790 |
# Ensure result is a string. If it's a message object, extract its content.
|
|
|
|
| 796 |
|
| 797 |
sys_msg = SystemMessage(content=prompt)
|
| 798 |
|
| 799 |
+
response = [general_model.invoke([sys_msg] + state["messages"]+ question + nodes_response)]
|
| 800 |
|
| 801 |
return {
|
| 802 |
"messages": response,
|
|
|
|
| 829 |
|
| 830 |
Here are the nodes you can choose:
|
| 831 |
- thinking_node: {thinking_node.__doc__}
|
| 832 |
+
- web_search_node: {web_search_node.__doc__}
|
| 833 |
- vision_node: {vision_node.__doc__}
|
| 834 |
- video_node: {video_node.__doc__}
|
| 835 |
- audio_node: {audio_node.__doc__}
|
|
|
|
| 853 |
|
| 854 |
entry_node_response[-1].pretty_print()
|
| 855 |
|
| 856 |
+
regex_result = re.search(r'.*next\s*node.*(?P<next_node>thinking_node|web_search_node|vision_node|video_node|audio_node|code_node|excel_node).*$', entry_node_response[-1].content, re.IGNORECASE)
|
| 857 |
|
| 858 |
next_node = "END"
|
| 859 |
if regex_result:
|
|
|
|
| 875 |
def build_graph():
|
| 876 |
builder = StateGraph(State)
|
| 877 |
builder.add_node("entry_node", entry_node)
|
| 878 |
+
builder.add_node("web_search_node", web_search_node)
|
| 879 |
builder.add_node("vision_node", vision_node)
|
| 880 |
builder.add_node("video_node", video_node)
|
| 881 |
builder.add_node("audio_node", audio_node)
|
|
|
|
| 891 |
"entry_node",
|
| 892 |
lambda state: state["next_node"],
|
| 893 |
{
|
| 894 |
+
"web_search_node": "web_search_node",
|
| 895 |
"vision_node": "vision_node",
|
| 896 |
"video_node": "video_node",
|
| 897 |
"audio_node": "audio_node",
|
|
|
|
| 901 |
}
|
| 902 |
)
|
| 903 |
# After specialized node, go to END
|
| 904 |
+
builder.add_edge("web_search_node", "format_answer_node")
|
| 905 |
builder.add_edge("vision_node", "format_answer_node")
|
| 906 |
builder.add_edge("video_node", "format_answer_node")
|
| 907 |
builder.add_edge("audio_node", "format_answer_node")
|
|
|
|
| 927 |
with open("./responses.json", "r") as responses:
|
| 928 |
json_responses = json.loads(responses.read())
|
| 929 |
|
| 930 |
+
json_questions = [{
|
| 931 |
+
"task_id": "840bfca7-4f7b-481a-8794-c560c340185d",
|
| 932 |
+
"question": "On June 6, 2023, an article by Carolyn Collins Petersen was published in Universe Today. This article mentions a team that produced a paper about their observations, linked at the bottom of the article. Find this paper. Under what NASA award number was the work performed by R. G. Arendt supported by?",
|
| 933 |
+
"Level": "1",
|
| 934 |
+
"file_name": ""
|
| 935 |
+
}]
|
| 936 |
|
| 937 |
+
# with open("questions.json", "r") as questions:
|
| 938 |
+
# json_questions = json.loads(questions.read())
|
| 939 |
|
| 940 |
for input in json_questions:
|
| 941 |
|