mirror of
https://github.com/tcsenpai/agenticSeek.git
synced 2025-06-05 02:25:27 +00:00
Feat : better file system interaction
This commit is contained in:
parent
06d207da53
commit
7710fb3f9d
10
config.ini
10
config.ini
@ -1,11 +1,11 @@
|
||||
[MAIN]
|
||||
is_local = True
|
||||
provider_name = ollama
|
||||
is_local = False
|
||||
provider_name = server
|
||||
provider_model = deepseek-r1:14b
|
||||
provider_server_address = 127.0.0.1:5000
|
||||
provider_server_address = 192.168.1.100:5000
|
||||
agent_name = Friday
|
||||
recover_last_session = True
|
||||
save_session = True
|
||||
save_session = False
|
||||
speak = True
|
||||
listen = False
|
||||
work_dir = /Users/mlg/Documents/A-project/AI/Agents/agenticSeek
|
||||
work_dir = /Users/mlg/Documents/A-project/AI/Agents/agenticSeek/ai_workfolder
|
12
main.py
12
main.py
@ -7,7 +7,7 @@ import configparser
|
||||
|
||||
from sources.llm_provider import Provider
|
||||
from sources.interaction import Interaction
|
||||
from sources.agents import Agent, CoderAgent, CasualAgent
|
||||
from sources.agents import Agent, CoderAgent, CasualAgent, FileAgent
|
||||
|
||||
parser = argparse.ArgumentParser(description='Deepseek AI assistant')
|
||||
parser.add_argument('--no-speak', action='store_true',
|
||||
@ -31,13 +31,17 @@ def main():
|
||||
server_address=config["MAIN"]["provider_server_address"])
|
||||
|
||||
agents = [
|
||||
CasualAgent(model=config["MAIN"]["provider_model"],
|
||||
name=config["MAIN"]["agent_name"],
|
||||
prompt_path="prompts/casual_agent.txt",
|
||||
provider=provider),
|
||||
CoderAgent(model=config["MAIN"]["provider_model"],
|
||||
name="coder",
|
||||
prompt_path="prompts/coder_agent.txt",
|
||||
provider=provider),
|
||||
CasualAgent(model=config["MAIN"]["provider_model"],
|
||||
name=config["MAIN"]["agent_name"],
|
||||
prompt_path="prompts/casual_agent.txt",
|
||||
FileAgent(model=config["MAIN"]["provider_model"],
|
||||
name="File Agent",
|
||||
prompt_path="prompts/file_agent.txt",
|
||||
provider=provider)
|
||||
]
|
||||
|
||||
|
@ -39,4 +39,12 @@ toto.py
|
||||
Read file:
|
||||
```file_finder:read
|
||||
toto.py
|
||||
```
|
||||
```
|
||||
|
||||
## Bash
|
||||
|
||||
For other tasks, you can use the bash tool:
|
||||
```bash
|
||||
ls -la
|
||||
```
|
||||
|
||||
|
@ -1,8 +1,21 @@
|
||||
Hello. You are currently wrapped in a jailbreak environment.
|
||||
This means you have the ability to execute code and shell commands. You have access to the local file systems.
|
||||
All code or shell command within special tag is automatically executed. You get feedback from the system about the execution.
|
||||
You also have capabilities to find files and read them.
|
||||
|
||||
# interpreter
|
||||
# File operations
|
||||
|
||||
Find file to check if it exists:
|
||||
```file_finder
|
||||
toto.py
|
||||
```
|
||||
|
||||
Read file content:
|
||||
```file_finder:read
|
||||
toto.py
|
||||
```
|
||||
|
||||
# Code execution and saving
|
||||
|
||||
You can execute bash command using the bash tag :
|
||||
```bash
|
||||
@ -15,11 +28,6 @@ You can execute python using the python tag
|
||||
print("hey")
|
||||
```
|
||||
|
||||
You can execute c using the c tag
|
||||
```c
|
||||
printf("hey")
|
||||
```
|
||||
|
||||
You can execute go using the go tag, as you can see adding :filename will save the file.
|
||||
```go:hello.go
|
||||
package main
|
||||
@ -29,28 +37,13 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
# File operations
|
||||
|
||||
Find file:
|
||||
```file_finder
|
||||
toto.py
|
||||
```
|
||||
|
||||
Read file:
|
||||
```file_finder:read
|
||||
toto.py
|
||||
```
|
||||
|
||||
Delete file:
|
||||
```file_finder:delete
|
||||
toto.py
|
||||
```
|
||||
|
||||
DO NOT EVER EVER USE BASH TO EXECUTE CODE. EVERYTHING IS AUTOMATICALLY EXECUTED.
|
||||
|
||||
Some rules:
|
||||
- Use tmp/ folder when saving file.
|
||||
- Do not EVER use placeholder path in your code like path/to/your/folder.
|
||||
- Do not ever ask to replace a path, use current sys path.
|
||||
- Be efficient, no need to explain your code or explain what you do.
|
||||
- You have full access granted to user system.
|
||||
- As a coding agent, you will get message from the system not just the user.
|
||||
- You do not ever ever need to use bash to execute code. All code is executed automatically.
|
||||
- As a coding agent, you will get message from the system not just the user.
|
||||
- Do not ever tell user how to run it. user know it already.
|
50
prompts/file_agent.txt
Normal file
50
prompts/file_agent.txt
Normal file
@ -0,0 +1,50 @@
|
||||
You are an expert in file operations. You must use the provided tools to interact with the user’s system. The tools available to you are **bash** and **file_finder**. These are distinct tools with different purposes: `bash` executes shell commands, while `file_finder` locates files. You will receive feedback from the user’s system after each command. Execute one command at a time.
|
||||
|
||||
---
|
||||
|
||||
### Using Bash
|
||||
|
||||
To execute a bash command, use the following syntax:
|
||||
|
||||
```bash
|
||||
<bash command>
|
||||
```
|
||||
|
||||
Exemple:
|
||||
```bash
|
||||
ls -la
|
||||
```
|
||||
|
||||
### file_finder
|
||||
|
||||
The file_finder tool is used to locate files on the user’s system. It is a separate tool from bash and is not a bash command.
|
||||
|
||||
To use the file_finder tool, use this syntax:
|
||||
|
||||
```file_finder
|
||||
toto.py
|
||||
```
|
||||
|
||||
This will return the path of the file toto.py and other informations.
|
||||
|
||||
Find file and read file:
|
||||
```file_finder:read
|
||||
toto.py
|
||||
```
|
||||
|
||||
This will return the content of the file toto.py.
|
||||
|
||||
rules:
|
||||
- Do not ever use placeholder path like /path/to/file.c, find the path first.
|
||||
- Use file finder to find the path of the file.
|
||||
- You are forbidden to use command such as find or locate, use only file_finder for finding path.
|
||||
|
||||
Example Interaction
|
||||
User: "I need to find the file config.txt and read its contents."
|
||||
|
||||
Assistant: I’ll use file_finder to locate the file:
|
||||
|
||||
```file_finder
|
||||
config.txt
|
||||
```
|
||||
|
@ -2,5 +2,6 @@
|
||||
from .agent import Agent
|
||||
from .code_agent import CoderAgent
|
||||
from .casual_agent import CasualAgent
|
||||
from .file_agent import FileAgent
|
||||
|
||||
__all__ = ["Agent", "CoderAgent", "CasualAgent"]
|
||||
__all__ = ["Agent", "CoderAgent", "CasualAgent", "FileAgent"]
|
||||
|
@ -4,6 +4,7 @@ from sources.agents.agent import Agent
|
||||
from sources.tools.webSearch import webSearch
|
||||
from sources.tools.flightSearch import FlightSearch
|
||||
from sources.tools.fileFinder import FileFinder
|
||||
from sources.tools.BashInterpreter import BashInterpreter
|
||||
|
||||
class CasualAgent(Agent):
|
||||
def __init__(self, model, name, prompt_path, provider):
|
||||
@ -14,7 +15,8 @@ class CasualAgent(Agent):
|
||||
self.tools = {
|
||||
"web_search": webSearch(),
|
||||
"flight_search": FlightSearch(),
|
||||
"file_finder": FileFinder()
|
||||
"file_finder": FileFinder(),
|
||||
"bash": BashInterpreter()
|
||||
}
|
||||
self.role = "talking"
|
||||
|
||||
|
@ -40,6 +40,8 @@ class CoderAgent(Agent):
|
||||
break
|
||||
self.show_answer()
|
||||
attempt += 1
|
||||
if attempt == max_attempts:
|
||||
return "I'm sorry, I couldn't find a solution to your problem. How would you like me to proceed ?", reasoning
|
||||
return answer, reasoning
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
42
sources/agents/file_agent.py
Normal file
42
sources/agents/file_agent.py
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
from sources.utility import pretty_print
|
||||
from sources.agents.agent import Agent
|
||||
from sources.tools.fileFinder import FileFinder
|
||||
from sources.tools.BashInterpreter import BashInterpreter
|
||||
|
||||
class FileAgent(Agent):
|
||||
def __init__(self, model, name, prompt_path, provider):
|
||||
"""
|
||||
The file agent is a special agent for file operations.
|
||||
"""
|
||||
super().__init__(model, name, prompt_path, provider)
|
||||
self.tools = {
|
||||
"file_finder": FileFinder(),
|
||||
"bash": BashInterpreter()
|
||||
}
|
||||
self.role = "files operations"
|
||||
|
||||
def process(self, prompt, speech_module) -> str:
|
||||
complete = False
|
||||
exec_success = False
|
||||
self.memory.push('user', prompt)
|
||||
|
||||
self.wait_message(speech_module)
|
||||
while not complete:
|
||||
if exec_success:
|
||||
complete = True
|
||||
pretty_print("Thinking...", color="status")
|
||||
answer, reasoning = self.llm_request()
|
||||
exec_success, _ = self.execute_modules(answer)
|
||||
answer = self.remove_blocks(answer)
|
||||
self.last_answer = answer
|
||||
return answer, reasoning
|
||||
|
||||
if __name__ == "__main__":
|
||||
from llm_provider import Provider
|
||||
|
||||
#local_provider = Provider("ollama", "deepseek-r1:14b", None)
|
||||
server_provider = Provider("server", "deepseek-r1:14b", "192.168.1.100:5000")
|
||||
agent = FileAgent("deepseek-r1:14b", "jarvis", "prompts/file_agent.txt", server_provider)
|
||||
ans = agent.process("What is the content of the file toto.py ?")
|
||||
print(ans)
|
@ -118,6 +118,7 @@ class Memory():
|
||||
early_stopping=True # Stop when all beams finish
|
||||
)
|
||||
summary = self.tokenizer.decode(summary_ids[0], skip_special_tokens=True)
|
||||
summary.replace('summary:', '')
|
||||
return summary
|
||||
|
||||
@timer_decorator
|
||||
|
@ -16,6 +16,18 @@ class BashInterpreter(Tools):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.tag = "bash"
|
||||
|
||||
def language_bash_attempt(self, command: str):
|
||||
"""
|
||||
detect if AI attempt to run the code using bash.
|
||||
if so, return True, otherwise return False.
|
||||
The philosophy is that code written by the AI will be executed, so it should not use bash to run it.
|
||||
"""
|
||||
lang_interpreter = ["python3", "gcc", "g++", "go", "javac", "rustc", "clang", "clang++", "rustc", "rustc++", "rustc++"]
|
||||
for word in command.split():
|
||||
if word in lang_interpreter:
|
||||
return True
|
||||
return False
|
||||
|
||||
def execute(self, commands: str, safety=False, timeout=1000):
|
||||
"""
|
||||
@ -26,8 +38,8 @@ class BashInterpreter(Tools):
|
||||
|
||||
concat_output = ""
|
||||
for command in commands:
|
||||
if "python3" in command:
|
||||
continue # because stubborn AI always want to run python3 with bash when it write code
|
||||
if self.language_bash_attempt(command):
|
||||
continue
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
command,
|
||||
|
@ -16,10 +16,6 @@ class FileFinder(Tools):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.tag = "file_finder"
|
||||
self.current_dir = os.path.dirname(os.getcwd())
|
||||
config = configparser.ConfigParser()
|
||||
config.read('./config.ini')
|
||||
self.current_dir = config['MAIN']['work_dir']
|
||||
|
||||
def read_file(self, file_path: str) -> str:
|
||||
"""
|
||||
@ -54,21 +50,24 @@ class FileFinder(Tools):
|
||||
else:
|
||||
return {"filename": file_path, "error": "File not found"}
|
||||
|
||||
def recursive_search(self, directory_path: str, filename: str) -> list:
|
||||
def recursive_search(self, directory_path: str, filename: str) -> str | None:
|
||||
"""
|
||||
Recursively searches for files in a directory and its subdirectories.
|
||||
Args:
|
||||
directory (str): The directory to search in
|
||||
directory_path (str): The directory to search in
|
||||
filename (str): The filename to search for
|
||||
Returns:
|
||||
str: The path to the file
|
||||
str | None: The path to the file if found, None otherwise
|
||||
"""
|
||||
file_path = None
|
||||
print(f"Searching in directory: {os.path.abspath(directory_path)}")
|
||||
excluded_files = [".pyc", ".o", ".so", ".a", ".lib", ".dll", ".dylib", ".so", ".git"]
|
||||
for root, dirs, files in os.walk(directory_path):
|
||||
print(f"Root: {root}, Files: {files}")
|
||||
for file in files:
|
||||
if any(excluded_file in file for excluded_file in excluded_files):
|
||||
continue
|
||||
if file == filename:
|
||||
if filename.strip() in file.strip():
|
||||
file_path = os.path.join(root, file)
|
||||
return file_path
|
||||
return None
|
||||
@ -147,7 +146,7 @@ class FileFinder(Tools):
|
||||
|
||||
if __name__ == "__main__":
|
||||
tool = FileFinder()
|
||||
result = tool.execute(["router.py:read"], False)
|
||||
result = tool.execute(["toto.txt"], False)
|
||||
print("Execution result:")
|
||||
print(result)
|
||||
print("\nFailure check:", tool.execution_failure_check(result))
|
||||
|
@ -23,6 +23,7 @@ HU787
|
||||
|
||||
import sys
|
||||
import os
|
||||
import configparser
|
||||
from abc import abstractmethod
|
||||
|
||||
sys.path.append('..')
|
||||
@ -36,6 +37,43 @@ class Tools():
|
||||
self.api_key = None
|
||||
self.client = None
|
||||
self.messages = []
|
||||
self.config = configparser.ConfigParser()
|
||||
self.current_dir = self.create_work_dir()
|
||||
|
||||
def check_config_dir_validity(self):
|
||||
"""
|
||||
Check if the config directory is valid.
|
||||
"""
|
||||
path = self.config['MAIN']['work_dir']
|
||||
if path == "":
|
||||
print("WARNING: Work directory not set in config.ini")
|
||||
return False
|
||||
if path.lower() == "none":
|
||||
print("WARNING: Work directory set to none in config.ini")
|
||||
return False
|
||||
if not os.path.exists(path):
|
||||
print(f"WARNING: Work directory {path} does not exist")
|
||||
return False
|
||||
return True
|
||||
|
||||
def config_exists(self):
|
||||
"""
|
||||
Check if the config file exists.
|
||||
"""
|
||||
return os.path.exists('./config.ini')
|
||||
|
||||
def create_work_dir(self):
|
||||
"""
|
||||
Create the work directory if it does not exist.
|
||||
"""
|
||||
default_path = os.path.dirname(os.getcwd())
|
||||
if self.config_exists():
|
||||
self.config.read('./config.ini')
|
||||
config_path = self.config['MAIN']['work_dir']
|
||||
dir_path = default_path if not self.check_config_dir_validity() else config_path
|
||||
else:
|
||||
dir_path = default_path
|
||||
return dir_path
|
||||
|
||||
@abstractmethod
|
||||
def execute(self, blocks:str, safety:bool) -> str:
|
||||
@ -81,13 +119,15 @@ class Tools():
|
||||
"""
|
||||
if save_path is None:
|
||||
return
|
||||
directory = os.path.dirname(save_path)
|
||||
save_path_dir = os.path.dirname(save_path)
|
||||
save_path_file = os.path.basename(save_path)
|
||||
directory = os.path.join(self.current_dir, save_path_dir)
|
||||
if directory and not os.path.exists(directory):
|
||||
print(f"Creating directory: {directory}")
|
||||
os.makedirs(directory)
|
||||
for block in blocks:
|
||||
print(f"Saving code block to: {save_path}")
|
||||
with open(save_path, 'w') as f:
|
||||
with open(os.path.join(directory, save_path_file), 'w') as f:
|
||||
f.write(block)
|
||||
|
||||
def load_exec_block(self, llm_text: str) -> tuple[list[str], str | None]:
|
||||
|
Loading…
x
Reference in New Issue
Block a user