Nguyen Nhu Trung
fix system prompt
528d7ce
raw
history blame
6.99 kB
import os
from dotenv import load_dotenv
import pandas as pd
import json
from langgraph.graph import START, StateGraph, MessagesState
from langgraph.prebuilt import tools_condition
from langgraph.prebuilt import ToolNode
from langchain_groq import ChatGroq
from langchain_community.tools import DuckDuckGoSearchResults
from langchain_community.document_loaders import WikipediaLoader
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.tools import tool
from langchain_core.output_parsers import StrOutputParser
from langchain_core.tools import Tool
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_experimental.utilities import PythonREPL
import assemblyai as aai
load_dotenv()
aai.settings.api_key = os.getenv("ASSEMBLY_AI_KEY")
repl_tool = Tool(
name="python_repl",
description="A Python shell. Use this to execute python commands. Input should be a valid python command. If you want to see the output of a value, you should print it out with `print(...)`.",
func=PythonREPL().run,
)
@tool
def read_excel_file(excel_file_path: str) -> str:
"""Read the content of excel file.
Args:
excel_file_path: path to excel file
"""
# Load the Excel file using pandas
try:
# Read the Excel file
df = pd.read_excel(excel_file_path, sheet_name=None) # sheet_name=None loads all sheets
# Convert each sheet to a dictionary of rows
json_output = {}
for sheet_name, sheet_data in df.items():
# Convert the dataframe to a list of dictionaries (rows)
json_output[sheet_name] = sheet_data.to_dict(orient="records")
# Convert the result to a JSON formatted string
json_result = json.dumps(json_output, indent=4)
return json_result
except Exception as e:
return str(e)
@tool
def transcribe_audio(file_path: str) -> str:
"""Transcribe the audio file into text.
Args:
file_path: path to audio file
"""
config = aai.TranscriptionConfig(speech_model=aai.SpeechModel.best)
transcript = aai.Transcriber(config=config).transcribe(file_path)
if transcript.status == "error":
raise RuntimeError(f"Transcription failed: {transcript.error}")
return f"Here is the transcript: {transcript.text}"
@tool
def wiki_search(query: str) -> str:
"""Search Wikipedia for a query and return maximum 2 results.
Args:
query: The search query."""
search_docs = WikipediaLoader(query=query, load_max_docs=2).load()
formatted_search_docs = "\n\n---\n\n".join(
[
f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}\n</Document>'
for doc in search_docs
])
return {"wiki_results": formatted_search_docs}
# @tool
# def web_search(query: str) -> str:
# """Search DuckDuckGo for a query and return maximum 5 results.
# Args:
# query: The search query."""
# search_docs = DuckDuckGoSearchResults(max_results=5).invoke(query)
# return {"web_results": search_docs}
@tool
def web_search(query: str) -> str:
"""Search Tavily for a query and return maximum 3 results.
Args:
query: The search query."""
search_docs = TavilySearchResults(max_results=3).invoke(query=query)
formatted_search_docs = "\n\n---\n\n".join(
[
f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}\n</Document>'
for doc in search_docs
])
return {"web_results": formatted_search_docs}
system_prompt = """
You are a helpful assistant tasked with answering questions using a set of tools.
Now, I will ask you a question. Report your thoughts, and finish your answer with the following template:
FINAL ANSWER: [YOUR FINAL ANSWER].
YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.
Your answer should only start with "FINAL ANSWER: ", then follows with the answer.
"""
sys_msg = SystemMessage(content=system_prompt)
tools = [
wiki_search,
web_search,
repl_tool,
read_excel_file,
transcribe_audio
]
llm = ChatGroq(model="qwen-qwq-32b", temperature=0.7)
llm_with_tools = llm.bind_tools(tools)
def assistant(state: MessagesState):
"""Assistant node"""
return {"messages": [llm_with_tools.invoke(state["messages"])]}
def final_answer(answer):
print(f"ANSWER: {answer}")
return answer.replace("FINAL ANSWER:","")
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")
graph = builder.compile()
def get_answer(query):
messages = [sys_msg, HumanMessage(content=query)]
results = graph.invoke({"messages": messages})
return final_answer(results["messages"][-1].content)
if __name__ == "__main__":
question = "In the video https://www.youtube.com/watch?v=L1vXCYZAYYM, what is the highest number of bird species to be on camera simultaneously?"
question = "Hi, I was out sick from my classes on Friday, so I'm trying to figure out what I need to study for my Calculus mid-term next week. My friend from class sent me an audio recording of Professor Willowbrook giving out the recommended reading for the test, but my headphones are broken :(\n\nCould you please listen to the recording for me and tell me the page numbers I'm supposed to go over? I've attached a file called Homework.mp3 that has the recording. Please provide just the page numbers as a comma-delimited list. And please provide the list in ascending order."
question = "What is the first name of the only Malko Competition recipient from the 20th Century (after 1977) whose nationality on record is a country that no longer exists?"
question = "Where were the Vietnamese specimens described by Kuznetzov in Nedoshivina's 2010 paper eventually deposited? Just give me the city name without abbreviations."
# getmessages = [HumanMessage(content=question)]
# messages = graph.invoke({"messages": messages})
# for m in messages["messages"]:
# m.pretty_print()
print(f"FINAL ANSWER: {get_answer(question)}")