From a7b292f43793aae23f21ad2287de24884c4d5908 Mon Sep 17 00:00:00 2001 From: Ismael Sampaio Date: Wed, 19 Mar 2025 21:57:08 -0300 Subject: [PATCH] feat: - Initial agent development, starting by PDF fix: - Fixed test discovery on subdirectories test: - Started tests for PDF agent --- .vscode/settings.json | 5 +- __init__.py | 0 src/__init__.py | 1 - src/interfaces/agents/agent.py | 53 ++++++++++++++++++++++ src/main.py | 21 +++++++-- src/modules/pdf/pdfAgent.py | 8 +++- src/modules/pdf/tools/metadata.pdf.tool.py | 9 ++-- src/service/__init__.py | 0 src/service/ollama/__init__.py | 0 test/agent/__init__.py | 0 test/agent/test_pdfAgent.py | 20 ++++++++ test/test_ollamaModelManager.py | 9 ++-- 12 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 __init__.py create mode 100644 src/service/__init__.py create mode 100644 src/service/ollama/__init__.py create mode 100644 test/agent/__init__.py create mode 100644 test/agent/test_pdfAgent.py diff --git a/.vscode/settings.json b/.vscode/settings.json index 519a8e7..5f42843 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,8 @@ "test_*.py" ], "python.testing.pytestEnabled": false, - "python.testing.unittestEnabled": true + "python.testing.unittestEnabled": true, + "python.analysis.extraPaths": [ + "./src/service" + ] } \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/__init__.py b/src/__init__.py index f50bf19..e69de29 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1 +0,0 @@ -# Este arquivo transforma o diretório em um pacote Python diff --git a/src/interfaces/agents/agent.py b/src/interfaces/agents/agent.py index 138528c..ffe6e39 100644 --- a/src/interfaces/agents/agent.py +++ b/src/interfaces/agents/agent.py @@ -1,7 +1,46 @@ from abc import ABC, abstractmethod +from json import tool from typing import List, Dict, Any +from langchain.tools import BaseTool +from sqlalchemy import desc + + class Agent(ABC): + name: str + description: str + tools: List[BaseTool] + + @abstractmethod + def list_tools(self) -> List[BaseTool]: + """ + List all available tools. + + Returns: + List[BaseTool]: A list of tools available for the agent. + """ + return self.tools + + @abstractmethod + def add_tool(self, tool: BaseTool) -> None: + """ + Adds a new tool to the agent's toolset. + + Args: + tool (BaseTool): LangChain tool to be added + """ + pass + + @abstractmethod + def remove_tool(self, tool_name: str) -> None: + """ + Removes a tool from the agent's toolset. + + Args: + tool_name (str): Name of the tool to be removed + """ + pass + @abstractmethod def get_agent_tools(self) -> List[Dict[str, Any]]: """ @@ -20,4 +59,18 @@ class Agent(ABC): Returns: Dict[str, Any]: A dictionary containing agent details. """ + pass + + @abstractmethod + def create_agent(self, agent_name: str, agent_description: str) -> Dict[str, Any]: + """ + Create a new agent. + + Args: + agent_name (str): The name of the agent. + agent_description (str): The description of the agent. + + Returns: + Dict[str, Any]: A dictionary containing the created agent's details. + """ pass \ No newline at end of file diff --git a/src/main.py b/src/main.py index dee9893..b59b856 100644 --- a/src/main.py +++ b/src/main.py @@ -1,9 +1,20 @@ -from service.ollama.ollamaModelManager import OllamaModelManager # Utilizando nossa classe para obter os modelos -ollama_manager = OllamaModelManager() -models = ollama_manager.get_available_models() +import sys +import os + +# Adiciona o diretório raiz ao path +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + +from src.service.ollama.ollamaModelManager import OllamaModelManager + + +# ollama_manager = OllamaModelManager() +# models = ollama_manager.get_available_models() # print(models) -details = ollama_manager.get_model_details("qwen2.5:1.5b") -print(details) \ No newline at end of file + + + +# details = ollama_manager.get_model_details("qwen2.5:1.5b") +# print(details) \ No newline at end of file diff --git a/src/modules/pdf/pdfAgent.py b/src/modules/pdf/pdfAgent.py index 8ca5738..95748ed 100644 --- a/src/modules/pdf/pdfAgent.py +++ b/src/modules/pdf/pdfAgent.py @@ -8,6 +8,10 @@ from src.interfaces.agents.agent import Agent class PDFAgent(Agent): + # Class properties + name = "PDF Agent" + description = "Agent to handle PDF operations" + tools = [] def __init__(self): """ @@ -18,10 +22,10 @@ class PDFAgent(Agent): Attributes: agent: The agent implementation for PDF operations. """ + self.agent = None + self.tools = [] - self.agent - def get_agent_details(self): return super().get_agent_details() diff --git a/src/modules/pdf/tools/metadata.pdf.tool.py b/src/modules/pdf/tools/metadata.pdf.tool.py index 8d82110..93d77a6 100644 --- a/src/modules/pdf/tools/metadata.pdf.tool.py +++ b/src/modules/pdf/tools/metadata.pdf.tool.py @@ -1,5 +1,5 @@ import fitz -from langchain_community.tools import BaseTool +from langchain.tools import BaseTool class PDFMetadataTool(BaseTool): name="pdf_metadata" @@ -11,5 +11,8 @@ class PDFMetadataTool(BaseTool): metadata = { "páginas": len(doc) } - except Exception as e: - return f"Error: {e}" \ No newline at end of file + metadata.update(doc.metadata) + return metadata + except FileNotFoundError: + return f"Error: File {path} not found." + \ No newline at end of file diff --git a/src/service/__init__.py b/src/service/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/service/ollama/__init__.py b/src/service/ollama/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/agent/__init__.py b/test/agent/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/agent/test_pdfAgent.py b/test/agent/test_pdfAgent.py new file mode 100644 index 0000000..d82d028 --- /dev/null +++ b/test/agent/test_pdfAgent.py @@ -0,0 +1,20 @@ +from math import e +import unittest + +from src.interfaces.agents.agent import Agent +from src.modules.pdf.pdfAgent import PDFAgent + +class TestPDFAgent(unittest.TestCase): + def setUp(self): + self.agent: Agent + return super().setUp() + + + def createAgent(self): + self.agent = PDFAgent() + self.agent.createAgent() + self.assertIsNone(self.agent) + self.assertEqual(self.agent.name, "PDF Agent") + self.assertEqual(self.agent.description, "Agent to handle PDF operations") + + self.assertIsInstance(self.agent.tools, list) diff --git a/test/test_ollamaModelManager.py b/test/test_ollamaModelManager.py index 055ed35..562f7e5 100644 --- a/test/test_ollamaModelManager.py +++ b/test/test_ollamaModelManager.py @@ -3,13 +3,14 @@ from unittest.mock import patch, MagicMock from src.service.ollama.ollamaModelManager import OllamaModelManager + class TestOllamaModelManager(unittest.TestCase): def setUp(self): self.model_manager = OllamaModelManager() self.model_manager.base_url = "http://test-url:11434" - @patch('service.ollama.ollamaModelManager.requests.get') + @patch('src.service.ollama.ollamaModelManager.requests.get') def test_get_available_models_success(self, mock_get): # Setup mock response mock_response = MagicMock() @@ -29,7 +30,7 @@ class TestOllamaModelManager(unittest.TestCase): self.assertEqual(len(result), 2) self.assertEqual(result, [{'name': 'model1'}, {'name': 'model2'}]) - @patch('service.ollama.ollamaModelManager.requests.get') + @patch('src.service.ollama.ollamaModelManager.requests.get') def test_get_available_models_exception(self, mock_get): # Setup mock to raise exception mock_get.side_effect = Exception("Connection error") @@ -40,7 +41,7 @@ class TestOllamaModelManager(unittest.TestCase): # Assertions self.assertEqual(result, []) - @patch('service.ollama.ollamaModelManager.requests.post') + @patch('src.service.ollama.ollamaModelManager.requests.post') def test_get_model_details_success(self, mock_post): # Setup mock response mock_response = MagicMock() @@ -63,7 +64,7 @@ class TestOllamaModelManager(unittest.TestCase): self.assertEqual(result['context_size'], 4096) self.assertEqual(result['license'], 'Apache 2.0') - @patch('service.ollama.ollamaModelManager.requests.post') + @patch('src.service.ollama.ollamaModelManager.requests.post') def test_get_model_details_exception(self, mock_post): # Setup mock to raise exception mock_post.side_effect = Exception("API error")