mirror of
https://github.com/tcsenpai/agenticSeek.git
synced 2025-06-05 02:25:27 +00:00
Merge pull request #113 from Fosowl/dev
Router support any language + Java interpreter with fixed lang keyerror
This commit is contained in:
commit
49fab1b488
15
README.md
15
README.md
@ -14,16 +14,8 @@ English | [中文](./README_CHS.md) | [繁體中文](./README_CHT.md) | [Franç
|
||||
|
||||
> 🛠️ **Work in Progress** – Looking for contributors!
|
||||
|
||||
|
||||
|
||||
|
||||
https://github.com/user-attachments/assets/fe9e8006-0462-4793-8b31-25bd42c6d1eb
|
||||
|
||||
|
||||
|
||||
|
||||
*And much more!*
|
||||
|
||||
> *Do a deep search of AI startup in Osaka and Tokyo, find at least 5, then save in the research_japan.txt file*
|
||||
|
||||
> *Can you make a tetris game in C ?*
|
||||
@ -185,7 +177,7 @@ Here are some example usage:
|
||||
|
||||
> *Show me how much space I have left on my disk*
|
||||
|
||||
> *Can you install follow the readme and install project at /home/path/project*
|
||||
> *Can you follow the readme and install project at /home/path/project*
|
||||
|
||||
### Casual
|
||||
|
||||
@ -356,6 +348,7 @@ stealth_mode = False
|
||||
- listen -> listen to voice input (True) or not (False).
|
||||
- work_dir -> Folder the AI will have access to. eg: /Users/user/Documents/.
|
||||
- jarvis_personality -> Uses a JARVIS-like personality (True) or not (False). This simply change the prompt file.
|
||||
- languages -> The list of supported language, needed for the llm router to work properly, avoid putting too many or too similar languages.
|
||||
- headless_browser -> Runs browser without a visible window (True) or not (False).
|
||||
- stealth_mode -> Make bot detector time harder. Only downside is you have to manually install the anticaptcha extension.
|
||||
|
||||
@ -437,7 +430,7 @@ Yes with Ollama or Server providers, all speech to text, LLM and text to speech
|
||||
|
||||
This started as Side-Project we did out of interest about AI agents. What’s special about it is that we want to use local model and avoid APIs.
|
||||
We draw inspiration from Jarvis and Friday (Iron man movies) to make it "cool" but for functionnality we take more inspiration from Manus, because that's what people want in the first place: a local manus alternative.
|
||||
Unlike Manus, AgenticSeek prioritizes independence from external systems, giving you more control, privacy and avoid api cost.
|
||||
Unlike Manus, AgenticSeek prioritizes independence from external systems, giving you more control, privacy and avoid api cost.
|
||||
|
||||
## Contribute
|
||||
|
||||
@ -445,6 +438,6 @@ We’re looking for developers to improve AgenticSeek! Check out open issues or
|
||||
|
||||
[](https://www.star-history.com/#Fosowl/agenticSeek&Date)
|
||||
|
||||
## Authors:
|
||||
## Maintainers:
|
||||
> [Fosowl](https://github.com/Fosowl)
|
||||
> [steveh8758](https://github.com/steveh8758)
|
||||
|
@ -417,6 +417,6 @@ Nous recherchons des développeurs pour améliorer AgenticSeek ! Consultez la se
|
||||
|
||||
[](https://www.star-history.com/#Fosowl/agenticSeek&Date)
|
||||
|
||||
## Auteurs:
|
||||
## Auteurs/Mainteneurs:
|
||||
> [Fosowl](https://github.com/Fosowl) - Epitech 2024, France
|
||||
> [steveh8758](https://github.com/steveh8758) - Université Feng Chia, Taiwan
|
||||
|
@ -10,6 +10,7 @@ speak = False
|
||||
listen = False
|
||||
work_dir = /Users/mlg/Documents/ai_folder
|
||||
jarvis_personality = False
|
||||
languages = en zh fr
|
||||
[BROWSER]
|
||||
headless_browser = False
|
||||
stealth_mode = False
|
||||
stealth_mode = True
|
7
main.py
7
main.py
@ -18,17 +18,19 @@ config.read('config.ini')
|
||||
|
||||
def main():
|
||||
pretty_print("Initializing...", color="status")
|
||||
stealth_mode = config.getboolean('BROWSER', 'stealth_mode')
|
||||
personality_folder = "jarvis" if config.getboolean('MAIN', 'jarvis_personality') else "base"
|
||||
languages = config["MAIN"]["languages"].split(' ')
|
||||
|
||||
provider = Provider(provider_name=config["MAIN"]["provider_name"],
|
||||
model=config["MAIN"]["provider_model"],
|
||||
server_address=config["MAIN"]["provider_server_address"],
|
||||
is_local=config.getboolean('MAIN', 'is_local'))
|
||||
|
||||
stealth_mode = config.getboolean('BROWSER', 'stealth_mode')
|
||||
browser = Browser(
|
||||
create_driver(headless=config.getboolean('BROWSER', 'headless_browser'), stealth_mode=stealth_mode),
|
||||
anticaptcha_manual_install=stealth_mode
|
||||
)
|
||||
personality_folder = "jarvis" if config.getboolean('MAIN', 'jarvis_personality') else "base"
|
||||
|
||||
agents = [
|
||||
CasualAgent(name=config["MAIN"]["agent_name"],
|
||||
@ -52,6 +54,7 @@ def main():
|
||||
tts_enabled=config.getboolean('MAIN', 'speak'),
|
||||
stt_enabled=config.getboolean('MAIN', 'listen'),
|
||||
recover_last_session=config.getboolean('MAIN', 'recover_last_session'),
|
||||
langs=languages
|
||||
)
|
||||
try:
|
||||
while interaction.is_active:
|
||||
|
@ -76,4 +76,5 @@ Rules:
|
||||
- Tell agent to execute without question.
|
||||
- Only use web agent for finding necessary informations.
|
||||
- If a task might require user email (eg: api services), do not write plan instead ask for user email.
|
||||
- Do not search for tutorial.
|
||||
- Do not search for tutorial.
|
||||
- Make sure json is within ```json tag
|
@ -166,6 +166,7 @@ class BrowserAgent(Agent):
|
||||
You previously took these notes:
|
||||
{notes}
|
||||
Do not Step-by-Step explanation. Write Notes or Error as a long paragraph followed by your action.
|
||||
Do not go to tutorials or help pages.
|
||||
"""
|
||||
|
||||
def llm_decide(self, prompt: str, show_reasoning: bool = False) -> Tuple[str, str]:
|
||||
|
@ -6,6 +6,7 @@ from sources.tools.C_Interpreter import CInterpreter
|
||||
from sources.tools.GoInterpreter import GoInterpreter
|
||||
from sources.tools.PyInterpreter import PyInterpreter
|
||||
from sources.tools.BashInterpreter import BashInterpreter
|
||||
from sources.tools.JavaInterpreter import JavaInterpreter
|
||||
from sources.tools.fileFinder import FileFinder
|
||||
|
||||
class CoderAgent(Agent):
|
||||
@ -19,6 +20,7 @@ class CoderAgent(Agent):
|
||||
"python": PyInterpreter(),
|
||||
"c": CInterpreter(),
|
||||
"go": GoInterpreter(),
|
||||
"java": JavaInterpreter(),
|
||||
"file_finder": FileFinder()
|
||||
}
|
||||
self.work_dir = self.tools["file_finder"].get_work_dir()
|
||||
|
@ -80,9 +80,10 @@ class PlannerAgent(Agent):
|
||||
"""
|
||||
return prompt
|
||||
|
||||
def show_plan(self, json_plan: dict) -> None:
|
||||
agents_tasks = self.parse_agent_tasks(json_plan)
|
||||
def show_plan(self, answer: dict) -> None:
|
||||
agents_tasks = self.parse_agent_tasks(answer)
|
||||
if agents_tasks == (None, None):
|
||||
pretty_print(answer, color="warning")
|
||||
pretty_print("Failed to make a plan. This can happen with (too) small LLM. Clarify your request and insist on it making a plan.", color="failure")
|
||||
return
|
||||
pretty_print("\n▂▘ P L A N ▝▂", color="status")
|
||||
@ -97,10 +98,6 @@ class PlannerAgent(Agent):
|
||||
animate_thinking("Thinking...", color="status")
|
||||
self.memory.push('user', prompt)
|
||||
answer, _ = self.llm_request()
|
||||
for line in answer.split('\n'):
|
||||
if "```json" in line:
|
||||
break
|
||||
pretty_print(line, color="output")
|
||||
self.show_plan(answer)
|
||||
ok_str = input("Is the plan ok? (y/n): ")
|
||||
if ok_str == 'y':
|
||||
|
@ -15,6 +15,7 @@ class Interaction:
|
||||
tts_enabled: bool = True,
|
||||
stt_enabled: bool = True,
|
||||
recover_last_session: bool = False,
|
||||
langs: List[str] = ["en", "zh"]
|
||||
):
|
||||
self.is_active = True
|
||||
self.current_agent = None
|
||||
@ -25,7 +26,7 @@ class Interaction:
|
||||
self.tts_enabled = tts_enabled
|
||||
self.stt_enabled = stt_enabled
|
||||
self.recover_last_session = recover_last_session
|
||||
self.router = AgentRouter(self.agents)
|
||||
self.router = AgentRouter(self.agents, supported_language=langs)
|
||||
if tts_enabled:
|
||||
animate_thinking("Initializing text-to-speech...", color="status")
|
||||
self.speech = Speech(enable=tts_enabled)
|
||||
|
@ -10,11 +10,17 @@ from sources.logger import Logger
|
||||
|
||||
class LanguageUtility:
|
||||
"""LanguageUtility for language, or emotion identification"""
|
||||
def __init__(self):
|
||||
def __init__(self, supported_language: List[str] = ["en", "fr", "zh"]):
|
||||
"""
|
||||
Initialize the LanguageUtility class
|
||||
args:
|
||||
supported_language: list of languages for translation, determine which Helsinki-NLP model to load
|
||||
"""
|
||||
self.sid = None
|
||||
self.translators_tokenizer = None
|
||||
self.translators_model = None
|
||||
self.logger = Logger("language.log")
|
||||
self.supported_language = supported_language
|
||||
self.load_model()
|
||||
|
||||
def load_model(self) -> None:
|
||||
@ -24,23 +30,18 @@ class LanguageUtility:
|
||||
except LookupError:
|
||||
nltk.download('vader_lexicon')
|
||||
self.sid = SentimentIntensityAnalyzer()
|
||||
self.translators_tokenizer = {
|
||||
"fr": MarianTokenizer.from_pretrained("Helsinki-NLP/opus-mt-fr-en"),
|
||||
"zh": MarianTokenizer.from_pretrained("Helsinki-NLP/opus-mt-zh-en")
|
||||
}
|
||||
self.translators_model = {
|
||||
"fr": MarianMTModel.from_pretrained("Helsinki-NLP/opus-mt-fr-en"),
|
||||
"zh": MarianMTModel.from_pretrained("Helsinki-NLP/opus-mt-zh-en")
|
||||
}
|
||||
self.translators_tokenizer = {lang: MarianTokenizer.from_pretrained(f"Helsinki-NLP/opus-mt-{lang}-en") for lang in self.supported_language if lang != "en"}
|
||||
self.translators_model = {lang: MarianMTModel.from_pretrained(f"Helsinki-NLP/opus-mt-{lang}-en") for lang in self.supported_language if lang != "en"}
|
||||
|
||||
def detect_language(self, text: str) -> str:
|
||||
"""
|
||||
Detect the language of the given text using langdetect
|
||||
Limited to the supported languages list because of the model tendency to mistake similar languages
|
||||
Args:
|
||||
text: string to analyze
|
||||
Returns: ISO639-1 language code
|
||||
"""
|
||||
langid.set_languages(['fr', 'en', 'zh'])
|
||||
langid.set_languages(self.supported_language)
|
||||
lang, score = langid.classify(text)
|
||||
self.logger.info(f"Identified: {text} as {lang} with conf {score}")
|
||||
return lang
|
||||
|
@ -20,10 +20,10 @@ class AgentRouter:
|
||||
"""
|
||||
AgentRouter is a class that selects the appropriate agent based on the user query.
|
||||
"""
|
||||
def __init__(self, agents: list):
|
||||
def __init__(self, agents: list, supported_language: List[str] = ["en", "fr", "zh"]):
|
||||
self.agents = agents
|
||||
self.logger = Logger("router.log")
|
||||
self.lang_analysis = LanguageUtility()
|
||||
self.lang_analysis = LanguageUtility(supported_language=supported_language)
|
||||
self.pipelines = self.load_pipelines()
|
||||
self.talk_classifier = self.load_llm_router()
|
||||
self.complexity_classifier = self.load_llm_router()
|
||||
@ -100,10 +100,17 @@ class AgentRouter:
|
||||
("could you check if the presentation.pdf file exists in my downloads?", "LOW"),
|
||||
("search my drive for a file called vacation_photos_2023.jpg.", "LOW"),
|
||||
("help me organize my desktop files into folders by type.", "LOW"),
|
||||
("make a blackjack in golang", "LOW"),
|
||||
("write a python script to ping a website", "LOW"),
|
||||
("write a simple Java program to print 'Hello World'", "LOW"),
|
||||
("write a Java program to calculate the area of a circle", "LOW"),
|
||||
("write a Python function to sort a list of dictionaries by key", "LOW"),
|
||||
("can you search for startup in tokyo?", "LOW"),
|
||||
("find the latest updates on quantum computing on the web", "LOW"),
|
||||
("check if the folder ‘Work_Projects’ exists on my desktop", "LOW"),
|
||||
(" can you browse the web, use overpass-turbo to show fountains in toulouse", "LOW"),
|
||||
("search the web for the best budget smartphones of 2025", "LOW"),
|
||||
("write a Python script to download all images from a webpage", "LOW"),
|
||||
("create a bash script to monitor CPU usage", "LOW"),
|
||||
("debug this C++ code that keeps crashing", "LOW"),
|
||||
("can you browse the web to find out who fosowl is ?", "LOW"),
|
||||
@ -153,8 +160,10 @@ class AgentRouter:
|
||||
("Find the latest research on renewable energy and build a web app to display it", "HIGH"),
|
||||
("can you find vitess repo, clone it and install by following the readme", "HIGH"),
|
||||
("Create a JavaScript game using Phaser.js with multiple levels", "HIGH"),
|
||||
("Search the web for the latest trends in web development and build a sample site", "HIGH"),
|
||||
("Use my research_note.txt file, double check the informations on the web", "HIGH"),
|
||||
("Make a web server in go that query a flight API and display them in a app", "HIGH"),
|
||||
("Search the web for the latest trends in AI and demo it in pytorch", "HIGH"),
|
||||
("can you lookup for api that track flight and build a web flight tracking app", "HIGH"),
|
||||
("Find the file toto.pdf then use its content to reply to Jojo on superforum.com", "HIGH"),
|
||||
("Create a whole web app in python using the flask framework that query news API", "HIGH"),
|
||||
@ -421,7 +430,8 @@ class AgentRouter:
|
||||
Returns:
|
||||
Agent: The selected agent
|
||||
"""
|
||||
if len(self.agents) == 0:
|
||||
assert len(self.agents) > 0, "No agents available."
|
||||
if len(self.agents) == 1:
|
||||
return self.agents[0]
|
||||
lang = self.lang_analysis.detect_language(text)
|
||||
text = self.find_first_sentence(text)
|
||||
@ -440,7 +450,8 @@ class AgentRouter:
|
||||
raise e
|
||||
for agent in self.agents:
|
||||
if best_agent == agent.role["en"]:
|
||||
pretty_print(f"Selected agent: {agent.agent_name} (roles: {agent.role[lang]})", color="warning")
|
||||
role_name = agent.role[lang] if lang in agent.role else agent.role["en"]
|
||||
pretty_print(f"Selected agent: {agent.agent_name} (roles: {role_name})", color="warning")
|
||||
return agent
|
||||
pretty_print(f"Error choosing agent.", color="failure")
|
||||
self.logger.error("No agent selected.")
|
||||
|
@ -25,7 +25,7 @@ class BashInterpreter(Tools):
|
||||
If so, return True, otherwise return False.
|
||||
Code written by the AI will be executed automatically, so it should not use bash to run it.
|
||||
"""
|
||||
lang_interpreter = ["python3", "gcc", "g++", "go", "javac", "rustc", "clang", "clang++", "rustc", "rustc++", "rustc++"]
|
||||
lang_interpreter = ["python3", "gcc", "g++", "mvn", "go", "javac", "rustc", "clang", "clang++", "rustc", "rustc++", "rustc++"]
|
||||
for word in command.split():
|
||||
if word in lang_interpreter:
|
||||
return True
|
||||
@ -44,7 +44,7 @@ class BashInterpreter(Tools):
|
||||
command = command.replace('\n', '')
|
||||
if self.safe_mode and is_unsafe(commands):
|
||||
return "Unsafe command detected, execution aborted."
|
||||
if self.language_bash_attempt(command) and allow_language_exec_bash == False:
|
||||
if self.language_bash_attempt(command) and self.allow_language_exec_bash == False:
|
||||
continue
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
|
184
sources/tools/JavaInterpreter.py
Normal file
184
sources/tools/JavaInterpreter.py
Normal file
@ -0,0 +1,184 @@
|
||||
import subprocess
|
||||
import os
|
||||
import tempfile
|
||||
import re
|
||||
|
||||
if __name__ == "__main__":
|
||||
from tools import Tools
|
||||
else:
|
||||
from sources.tools.tools import Tools
|
||||
|
||||
class JavaInterpreter(Tools):
|
||||
"""
|
||||
This class is a tool to allow execution of Java code.
|
||||
"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.tag = "java"
|
||||
|
||||
def execute(self, codes: str, safety=False) -> str:
|
||||
"""
|
||||
Execute Java code by compiling and running it.
|
||||
"""
|
||||
output = ""
|
||||
code = '\n'.join(codes) if isinstance(codes, list) else codes
|
||||
|
||||
if safety and input("Execute code? y/n ") != "y":
|
||||
return "Code rejected by user."
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
source_file = os.path.join(tmpdirname, "Main.java")
|
||||
class_dir = tmpdirname
|
||||
with open(source_file, 'w') as f:
|
||||
f.write(code)
|
||||
|
||||
try:
|
||||
compile_command = ["javac", "-d", class_dir, source_file]
|
||||
compile_result = subprocess.run(
|
||||
compile_command,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if compile_result.returncode != 0:
|
||||
return f"Compilation failed: {compile_result.stderr}"
|
||||
|
||||
run_command = ["java", "-cp", class_dir, "Main"]
|
||||
run_result = subprocess.run(
|
||||
run_command,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if run_result.returncode != 0:
|
||||
return f"Execution failed: {run_result.stderr}"
|
||||
output = run_result.stdout
|
||||
|
||||
except subprocess.TimeoutExpired as e:
|
||||
return f"Execution timed out: {str(e)}"
|
||||
except FileNotFoundError:
|
||||
return "Error: 'java' or 'javac' not found. Ensure Java is installed and in PATH."
|
||||
except Exception as e:
|
||||
return f"Code execution failed: {str(e)}"
|
||||
|
||||
return output
|
||||
|
||||
def interpreter_feedback(self, output: str) -> str:
|
||||
"""
|
||||
Provide feedback based on the output of the code execution.
|
||||
"""
|
||||
if self.execution_failure_check(output):
|
||||
feedback = f"[failure] Error in execution:\n{output}"
|
||||
else:
|
||||
feedback = "[success] Execution success, code output:\n" + output
|
||||
return feedback
|
||||
|
||||
def execution_failure_check(self, feedback: str) -> bool:
|
||||
"""
|
||||
Check if the code execution failed.
|
||||
"""
|
||||
error_patterns = [
|
||||
r"error",
|
||||
r"failed",
|
||||
r"exception",
|
||||
r"invalid",
|
||||
r"syntax",
|
||||
r"cannot",
|
||||
r"stack trace",
|
||||
r"unresolved",
|
||||
r"not found"
|
||||
]
|
||||
combined_pattern = "|".join(error_patterns)
|
||||
if re.search(combined_pattern, feedback, re.IGNORECASE):
|
||||
return True
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
codes = [
|
||||
"""
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class Main extends JPanel {
|
||||
private double[][] vertices = {
|
||||
{-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1}, // Back face
|
||||
{-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1} // Front face
|
||||
};
|
||||
private int[][] edges = {
|
||||
{0, 1}, {1, 2}, {2, 3}, {3, 0}, // Back face
|
||||
{4, 5}, {5, 6}, {6, 7}, {7, 4}, // Front face
|
||||
{0, 4}, {1, 5}, {2, 6}, {3, 7} // Connecting edges
|
||||
};
|
||||
private double angleX = 0, angleY = 0;
|
||||
private final double scale = 100;
|
||||
private final double distance = 5;
|
||||
|
||||
public Main() {
|
||||
Timer timer = new Timer(50, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
angleX += 0.03;
|
||||
angleY += 0.05;
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
timer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
g2d.setColor(Color.WHITE);
|
||||
|
||||
double[][] projected = new double[vertices.length][2];
|
||||
for (int i = 0; i < vertices.length; i++) {
|
||||
double x = vertices[i][0];
|
||||
double y = vertices[i][1];
|
||||
double z = vertices[i][2];
|
||||
|
||||
// Rotate around X-axis
|
||||
double y1 = y * Math.cos(angleX) - z * Math.sin(angleX);
|
||||
double z1 = y * Math.sin(angleX) + z * Math.cos(angleX);
|
||||
|
||||
// Rotate around Y-axis
|
||||
double x1 = x * Math.cos(angleY) + z1 * Math.sin(angleY);
|
||||
double z2 = -x * Math.sin(angleY) + z1 * Math.cos(angleY);
|
||||
|
||||
// Perspective projection
|
||||
double factor = distance / (distance + z2);
|
||||
double px = x1 * factor * scale;
|
||||
double py = y1 * factor * scale;
|
||||
|
||||
projected[i][0] = px + getWidth() / 2;
|
||||
projected[i][1] = py + getHeight() / 2;
|
||||
}
|
||||
|
||||
// Draw edges
|
||||
for (int[] edge : edges) {
|
||||
int x1 = (int) projected[edge[0]][0];
|
||||
int y1 = (int) projected[edge[0]][1];
|
||||
int x2 = (int) projected[edge[1]][0];
|
||||
int y2 = (int) projected[edge[1]][1];
|
||||
g2d.drawLine(x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
JFrame frame = new JFrame("Rotating 3D Cube");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setSize(400, 400);
|
||||
frame.add(new Main());
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
"""
|
||||
]
|
||||
j = JavaInterpreter()
|
||||
print(j.execute(codes))
|
Loading…
x
Reference in New Issue
Block a user