Initial project setup

This commit is contained in:
martin legrand
2025-04-01 18:49:37 +02:00
parent 698ed78acc
commit 56b5db7df3
13 changed files with 211 additions and 38 deletions
+3 -1
View File
@@ -133,6 +133,8 @@ class Agent():
Show the answer in a pretty way.
Show code blocks and their respective feedback by inserting them in the ressponse.
"""
if self.last_answer is None:
return
lines = self.last_answer.split("\n")
for line in lines:
if "block:" in line:
@@ -190,5 +192,5 @@ class Agent():
self.memory.push('user', feedback)
if save_path != None:
tool.save_block(blocks, save_path)
self.blocks_result = list(reversed(self.blocks_result))
self.blocks_result = self.blocks_result
return True, feedback
+6 -5
View File
@@ -93,7 +93,7 @@ class BrowserAgent(Agent):
Your task:
1. Decide if the current page answers the users query: {user_prompt}
- If it does, take notes of the useful information, write down source, link or reference, then move to a new page.
- If it does and you completed use request, say REQUEST_EXIT
- If it does and you completed user request, say REQUEST_EXIT
- If it doesnt, say: Error: This page does not answer the users query then go back or navigate to another link.
2. Navigate by either:
- Navigate to a navigation links (write the full URL, e.g., www.example.com/cats).
@@ -144,10 +144,10 @@ class BrowserAgent(Agent):
animate_thinking("Thinking...", color="status")
self.memory.push('user', prompt)
answer, reasoning = self.llm_request()
output = f"Answer: {answer}" if len(answer) > 16 else f"Action: {answer}\nReasoning: {reasoning}"
pretty_print("-"*100)
output = answer if len(answer) > 16 else f"Action: {answer}\nReasoning: {reasoning}"
print()
pretty_print(output, color="output")
pretty_print("-"*100)
print()
return answer, reasoning
def select_unvisited(self, search_result: List[str]) -> List[str]:
@@ -235,7 +235,8 @@ class BrowserAgent(Agent):
def show_search_results(self, search_result: List[str]):
pretty_print("\nSearch results:", color="output")
for res in search_result:
pretty_print(f"Title: {res['title']} - Link: {res['link']}", color="output")
pretty_print(f"Title: {res['title']} - ", color="info", no_newline=True)
pretty_print(f"Link: {res['link']}", color="status")
def process(self, user_prompt: str, speech_module: type) -> Tuple[str, str]:
"""
+142
View File
@@ -0,0 +1,142 @@
import json
from typing import List, Tuple, Type, Dict, Tuple
from sources.utility import pretty_print, animate_thinking
from sources.agents.agent import Agent
from sources.agents.code_agent import CoderAgent
from sources.agents.file_agent import FileAgent
from sources.agents.browser_agent import BrowserAgent
from sources.tools.tools import Tools
class PlannerAgent(Agent):
def __init__(self, name, prompt_path, provider, verbose=False, browser=None):
"""
The planner agent is a special agent that divides and conquers the task.
"""
super().__init__(name, prompt_path, provider, verbose, None)
self.tools = {
"json": Tools()
}
self.tools['json'].tag = "json"
self.browser = browser
self.agents = {
"coder": CoderAgent(name, "prompts/base/coder_agent.txt", provider, verbose=False),
"file": FileAgent(name, "prompts/base/file_agent.txt", provider, verbose=False),
"web": BrowserAgent(name, "prompts/base/browser_agent.txt", provider, verbose=False, browser=browser)
}
self.role = {
"en": "Research, setup and code",
"fr": "Recherche, configuration et codage",
"zh": "研究,设置和编码",
}
self.type = "planner_agent"
def parse_agent_tasks(self, text: str) -> Tuple[list | None, list | None]:
"""
Parse the agent tasks from the given text into json.
"""
tasks = []
tasks_names = []
lines = text.strip().split('\n')
for line in lines:
if line is None or len(line) == 0:
continue
line = line.strip()
if '##' in line or line[0].isdigit():
tasks_names.append(line)
continue
blocks, _ = self.tools["json"].load_exec_block(text)
if blocks == None:
return (None, None)
for block in blocks:
line_json = json.loads(block)
if 'plan' in line_json:
for task in line_json['plan']:
agent = {
'agent': task['agent'],
'id': task['id'],
'task': task['task']
}
if 'need' in task:
agent['need'] = task['need']
tasks.append(agent)
if len(tasks_names) != len(tasks):
names = [task['task'] for task in tasks]
return zip(names, tasks)
return zip(tasks_names, tasks)
def make_prompt(self, task: str, needed_infos: str) -> str:
"""
Make a prompt for the agent.
"""
if needed_infos is None:
needed_infos = "No needed informations."
prompt = f"""
You are given the following informations:
{needed_infos}
Your task is:
{task}
"""
return prompt
def show_plan(self, agents_tasks):
if agents_tasks == (None, None):
return
pretty_print("▂▘ P L A N ▝▂", color="output")
for task_name, task in agents_tasks:
pretty_print(f"{task['agent']} -> {task['task']}", color="info")
pretty_print("▔▗ E N D ▖▔", color="output")
def process(self, prompt: str, speech_module: type) -> str:
"""
Process the prompt and divide the task between the agents.
Args:
prompt (str): The prompt to process.
speech_module (type): The speech module to use.
Returns:
str: The final answer resulting from successive task.
"""
ok = False
agents_tasks = (None, None)
while not ok:
self.wait_message(speech_module)
animate_thinking("Thinking...", color="status")
self.memory.push('user', prompt)
answer, _ = self.llm_request()
pretty_print(answer.split('\n')[0], color="output")
agents_tasks = self.parse_agent_tasks(answer)
if agents_tasks == (None, None):
pretty_print("Failed to parse the tasks, retrying", color="failure")
prompt = "Task parsing failed. Please retry with proper json."
continue
self.show_plan(agents_tasks)
ok_str = input("Is the plan ok? (y/n): ")
if ok_str == 'y':
ok = True
else:
prompt = input("Please reformulate: ")
if agents_tasks == (None, None):
return "Failed to parse the tasks", reasoning
prev_agent_answer = None
for task_name, task in agents_tasks:
pretty_print(f"I will {task_name}.", color="info")
agent_prompt = self.make_prompt(task['task'], prev_agent_answer)
pretty_print(f"Assigned agent {task['agent']} to {task_name}", color="info")
if speech_module: speech_module.speak(f"I will {task_name}. I assigned the {task['agent']} agent to the task.")
try:
prev_agent_answer, _ = self.agents[task['agent'].lower()].process(agent_prompt, speech_module)
pretty_print(f"-- Agent answer ---\n\n", color="output")
self.agents[task['agent'].lower()].show_answer()
pretty_print(f"\n\n", color="output")
except Exception as e:
raise e
self.last_answer = prev_agent_answer
return prev_agent_answer, ""
if __name__ == "__main__":
from llm_provider import Provider
server_provider = Provider("server", "deepseek-r1:14b", "192.168.1.100:5000")
agent = PlannerAgent("deepseek-r1:14b", "jarvis", "prompts/planner_agent.txt", server_provider)
ans = agent.process("Do a deep search of AI startup in Osaka and Tokyo, find at least 5, then save in the research_japan.txt file")
+3 -3
View File
@@ -76,10 +76,10 @@ class PlannerAgent(Agent):
agents_tasks = self.parse_agent_tasks(json_plan)
if agents_tasks == (None, None):
return
pretty_print(f"--- Plan ---", color="output")
pretty_print("▂▘ P L A N ▝▂", color="output")
for task_name, task in agents_tasks:
pretty_print(f"{task}", color="output")
pretty_print(f"--- End of Plan ---", color="output")
pretty_print(f"{task['agent']} -> {task['task']}", color="info")
pretty_print("▔▗ E N D ▖▔", color="output")
def process(self, prompt, speech_module) -> str:
ok = False