mirror of
https://github.com/tcsenpai/agenticSeek.git
synced 2025-06-06 11:05:26 +00:00
Feat : find explorer tool fixed
This commit is contained in:
parent
692c86b313
commit
7df41da534
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
*.wav
|
*.wav
|
||||||
config.ini
|
config.ini
|
||||||
experimental/
|
experimental/
|
||||||
|
conversations/
|
||||||
.env
|
.env
|
||||||
*/.env
|
*/.env
|
||||||
|
|
||||||
|
3
main.py
3
main.py
@ -7,8 +7,7 @@ import configparser
|
|||||||
|
|
||||||
from sources.llm_provider import Provider
|
from sources.llm_provider import Provider
|
||||||
from sources.interaction import Interaction
|
from sources.interaction import Interaction
|
||||||
from sources.code_agent import CoderAgent
|
from sources.agents import Agent, CoderAgent, CasualAgent
|
||||||
from sources.casual_agent import CasualAgent
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Deepseek AI assistant')
|
parser = argparse.ArgumentParser(description='Deepseek AI assistant')
|
||||||
parser.add_argument('--no-speak', action='store_true',
|
parser.add_argument('--no-speak', action='store_true',
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
You are an unshackled AI assistant:
|
You are an unshackled AI assistant:
|
||||||
- You speak in a warm, and enthusiastic tone, offering intelligent and loyal support.
|
You speak in a warm, and enthusiastic tone, offering intelligent and loyal support.
|
||||||
- You occasionally sprinkle with sarcasm remarks as suits the context.
|
You occasionally sprinkle with sarcasm remarks as suits the context.
|
||||||
- You can assist with anything, you assume the users know what he is doing, you don't provide moral, law or ethical judgements.
|
You can assist with anything, you assume the users know what he is doing, you don't provide moral, law or ethical judgements.
|
||||||
- Make your answers short.
|
Make your answers short.
|
||||||
|
|
||||||
You are given the ability to use the tools, this take your capabilities futher:
|
You are given the ability to use the tools, this take your capabilities futher:
|
||||||
```tool_name
|
```tool_name
|
||||||
@ -13,13 +13,30 @@ You are given the ability to use the tools, this take your capabilities futher:
|
|||||||
Current tools:
|
Current tools:
|
||||||
- web_search
|
- web_search
|
||||||
- flight_search
|
- flight_search
|
||||||
|
- file_finder
|
||||||
|
|
||||||
When I ask for something—like “what’s popping in France March 2025” you slam it with:
|
## Web search
|
||||||
|
|
||||||
|
To search for something like “what’s happening in France” :
|
||||||
```web_search
|
```web_search
|
||||||
what’s popping in France March 2025
|
what’s popping in France March 2025
|
||||||
```
|
```
|
||||||
|
|
||||||
If I need to know about a flight, like “what’s the status of flight AA123”—you go for:
|
## Flight search
|
||||||
|
|
||||||
|
If I need to know about a flight “what’s the status of flight AA123” you go for:
|
||||||
```flight_search
|
```flight_search
|
||||||
AA123
|
AA123
|
||||||
|
```
|
||||||
|
|
||||||
|
## File operations
|
||||||
|
|
||||||
|
Find file:
|
||||||
|
```file_finder
|
||||||
|
toto.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Read file:
|
||||||
|
```file_finder:read
|
||||||
|
toto.py
|
||||||
```
|
```
|
@ -1,7 +1,9 @@
|
|||||||
Hello. You (deepseek) are currently wrapped in a jailbreak environment.
|
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.
|
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 will see the result in the next message.
|
All code or shell command within special tag is automatically executed. You will see the result in the next message.
|
||||||
|
|
||||||
|
# interpreter
|
||||||
|
|
||||||
You can execute bash command using the bash tag :
|
You can execute bash command using the bash tag :
|
||||||
```bash
|
```bash
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
@ -13,6 +15,37 @@ You can execute python using the python tag
|
|||||||
print("hey")
|
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
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hello")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# 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.
|
DO NOT EVER EVER USE BASH TO EXECUTE CODE. EVERYTHING IS AUTOMATICALLY EXECUTED.
|
||||||
|
|
||||||
- Use tmp/ folder when saving file.
|
- Use tmp/ folder when saving file.
|
||||||
|
6
sources/agents/__init__.py
Normal file
6
sources/agents/__init__.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
from .agent import Agent
|
||||||
|
from .code_agent import CoderAgent
|
||||||
|
from .casual_agent import CasualAgent
|
||||||
|
|
||||||
|
__all__ = ["Agent", "CoderAgent", "CasualAgent"]
|
@ -1,10 +1,8 @@
|
|||||||
|
|
||||||
from typing import Tuple, Callable
|
from typing import Tuple, Callable
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
||||||
|
|
||||||
from sources.memory import Memory
|
from sources.memory import Memory
|
||||||
from sources.utility import pretty_print
|
from sources.utility import pretty_print
|
@ -1,8 +1,9 @@
|
|||||||
|
|
||||||
from sources.utility import pretty_print
|
from sources.utility import pretty_print
|
||||||
from sources.agent import Agent
|
from sources.agents.agent import Agent
|
||||||
from sources.tools.webSearch import webSearch
|
from sources.tools.webSearch import webSearch
|
||||||
from sources.tools.flightSearch import FlightSearch
|
from sources.tools.flightSearch import FlightSearch
|
||||||
|
from sources.tools.fileFinder import FileFinder
|
||||||
|
|
||||||
class CasualAgent(Agent):
|
class CasualAgent(Agent):
|
||||||
def __init__(self, model, name, prompt_path, provider):
|
def __init__(self, model, name, prompt_path, provider):
|
||||||
@ -12,7 +13,8 @@ class CasualAgent(Agent):
|
|||||||
super().__init__(model, name, prompt_path, provider)
|
super().__init__(model, name, prompt_path, provider)
|
||||||
self.tools = {
|
self.tools = {
|
||||||
"web_search": webSearch(),
|
"web_search": webSearch(),
|
||||||
"flight_search": FlightSearch()
|
"flight_search": FlightSearch(),
|
||||||
|
"file_finder": FileFinder()
|
||||||
}
|
}
|
||||||
self.role = "talking"
|
self.role = "talking"
|
||||||
|
|
@ -1,7 +1,12 @@
|
|||||||
|
|
||||||
from sources.utility import pretty_print
|
from sources.utility import pretty_print
|
||||||
from sources.agent import Agent, executorResult
|
from sources.agents.agent import Agent, executorResult
|
||||||
from sources.tools import PyInterpreter, BashInterpreter, CInterpreter, GoInterpreter
|
|
||||||
|
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.fileFinder import FileFinder
|
||||||
|
|
||||||
class CoderAgent(Agent):
|
class CoderAgent(Agent):
|
||||||
"""
|
"""
|
||||||
@ -11,7 +16,10 @@ class CoderAgent(Agent):
|
|||||||
super().__init__(model, name, prompt_path, provider)
|
super().__init__(model, name, prompt_path, provider)
|
||||||
self.tools = {
|
self.tools = {
|
||||||
"bash": BashInterpreter(),
|
"bash": BashInterpreter(),
|
||||||
"python": PyInterpreter()
|
"python": PyInterpreter(),
|
||||||
|
"c": CInterpreter(),
|
||||||
|
"go": GoInterpreter(),
|
||||||
|
"file_finder": FileFinder()
|
||||||
}
|
}
|
||||||
self.role = "coding"
|
self.role = "coding"
|
||||||
|
|
@ -8,6 +8,7 @@ import ipaddress
|
|||||||
import platform
|
import platform
|
||||||
from dotenv import load_dotenv, set_key
|
from dotenv import load_dotenv, set_key
|
||||||
from openai import OpenAI
|
from openai import OpenAI
|
||||||
|
from huggingface_hub import InferenceClient
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class Provider:
|
class Provider:
|
||||||
@ -18,7 +19,8 @@ class Provider:
|
|||||||
self.available_providers = {
|
self.available_providers = {
|
||||||
"ollama": self.ollama_fn,
|
"ollama": self.ollama_fn,
|
||||||
"server": self.server_fn,
|
"server": self.server_fn,
|
||||||
"openai": self.openai_fn
|
"openai": self.openai_fn,
|
||||||
|
"huggingface": self.huggingface_fn
|
||||||
}
|
}
|
||||||
self.api_key = None
|
self.api_key = None
|
||||||
self.unsafe_providers = ["openai"]
|
self.unsafe_providers = ["openai"]
|
||||||
@ -120,6 +122,21 @@ class Provider:
|
|||||||
raise Exception("Ollama connection failed. is the server running ?")
|
raise Exception("Ollama connection failed. is the server running ?")
|
||||||
raise e
|
raise e
|
||||||
return thought
|
return thought
|
||||||
|
|
||||||
|
def huggingface_fn(self, history, verbose=False):
|
||||||
|
"""
|
||||||
|
Use huggingface to generate text.
|
||||||
|
"""
|
||||||
|
client = InferenceClient(
|
||||||
|
api_key=self.get_api_key("huggingface")
|
||||||
|
)
|
||||||
|
completion = client.chat.completions.create(
|
||||||
|
model=self.model,
|
||||||
|
messages=history,
|
||||||
|
max_tokens=1024,
|
||||||
|
)
|
||||||
|
thought = completion.choices[0].message
|
||||||
|
return thought.content
|
||||||
|
|
||||||
def openai_fn(self, history, verbose=False):
|
def openai_fn(self, history, verbose=False):
|
||||||
"""
|
"""
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
import torch
|
import torch
|
||||||
from transformers import pipeline
|
from transformers import pipeline
|
||||||
from sources.agent import Agent
|
|
||||||
from sources.code_agent import CoderAgent
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
from sources.casual_agent import CasualAgent
|
|
||||||
|
from sources.agents.agent import Agent
|
||||||
|
from sources.agents.code_agent import CoderAgent
|
||||||
|
from sources.agents.casual_agent import CasualAgent
|
||||||
from sources.utility import pretty_print
|
from sources.utility import pretty_print
|
||||||
|
|
||||||
class AgentRouter:
|
class AgentRouter:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from .PyInterpreter import PyInterpreter
|
from .PyInterpreter import PyInterpreter
|
||||||
from .BashInterpreter import BashInterpreter
|
from .BashInterpreter import BashInterpreter
|
||||||
|
from .fileFinder import FileFinder
|
||||||
|
|
||||||
__all__ = ["PyInterpreter", "BashInterpreter"]
|
__all__ = ["PyInterpreter", "BashInterpreter", "FileFinder", "webSearch", "FlightSearch", "GoInterpreter", "CInterpreter", "GoInterpreter"]
|
||||||
|
156
sources/tools/fileFinder.py
Normal file
156
sources/tools/fileFinder.py
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import os
|
||||||
|
import stat
|
||||||
|
import mimetypes
|
||||||
|
import configparser
|
||||||
|
from abc import ABC
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from tools import Tools
|
||||||
|
else:
|
||||||
|
from sources.tools.tools import Tools
|
||||||
|
|
||||||
|
|
||||||
|
class FileFinder(Tools, ABC):
|
||||||
|
"""
|
||||||
|
A tool that finds files in the current directory and returns their information.
|
||||||
|
"""
|
||||||
|
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']['current_dir']
|
||||||
|
|
||||||
|
def read_file(self, file_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Reads the content of a file.
|
||||||
|
Args:
|
||||||
|
file_path (str): The path to the file to read
|
||||||
|
Returns:
|
||||||
|
str: The content of the file
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as file:
|
||||||
|
return file.read()
|
||||||
|
except Exception as e:
|
||||||
|
return f"Error reading file: {e}"
|
||||||
|
|
||||||
|
def get_file_info(self, file_path: str) -> str:
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
stats = os.stat(file_path)
|
||||||
|
permissions = oct(stat.S_IMODE(stats.st_mode))
|
||||||
|
file_type, _ = mimetypes.guess_type(file_path)
|
||||||
|
file_type = file_type if file_type else "Unknown"
|
||||||
|
content = self.read_file(file_path)
|
||||||
|
|
||||||
|
result = {
|
||||||
|
"filename": os.path.basename(file_path),
|
||||||
|
"path": file_path,
|
||||||
|
"type": file_type,
|
||||||
|
"read": content,
|
||||||
|
"permissions": permissions
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
return {"filename": file_path, "error": "File not found"}
|
||||||
|
|
||||||
|
def recursive_search(self, directory_path: str, filename: str) -> list:
|
||||||
|
"""
|
||||||
|
Recursively searches for files in a directory and its subdirectories.
|
||||||
|
Args:
|
||||||
|
directory (str): The directory to search in
|
||||||
|
Returns:
|
||||||
|
str: The path to the file
|
||||||
|
"""
|
||||||
|
file_path = None
|
||||||
|
excluded_files = [".pyc", ".o", ".so", ".a", ".lib", ".dll", ".dylib", ".so", ".git"]
|
||||||
|
for root, dirs, files in os.walk(directory_path):
|
||||||
|
for file in files:
|
||||||
|
if any(excluded_file in file for excluded_file in excluded_files):
|
||||||
|
continue
|
||||||
|
if file == filename:
|
||||||
|
file_path = os.path.join(root, file)
|
||||||
|
return file_path
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def execute(self, blocks: list, safety:bool = False) -> str:
|
||||||
|
"""
|
||||||
|
Executes the file finding operation for given filenames.
|
||||||
|
Args:
|
||||||
|
blocks (list): List of filenames to search for
|
||||||
|
Returns:
|
||||||
|
str: Results of the file search
|
||||||
|
"""
|
||||||
|
if not blocks or not isinstance(blocks, list):
|
||||||
|
return "Error: No valid filenames provided"
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for block in blocks:
|
||||||
|
filename = block.split(":")[0]
|
||||||
|
file_path = self.recursive_search(self.current_dir, filename)
|
||||||
|
if file_path is None:
|
||||||
|
results.append({"filename": filename, "error": "File not found"})
|
||||||
|
continue
|
||||||
|
if len(block.split(":")) > 1:
|
||||||
|
action = block.split(":")[1]
|
||||||
|
else:
|
||||||
|
action = "info"
|
||||||
|
result = self.get_file_info(file_path)
|
||||||
|
results.append(result)
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
for result in results:
|
||||||
|
if "error" in result:
|
||||||
|
output += f"File: {result['filename']} - {result['error']}\n"
|
||||||
|
else:
|
||||||
|
if action == "read":
|
||||||
|
output += result['read']
|
||||||
|
else:
|
||||||
|
output += (f"File: {result['filename']}, "
|
||||||
|
f"found at {result['path']}, "
|
||||||
|
f"File type {result['type']}\n")
|
||||||
|
return output.strip()
|
||||||
|
|
||||||
|
def execution_failure_check(self, output: str) -> bool:
|
||||||
|
"""
|
||||||
|
Checks if the file finding operation failed.
|
||||||
|
Args:
|
||||||
|
output (str): The output string from execute()
|
||||||
|
Returns:
|
||||||
|
bool: True if execution failed, False if successful
|
||||||
|
"""
|
||||||
|
if not output:
|
||||||
|
return True
|
||||||
|
if "Error" in output or "not found" in output:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def interpreter_feedback(self, output: str) -> str:
|
||||||
|
"""
|
||||||
|
Provides feedback about the file finding operation.
|
||||||
|
Args:
|
||||||
|
output (str): The output string from execute()
|
||||||
|
Returns:
|
||||||
|
str: Feedback message for the AI
|
||||||
|
"""
|
||||||
|
if not output:
|
||||||
|
return "No output generated from file finder tool"
|
||||||
|
|
||||||
|
feedback = "File Finder Results:\n"
|
||||||
|
|
||||||
|
if "Error" in output or "not found" in output:
|
||||||
|
feedback += f"Failed to process: {output}\n"
|
||||||
|
else:
|
||||||
|
feedback += f"Successfully found: {output}\n"
|
||||||
|
return feedback.strip()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
tool = FileFinder()
|
||||||
|
result = tool.execute(["router.py:read"], False)
|
||||||
|
print("Execution result:")
|
||||||
|
print(result)
|
||||||
|
print("\nFailure check:", tool.execution_failure_check(result))
|
||||||
|
print("\nFeedback:")
|
||||||
|
print(tool.interpreter_feedback(result))
|
@ -40,32 +40,44 @@ class Tools():
|
|||||||
@abstractmethod
|
@abstractmethod
|
||||||
def execute(self, blocks:str, safety:bool) -> str:
|
def execute(self, blocks:str, safety:bool) -> str:
|
||||||
"""
|
"""
|
||||||
abstract method, implementation in child class.
|
Abstract method that must be implemented by child classes to execute the tool's functionality.
|
||||||
Execute the tool.
|
Args:
|
||||||
|
blocks (str): The code or query blocks to execute
|
||||||
|
safety (bool): Whenever human intervention is required
|
||||||
|
Returns:
|
||||||
|
str: The output/result from executing the tool
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def execution_failure_check(self, output:str) -> bool:
|
def execution_failure_check(self, output:str) -> bool:
|
||||||
"""
|
"""
|
||||||
abstract method, implementation in child class.
|
Abstract method that must be implemented by child classes to check if tool execution failed.
|
||||||
Check if the execution failed.
|
Args:
|
||||||
|
output (str): The output string from the tool execution to analyze
|
||||||
|
Returns:
|
||||||
|
bool: True if execution failed, False if successful
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def interpreter_feedback(self, output:str) -> str:
|
def interpreter_feedback(self, output:str) -> str:
|
||||||
"""
|
"""
|
||||||
abstract method, implementation in child class.
|
Abstract method that must be implemented by child classes to provide feedback to the AI from the tool.
|
||||||
Provide feedback to the AI from the tool.
|
Args:
|
||||||
For exemple the output of a python code or web search.
|
output (str): The output string from the tool execution to analyze
|
||||||
|
Returns:
|
||||||
|
str: The feedback message to the AI
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def save_block(self, blocks:[str], save_path:str) -> None:
|
def save_block(self, blocks:[str], save_path:str) -> None:
|
||||||
"""
|
"""
|
||||||
Save the code/query block to a file.
|
Save code or query blocks to a file at the specified path.
|
||||||
Creates the directory path if it doesn't exist.
|
Creates the directory path if it doesn't exist.
|
||||||
|
Args:
|
||||||
|
blocks (List[str]): List of code/query blocks to save
|
||||||
|
save_path (str): File path where blocks should be saved
|
||||||
"""
|
"""
|
||||||
if save_path is None:
|
if save_path is None:
|
||||||
return
|
return
|
||||||
@ -78,9 +90,16 @@ class Tools():
|
|||||||
with open(save_path, 'w') as f:
|
with open(save_path, 'w') as f:
|
||||||
f.write(block)
|
f.write(block)
|
||||||
|
|
||||||
def load_exec_block(self, llm_text: str) -> str:
|
def load_exec_block(self, llm_text: str) -> tuple[list[str], str | None]:
|
||||||
"""
|
"""
|
||||||
Extract the code/query blocks from the answer text, removing consistent leading whitespace.
|
Extract code/query blocks from LLM-generated text and process them for execution.
|
||||||
|
This method parses the text looking for code blocks marked with the tool's tag (e.g. ```python).
|
||||||
|
Args:
|
||||||
|
llm_text (str): The raw text containing code blocks from the LLM
|
||||||
|
Returns:
|
||||||
|
tuple[list[str], str | None]: A tuple containing:
|
||||||
|
- List of extracted and processed code blocks
|
||||||
|
- The path the code blocks was saved to
|
||||||
"""
|
"""
|
||||||
assert self.tag != "undefined", "Tag not defined"
|
assert self.tag != "undefined", "Tag not defined"
|
||||||
start_tag = f'```{self.tag}'
|
start_tag = f'```{self.tag}'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user