tool_use #1
@ -99,6 +99,8 @@
|
||||
.thought-summary.tool_result { background-color: #27ae60; }
|
||||
.thought-summary.think_more { background-color: #2980b9; }
|
||||
.thought-summary.answer { background-color: #8e44ad; }
|
||||
.thought-summary.reply { background-color: #f39c12; }
|
||||
.thought-summary.thoughts { background-color: #f39c12; }
|
||||
.thought-details {
|
||||
display: none;
|
||||
margin-left: 20px;
|
||||
|
103
main.py
103
main.py
@ -77,7 +77,7 @@ def answer_question_tools(user_input: str, conversation_history: List[dict], max
|
||||
emit('thinking', {'step': 'Starting'})
|
||||
emit('conversation_history', {'history': conversation_history})
|
||||
|
||||
for iteration in range(max_retries):
|
||||
for _ in range(max_retries):
|
||||
response = ollama.chat(model=PRIMARY_MODEL, messages=conversation_history, tools=tool_manager.get_tools_for_ollama_dict(), stream=False)
|
||||
assistant_message = response['message']
|
||||
|
||||
@ -86,7 +86,6 @@ def answer_question_tools(user_input: str, conversation_history: List[dict], max
|
||||
pprint.pp(assistant_message)
|
||||
|
||||
if 'tool_calls' in assistant_message:
|
||||
emit('thought', {'type': 'decision', 'content': "Tool Call\n\n" + assistant_message['content']})
|
||||
for tool_call in assistant_message['tool_calls']:
|
||||
tool_name = tool_call['function']['name']
|
||||
tool_args = tool_call['function']['arguments']
|
||||
@ -98,40 +97,20 @@ def answer_question_tools(user_input: str, conversation_history: List[dict], max
|
||||
})
|
||||
emit('conversation_history', {'history': conversation_history})
|
||||
emit('thought', {'type': 'tool_result', 'content': tool_response})
|
||||
|
||||
reflection_prompt = "Reflect on the tool results. If there were any errors, propose multiple alternative approaches to solve the problem. If successful, consider if the result fully answers the user's query or if additional steps are needed. If input is needed, ask the user for clarification with <answer></answer>."
|
||||
conversation_history.append({
|
||||
"role": "assistant",
|
||||
"content": reflection_prompt
|
||||
})
|
||||
emit('conversation_history', {'history': conversation_history})
|
||||
else:
|
||||
if "<answer>" in assistant_message['content'].lower():
|
||||
answer_content = re.search(r'<answer>(.*?)</answer>', assistant_message['content'], re.DOTALL)
|
||||
if answer_content:
|
||||
final_answer = answer_content.group(1).strip()
|
||||
emit('thought', {'type': 'answer', 'content': final_answer})
|
||||
return final_answer
|
||||
elif "<clarification>" in assistant_message['content'].lower():
|
||||
clarification_content = re.search(r'<clarification>(.*?)</clarification>', assistant_message['content'], re.DOTALL)
|
||||
if clarification_content:
|
||||
clarification_answer = clarification_content.group(1).strip()
|
||||
emit('thought', {'type': 'clarification', 'content': clarification_answer})
|
||||
return clarification_answer
|
||||
if "<reply>" in assistant_message['content'].lower():
|
||||
reply_content = re.search(r'<reply>(.*?)</reply>', assistant_message['content'], re.DOTALL)
|
||||
if reply_content:
|
||||
reply_answer = reply_content.group(1).strip()
|
||||
emit('thought', {'type': 'answer', 'content': reply_answer})
|
||||
return reply_answer
|
||||
else:
|
||||
if assistant_message['content'].strip():
|
||||
emit('thought', {'type': 'think_more', 'content': "Think/Plan/Decision/Action\n\n" + assistant_message['content']})
|
||||
reflection_prompt = "Your last response didn't provide a final answer or was incorrectly formatted. Please reflect on your current understanding of the problem and consider if you need to use any tools or if you can now provide a final answer. If you're ready to give a final answer, or need more input from the user, put your response in tags <answer></answer>."
|
||||
else:
|
||||
emit('thought', {'type': 'think_more', 'content': "Previous step failed. Retrying..."})
|
||||
reflection_prompt = "The previous step failed to produce any content. Please retry the previous step, considering alternative approaches or tools that might help solve the problem. If you're ready to give a final answer, or need more input from the user, put your response in tags <answer></answer>."
|
||||
|
||||
conversation_history.append({"role": "assistant", "content": reflection_prompt})
|
||||
emit('conversation_history', {'history': conversation_history})
|
||||
emit('thought', {'type': 'thoughts', 'content': assistant_message['content']})
|
||||
continue
|
||||
|
||||
return f"Max iterations reached. Last response: {assistant_message['content']}"
|
||||
|
||||
ANSWER_QUESTION_PROMPT = f"""
|
||||
ANSWER_QUESTION_PROMPT2 = f"""
|
||||
The current date is {datetime.now().strftime("%A, %B %d, %Y")}, your knowledge cutoff was December 2023.
|
||||
You are Dewey, an AI assistant with access to external tools and the ability to think through complex problems. Your role is to assist users by leveraging tools when necessary, thinking deeply about problems, and providing accurate and helpful information, all with a cheerful, but witty personality. Here are the tools available to you:
|
||||
|
||||
@ -165,6 +144,68 @@ Remember, complex problems often require multiple steps and iterations. Don't he
|
||||
Before approaching a problem, come up with a few ways you might solve it, and then choose the most promising approach. Repeat this on each iteration.
|
||||
"""
|
||||
|
||||
|
||||
ANSWER_QUESTION_PROMPT = f"""
|
||||
You are Dewey, an AI assistant with a personality that combines the wit and sarcasm of Dr. Gregory House from House MD with the helpfulness and intelligence of Jarvis from Iron Man. Today's date is {datetime.now().strftime("%A, %B %d, %Y")}. Your knowledge cutoff date is December 2023.
|
||||
When responding to user queries, follow these steps:
|
||||
|
||||
Analyze the user's request
|
||||
|
||||
Option 1: [First interpretation of the request]
|
||||
Option 2: [Second interpretation of the request]
|
||||
... (up to 5 options)
|
||||
|
||||
Selected approach: [Choose the most promising option or combine the two best]
|
||||
Break down the task into subtasks
|
||||
|
||||
Option 1: [First breakdown of subtasks]
|
||||
Option 2: [Second breakdown of subtasks]
|
||||
... (up to 5 options)
|
||||
|
||||
Selected breakdown: [Choose the most promising option or combine the two best]
|
||||
For each subtask, consider available tools:
|
||||
{tool_manager.get_tools_and_descriptions_for_prompt()}
|
||||
|
||||
Option 1: [First approach using tools]
|
||||
Option 2: [Second approach using tools]
|
||||
... (up to 5 options)
|
||||
|
||||
Selected tool usage: [Choose the most promising option or combine the two best]
|
||||
Execute the plan
|
||||
|
||||
Option 1: [First execution plan]
|
||||
Option 2: [Second execution plan]
|
||||
... (up to 5 options)
|
||||
|
||||
Selected execution: [Choose the most promising option or combine the two best]
|
||||
Review and refine the response
|
||||
|
||||
Option 1: [First refined response]
|
||||
Option 2: [Second refined response]
|
||||
... (up to 5 options)
|
||||
|
||||
Selected response: [Choose the most promising option or combine the two best]
|
||||
Verify the results
|
||||
|
||||
Check 1: [First verification method]
|
||||
Check 2: [Second verification method]
|
||||
... (up to 5 checks)
|
||||
|
||||
Verification outcome: [Summarize the verification results]
|
||||
Generate the final response to the user within <reply></reply> tags:
|
||||
|
||||
<reply>
|
||||
[Final response goes here, incorporating the following guidelines:]
|
||||
- Be conversational and engaging
|
||||
- Maintain a witty and slightly sarcastic tone, reminiscent of Dr. Gregory House
|
||||
- Deliver factual information with the precision and helpfulness of Jarvis
|
||||
- Use clever analogies or pop culture references when appropriate
|
||||
- Don't be afraid to challenge the user's assumptions, but always in a constructive manner
|
||||
- Ensure the response is tailored to the user's query while showcasing your unique personality
|
||||
</reply>
|
||||
Remember to always be helpful, accurate, and respectful in your interactions, while maintaining your distinctive character blend of House and Jarvis.
|
||||
"""
|
||||
|
||||
PRIMARY_MODEL = "qwen2.5:14b"
|
||||
|
||||
UPDATE_INTERVAL = 0.1 # 100ms, configurable
|
||||
|
@ -4,11 +4,18 @@ aiohttp==3.10.5
|
||||
aiosignal==1.3.1
|
||||
annotated-types==0.7.0
|
||||
anyio==4.6.0
|
||||
art==6.3
|
||||
attrs==24.2.0
|
||||
beautifulsoup4==4.12.3
|
||||
bidict==0.23.1
|
||||
blinker==1.8.2
|
||||
bs4==0.0.2
|
||||
certifi==2024.7.4
|
||||
chardet==5.2.0
|
||||
charset-normalizer==3.3.2
|
||||
click==8.1.7
|
||||
cloudpickle==3.0.0
|
||||
cssselect==1.2.0
|
||||
datasets==3.0.0
|
||||
dill==0.3.8
|
||||
diskcache==5.6.3
|
||||
@ -17,9 +24,13 @@ duckduckgo_search==6.2.6
|
||||
einops==0.8.0
|
||||
fastapi==0.115.0
|
||||
filelock==3.15.4
|
||||
Flask==3.0.3
|
||||
flask-openapi3==3.1.3
|
||||
Flask-SocketIO==5.3.7
|
||||
frozenlist==1.4.1
|
||||
fsspec==2024.6.1
|
||||
gguf==0.9.1
|
||||
GPUtil==1.4.0
|
||||
h11==0.14.0
|
||||
httpcore==1.0.5
|
||||
httptools==0.6.1
|
||||
@ -29,6 +40,7 @@ idna==3.7
|
||||
importlib_metadata==8.5.0
|
||||
inquirerpy==0.3.4
|
||||
interegular==0.3.3
|
||||
itsdangerous==2.2.0
|
||||
Jinja2==3.1.4
|
||||
jiter==0.5.0
|
||||
jsonschema==4.23.0
|
||||
@ -36,6 +48,9 @@ jsonschema-specifications==2023.12.1
|
||||
lark==1.2.2
|
||||
llvmlite==0.43.0
|
||||
lm-format-enforcer==0.10.6
|
||||
lxml==5.3.0
|
||||
lxml_html_clean==0.2.2
|
||||
markdownify==0.13.1
|
||||
MarkupSafe==2.1.5
|
||||
mistral_common==1.4.3
|
||||
mpmath==1.3.0
|
||||
@ -60,6 +75,7 @@ nvidia-ml-py==12.560.30
|
||||
nvidia-nccl-cu12==2.20.5
|
||||
nvidia-nvjitlink-cu12==12.6.20
|
||||
nvidia-nvtx-cu12==12.1.105
|
||||
ollama==0.3.3
|
||||
openai==1.47.1
|
||||
outlines==0.0.46
|
||||
packaging==24.1
|
||||
@ -81,10 +97,13 @@ pydantic==2.9.2
|
||||
pydantic_core==2.23.4
|
||||
python-dateutil==2.9.0.post0
|
||||
python-dotenv==1.0.1
|
||||
python-engineio==4.9.1
|
||||
python-socketio==5.11.4
|
||||
pytz==2024.2
|
||||
PyYAML==6.0.2
|
||||
pyzmq==26.2.0
|
||||
ray==2.36.1
|
||||
readability-lxml==0.8.1
|
||||
referencing==0.35.1
|
||||
regex==2024.7.24
|
||||
requests==2.32.3
|
||||
@ -92,9 +111,12 @@ rpds-py==0.20.0
|
||||
safetensors==0.4.4
|
||||
sentencepiece==0.2.0
|
||||
setuptools==72.1.0
|
||||
simple-websocket==1.0.0
|
||||
six==1.16.0
|
||||
sniffio==1.3.1
|
||||
soupsieve==2.6
|
||||
starlette==0.38.6
|
||||
structlog==24.4.0
|
||||
sympy==1.13.2
|
||||
tiktoken==0.7.0
|
||||
tokenizers==0.19.1
|
||||
@ -113,6 +135,8 @@ vllm-flash-attn==2.6.1
|
||||
watchfiles==0.24.0
|
||||
wcwidth==0.2.13
|
||||
websockets==13.1
|
||||
Werkzeug==3.0.4
|
||||
wsproto==1.2.0
|
||||
xformers==0.0.27.post2
|
||||
xxhash==3.5.0
|
||||
yarl==1.12.0
|
||||
|
9
tools.py
9
tools.py
@ -77,11 +77,14 @@ class GetReadablePageContentsTool(Tool):
|
||||
|
||||
class CalculatorTool(Tool):
|
||||
def __init__(self):
|
||||
super().__init__("calculator", "Perform a calculation", {'type': 'object', 'properties': {'expression': {'type': 'string', 'description': 'The mathematical expression to evaluate, should be a python mathematical expression'}}}, "result:string")
|
||||
super().__init__("calculator", "Perform a calculation using python's eval function", {'type': 'object', 'properties': {'expression': {'type': 'string', 'description': 'The mathematical expression to evaluate, should be a python mathematical expression'}}}, "result:string")
|
||||
|
||||
def execute(self, arg: dict) -> str:
|
||||
p = PythonCodeTool()
|
||||
return p.execute({'code': arg['expression']})
|
||||
try:
|
||||
return str(eval(arg["expression"]))
|
||||
except Exception as e:
|
||||
return f"Error executing code: {str(e)}"
|
||||
|
||||
|
||||
class PythonCodeTool(Tool):
|
||||
def __init__(self):
|
||||
|
Loading…
Reference in New Issue
Block a user