diff --git a/examples/scientific_writing/cajal_integration_example.py b/examples/scientific_writing/cajal_integration_example.py deleted file mode 100644 index 82817c196..000000000 --- a/examples/scientific_writing/cajal_integration_example.py +++ /dev/null @@ -1,205 +0,0 @@ -""" -CAJAL Scientific Writer Agent Example - -This example demonstrates how to use the ScientificWriterAgent with CAJAL model -for generating academic papers in LaTeX format. - -CAJAL is a specialized 2GB local model for scientific paper generation, -part of the P2PCLAW decentralized research network. - -Example Usage: - python cajal_integration_example.py -""" - -import sys -import os - -# Add the src directory to Python path for examples -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src', 'praisonai-agents')) - -from praisonaiagents import ScientificWriterAgent, Agent, AgentTeam, Task - -def basic_scientific_writing_example(): - """Basic example of using ScientificWriterAgent with CAJAL.""" - - print("=== Basic Scientific Writing Example ===") - - # Create a scientific writer agent using CAJAL model - scientific_writer = ScientificWriterAgent( - name="Research Paper Writer", - model="Agnuxo/CAJAL-4B-P2PCLAW", # HuggingFace model path - instructions="You are a specialized scientific paper writer trained on academic literature." - ) - - # Generate a scientific paper - topic = "Climate Change Effects on Coral Reef Ecosystems" - print(f"Generating scientific paper on: {topic}") - - paper = scientific_writer.write_paper( - topic=topic, - sections=["Introduction", "Literature Review", "Methodology", "Results", "Discussion", "Conclusion"], - style="academic", - citation_style="APA" - ) - - print(f"Generated paper: {paper.title}") - print(f"Number of sections: {len(paper.sections)}") - print(f"Number of references: {len(paper.references)}") - - # Display a section - if paper.sections: - print(f"\nFirst section preview:") - print(f"Title: {paper.sections[0].title}") - print(f"Content: {paper.sections[0].content[:200]}...") - - return paper - -def multi_agent_scientific_workflow_example(): - """Example of multi-agent scientific writing workflow.""" - - print("\n=== Multi-Agent Scientific Workflow Example ===") - - # Create specialized agents for different research tasks - literature_reviewer = Agent( - name="Literature Reviewer", - role="Literature Review Specialist", - instructions="You specialize in reviewing scientific literature and identifying key research gaps.", - model="gpt-4o-mini" # Use default model for literature review - ) - - methodology_designer = Agent( - name="Methodology Designer", - role="Research Methodology Expert", - instructions="You design rigorous research methodologies for scientific studies.", - model="gpt-4o-mini" - ) - - scientific_writer = ScientificWriterAgent( - name="Scientific Writer", - model="Agnuxo/CAJAL-4B-P2PCLAW" # Use CAJAL for specialized scientific writing - ) - - # Create tasks for the workflow - review_task = Task( - name="review_literature", - description="Review existing literature on coral reef climate impacts", - agent=literature_reviewer - ) - - methodology_task = Task( - name="design_methodology", - description="Design a methodology for studying coral reef responses to climate change", - agent=methodology_designer - ) - - writing_task = Task( - name="write_paper", - description="Write a comprehensive scientific paper combining literature review and methodology", - agent=scientific_writer - ) - - # Create the research team - research_team = AgentTeam( - agents=[literature_reviewer, methodology_designer, scientific_writer], - tasks=[review_task, methodology_task, writing_task] - ) - - print("Executing multi-agent research workflow...") - - # Execute the workflow (this would run all tasks) - # Note: In a real implementation, tasks would be executed sequentially - # with outputs passed between agents - - # For this example, demonstrate individual agent capabilities - print("\n1. Literature Review Agent:") - literature_result = literature_reviewer.start("Review key literature on coral reef climate impacts") - print(f"Literature review: {literature_result[:100]}...") - - print("\n2. Methodology Designer Agent:") - methodology_result = methodology_designer.start("Design a methodology for coral reef climate study") - print(f"Methodology: {methodology_result[:100]}...") - - print("\n3. Scientific Writer Agent (CAJAL):") - paper_section = scientific_writer.write_section( - section_title="Introduction", - content_request="Write an introduction combining the literature review and methodology", - context=f"Literature: {literature_result}\nMethodology: {methodology_result}" - ) - print(f"Introduction section: {paper_section.content[:100]}...") - - return research_team - -def specialized_scientific_tasks_example(): - """Example of specialized scientific writing tasks.""" - - print("\n=== Specialized Scientific Tasks Example ===") - - scientific_writer = ScientificWriterAgent( - name="Academic Writer", - model="Agnuxo/CAJAL-4B-P2PCLAW" - ) - - # Generate different types of scientific content - - # 1. Literature review with citations - print("1. Generating literature review with citations...") - literature_review = scientific_writer.review_and_cite( - research_query="machine learning applications in climate science", - existing_content="Machine learning has emerged as a powerful tool for climate research." - ) - print(f"Literature review: {literature_review[:150]}...") - - # 2. Methodology section - print("\n2. Generating methodology section...") - methodology = scientific_writer.write_section( - section_title="Methodology", - content_request="Describe a machine learning methodology for climate data analysis" - ) - print(f"Methodology: {methodology.content[:150]}...") - - # 3. Results section with LaTeX formatting - print("\n3. Generating results section...") - results = scientific_writer.write_section( - section_title="Results", - content_request="Present hypothetical results with statistical analysis and LaTeX formatting" - ) - print(f"Results: {results.content[:150]}...") - - return scientific_writer - -def main(): - """Run all examples.""" - - print("CAJAL Scientific Writer Agent Integration Examples") - print("=" * 60) - print("\nCAJAL Model Information:") - print("- Model: Agnuxo/CAJAL-4B-P2PCLAW (HuggingFace)") - print("- Size: 2GB local model") - print("- Specialization: Scientific paper generation") - print("- Output: LaTeX-formatted academic content") - print("- Part of: P2PCLAW decentralized research network") - - # Run examples - try: - # Example 1: Basic scientific writing - paper = basic_scientific_writing_example() - - # Example 2: Multi-agent workflow - team = multi_agent_scientific_workflow_example() - - # Example 3: Specialized tasks - writer = specialized_scientific_tasks_example() - - print("\n=== Integration Success ===") - print("✅ ScientificWriterAgent successfully integrated with PraisonAI") - print("✅ CAJAL model support implemented") - print("✅ Multi-agent scientific workflows enabled") - print("✅ LaTeX formatting capabilities added") - - except Exception as e: - print(f"\n❌ Error during execution: {e}") - print("Note: This example requires CAJAL model to be available.") - print("Install with: pip install transformers torch") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/src/praisonai-agents/praisonaiagents/__init__.py b/src/praisonai-agents/praisonaiagents/__init__.py index e662b4ad5..0bf0742cf 100644 --- a/src/praisonai-agents/praisonaiagents/__init__.py +++ b/src/praisonai-agents/praisonaiagents/__init__.py @@ -127,11 +127,6 @@ def _get_lazy_cache(): 'get_tool': ('praisonaiagents.tools.registry', 'get_tool'), 'ToolRegistry': ('praisonaiagents.tools.registry', 'ToolRegistry'), - # Specialized agents - 'ScientificWriterAgent': ('praisonaiagents.agent', 'ScientificWriterAgent'), - 'PaperSection': ('praisonaiagents.agent', 'PaperSection'), - 'ScientificPaper': ('praisonaiagents.agent', 'ScientificPaper'), - # Main display utilities (imports rich) 'TaskOutput': ('praisonaiagents.main', 'TaskOutput'), 'ReflectionOutput': ('praisonaiagents.main', 'ReflectionOutput'), diff --git a/src/praisonai-agents/praisonaiagents/agent/__init__.py b/src/praisonai-agents/praisonaiagents/agent/__init__.py index 309e71ca3..4f7ae5502 100644 --- a/src/praisonai-agents/praisonaiagents/agent/__init__.py +++ b/src/praisonai-agents/praisonaiagents/agent/__init__.py @@ -111,18 +111,6 @@ def __getattr__(name): from .code_agent import CodeConfig _lazy_cache[name] = CodeConfig return CodeConfig - elif name == 'ScientificWriterAgent': - from .scientific_writer_agent import ScientificWriterAgent - _lazy_cache[name] = ScientificWriterAgent - return ScientificWriterAgent - elif name == 'PaperSection': - from .scientific_writer_agent import PaperSection - _lazy_cache[name] = PaperSection - return PaperSection - elif name == 'ScientificPaper': - from .scientific_writer_agent import ScientificPaper - _lazy_cache[name] = ScientificPaper - return ScientificPaper # Handoff - lightweight _handoff_names = { @@ -226,9 +214,6 @@ def __getattr__(name): 'RealtimeConfig', 'CodeAgent', 'CodeConfig', - 'ScientificWriterAgent', - 'PaperSection', - 'ScientificPaper', 'ContextAgent', 'create_context_agent', 'Handoff', diff --git a/src/praisonai-agents/praisonaiagents/agent/scientific_writer_agent.py b/src/praisonai-agents/praisonaiagents/agent/scientific_writer_agent.py deleted file mode 100644 index ee9409053..000000000 --- a/src/praisonai-agents/praisonaiagents/agent/scientific_writer_agent.py +++ /dev/null @@ -1,386 +0,0 @@ -""" -Scientific Writer Agent Module - -This module provides the ScientificWriterAgent class for generating scientific papers -using CAJAL (Specialized Scientific Paper Agent) from P2PCLAW. - -CAJAL is a 2GB local model specialized for scientific paper generation, producing -LaTeX-formatted academic output. It's part of the P2PCLAW decentralized research network. - -Features: -- Local 2GB model for privacy and offline operation -- LaTeX-formatted academic output -- Specialized for scientific paper generation -- Integration with PraisonAI multi-agent workflows - -Example: - from praisonaiagents import ScientificWriterAgent - - # Basic usage - agent = ScientificWriterAgent( - name="Research Paper Writer", - model="cajal-4b", - instructions="You are a specialized scientific paper writer" - ) - - paper = agent.write_paper("Write a paper on climate change effects on coral reefs") - print(paper.latex_content) - - # Multi-agent workflow - from praisonaiagents import Agent, AgentTeam, Task - - literature_reviewer = Agent( - name="Literature Reviewer", - model="cajal-4b", - instructions="Review and cite relevant literature" - ) - - methodology_designer = Agent( - name="Methodology Designer", - instructions="Design research methodology" - ) - - scientific_writer = ScientificWriterAgent( - name="Scientific Writer", - model="cajal-4b" - ) - - team = AgentTeam( - agents=[literature_reviewer, methodology_designer, scientific_writer], - tasks=[ - Task("review_literature", "Review literature on the topic", literature_reviewer), - Task("design_methodology", "Design research methodology", methodology_designer), - Task("write_paper", "Write the scientific paper", scientific_writer) - ] - ) -""" - -import os -import re -import logging -from praisonaiagents._logging import get_logger -from typing import List, Optional, Any, Dict, Union -from dataclasses import dataclass, field -from .agent import Agent - -logger = get_logger(__name__) - -@dataclass -class PaperSection: - """Represents a section of a scientific paper.""" - title: str - content: str - latex_content: str = "" - - def __repr__(self): - content_preview = self.content[:100] + "..." if len(self.content) > 100 else self.content - return f"PaperSection(title='{self.title}', content='{content_preview}')" - -@dataclass -class ScientificPaper: - """Represents a complete scientific paper with LaTeX formatting.""" - title: str - abstract: str - sections: List[PaperSection] = field(default_factory=list) - references: List[str] = field(default_factory=list) - latex_content: str = "" - metadata: Dict[str, Any] = field(default_factory=dict) - - def __repr__(self): - return f"ScientificPaper(title='{self.title}', sections={len(self.sections)}, references={len(self.references)})" - -class ScientificWriterAgent: - """ - Specialized agent for scientific paper generation using CAJAL model. - - This agent integrates the CAJAL model from P2PCLAW for generating academic papers - in LaTeX format. It follows the protocol-driven design of PraisonAI while providing - specialized functionality for scientific writing. - - The agent can work standalone or as part of a multi-agent workflow with - literature reviewers, methodology designers, and other research agents. - """ - - def __init__( - self, - name: Optional[str] = None, - model: Optional[str] = None, - instructions: Optional[str] = None, - role: Optional[str] = None, - goal: Optional[str] = None, - backstory: Optional[str] = None, - **kwargs - ): - """ - Initialize a ScientificWriterAgent. - - Args: - name: Agent name (defaults to "Scientific Writer") - model: Model to use (defaults to "cajal-4b" if available) - instructions: Custom instructions for the agent - role: Agent role (defaults to "Scientific Paper Writer") - goal: Agent goal (defaults to scientific writing goal) - backstory: Agent backstory (defaults to scientific writing backstory) - **kwargs: Additional arguments passed to base Agent - """ - # Set defaults for scientific writing - name = name or "Scientific Writer" - role = role or "Scientific Paper Writer" - goal = goal or "Generate high-quality scientific papers with proper academic formatting and citations" - backstory = backstory or ( - "You are a specialized scientific paper writer trained on academic literature. " - "You excel at creating well-structured, properly cited research papers in LaTeX format. " - "You understand academic conventions, citation styles, and the importance of rigorous methodology." - ) - - # Default instructions for scientific writing - if not instructions: - instructions = ( - "You are a specialized scientific paper writer. Your role is to create high-quality " - "academic papers with proper structure, citations, and LaTeX formatting. " - "Always follow academic conventions and ensure rigorous methodology. " - "Focus on clarity, precision, and scholarly communication." - ) - - # Set default model to CAJAL if not specified - if not model: - # Check if CAJAL is available, fallback to default model - model = self._get_cajal_model() - - # Initialize the base Agent with scientific writing configuration - self.agent = Agent( - name=name, - role=role, - goal=goal, - backstory=backstory, - instructions=instructions, - llm=model, - **kwargs - ) - - # Store CAJAL-specific configuration - self.is_cajal_model = "cajal" in (model or "").lower() - self.model_name = model - - logger.info(f"Initialized ScientificWriterAgent '{name}' with model '{model}'") - - def _get_cajal_model(self) -> str: - """ - Return the default CAJAL model identifier. - - Returns: - Model name to use for scientific writing - """ - # Return the HuggingFace model path for CAJAL - return "Agnuxo/CAJAL-4B-P2PCLAW" - - def write_paper( - self, - topic: str, - sections: Optional[List[str]] = None, - style: str = "academic", - citation_style: str = "APA" - ) -> ScientificPaper: - """ - Generate a complete scientific paper on the given topic. - - Args: - topic: The research topic or question - sections: List of section titles to include (defaults to standard academic sections) - style: Writing style ("academic", "review", "research") - citation_style: Citation style to use ("APA", "IEEE", "Nature") - - Returns: - ScientificPaper object with generated content - """ - if not sections: - sections = ["Introduction", "Literature Review", "Methodology", "Results", "Discussion", "Conclusion"] - - # Construct the prompt for paper generation - prompt = self._build_paper_prompt(topic, sections, style, citation_style) - - # Generate the paper using the agent - response = self.agent.start(prompt) - - # Parse the response into a structured ScientificPaper object - paper = self._parse_paper_response(response, topic, sections) - - return paper - - def write_section( - self, - section_title: str, - content_request: str, - context: Optional[str] = None - ) -> PaperSection: - """ - Generate a specific section of a scientific paper. - - Args: - section_title: Title of the section to generate - content_request: Specific request for the section content - context: Additional context or previous sections - - Returns: - PaperSection object with generated content - """ - prompt = f""" - Write a {section_title} section for a scientific paper. - - Content request: {content_request} - - {f"Context from previous sections: {context}" if context else ""} - - Please provide: - 1. Well-structured content appropriate for the {section_title} section - 2. Proper academic language and formatting - 3. LaTeX formatting where appropriate - 4. Citations in proper academic format - - Format the output clearly with section headings and proper academic style. - """ - - response = self.agent.start(prompt) - - # Create a PaperSection object - section = PaperSection( - title=section_title, - content=response, - latex_content=self._extract_latex(response) - ) - - return section - - def review_and_cite( - self, - research_query: str, - existing_content: Optional[str] = None - ) -> str: - """ - Review literature and add citations to existing content. - - Args: - research_query: The research query for literature review - existing_content: Existing content to add citations to - - Returns: - Content with added literature review and citations - """ - if existing_content: - prompt = f""" - Please review the following content and add appropriate citations and literature references: - - {existing_content} - - Research query: {research_query} - - Please: - 1. Add relevant citations where appropriate - 2. Include a literature review section if not present - 3. Ensure all claims are properly supported with references - 4. Use proper academic citation format - """ - else: - prompt = f""" - Conduct a literature review on: {research_query} - - Please provide: - 1. Overview of current research in the field - 2. Key findings and methodologies - 3. Gaps in the literature - 4. Proper citations and references - 5. LaTeX formatting for academic publication - """ - - return self.agent.start(prompt) - - def _build_paper_prompt( - self, - topic: str, - sections: List[str], - style: str, - citation_style: str - ) -> str: - """Build the prompt for full paper generation.""" - sections_str = "\n".join([f"- {section}" for section in sections]) - - return f""" - Write a comprehensive scientific paper on the following topic: {topic} - - Required sections: - {sections_str} - - Requirements: - - Style: {style} - - Citation style: {citation_style} - - Use proper LaTeX formatting for academic publication - - Include appropriate citations and references - - Maintain rigorous academic standards - - Structure the paper with clear headings and logical flow - - Please provide a complete, well-structured academic paper suitable for publication. - """ - - def _parse_paper_response( - self, - response: str, - topic: str, - sections: List[str] - ) -> ScientificPaper: - """Parse the agent response into a structured ScientificPaper object.""" - # Extract title (basic implementation) - title = topic # Could be improved with NLP parsing - - # Extract abstract (basic implementation) - abstract = self._extract_section(response, "abstract") or "Abstract not found" - - # Extract sections - paper_sections = [] - for section_name in sections: - section_content = self._extract_section(response, section_name.lower()) - if section_content: - paper_sections.append(PaperSection( - title=section_name, - content=section_content, - latex_content=self._extract_latex(section_content) - )) - - # Extract references - references = self._extract_references(response) - - return ScientificPaper( - title=title, - abstract=abstract, - sections=paper_sections, - references=references, - latex_content=response, # Full response as LaTeX - metadata={ - "model": self.model_name, - "generated_by": "ScientificWriterAgent", - "is_cajal": self.is_cajal_model - } - ) - - def _extract_section(self, text: str, section_name: str) -> Optional[str]: - """Extract a specific section from the generated text.""" - pattern = rf"##?\s+{re.escape(section_name)}[^\n]*\n(.*?)(?=\n\s*##?\s|\Z)" - match = re.search(pattern, text, re.IGNORECASE | re.DOTALL) - return match.group(1).strip() if match else None - - def _extract_latex(self, text: str) -> str: - """Extract LaTeX formatting from text.""" - # Basic implementation - return text as-is assuming it contains LaTeX - return text - - def _extract_references(self, text: str) -> List[str]: - """Extract references from the generated text.""" - ref_pattern = r"\\cite\{[^}]+\}|\[[0-9]+\]" - references = re.findall(ref_pattern, text) - return references - - # Delegate other methods to the underlying agent - def __getattr__(self, name): - """Delegate unknown attributes to the underlying agent.""" - if name == 'agent': - raise AttributeError("'ScientificWriterAgent' object has no attribute 'agent'") - return getattr(self.agent, name) \ No newline at end of file diff --git a/src/praisonai-agents/tests/unit/agent/test_scientific_writer_agent.py b/src/praisonai-agents/tests/unit/agent/test_scientific_writer_agent.py deleted file mode 100644 index 611e297f3..000000000 --- a/src/praisonai-agents/tests/unit/agent/test_scientific_writer_agent.py +++ /dev/null @@ -1,323 +0,0 @@ -""" -Tests for ScientificWriterAgent - specialized agent for scientific paper generation. - -This test suite validates the integration of CAJAL model support and -scientific writing capabilities within PraisonAI. -""" - -import pytest -import sys -import os -from unittest.mock import patch, MagicMock - -# Add the src directory to Python path for testing -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) - -from praisonaiagents.agent.scientific_writer_agent import ( - ScientificWriterAgent, - PaperSection, - ScientificPaper -) - -class TestPaperSection: - """Test the PaperSection dataclass.""" - - def test_paper_section_creation(self): - """Test creating a PaperSection.""" - section = PaperSection( - title="Introduction", - content="This is the introduction content.", - latex_content="\\section{Introduction}\nThis is the introduction content." - ) - - assert section.title == "Introduction" - assert section.content == "This is the introduction content." - assert "\\section{Introduction}" in section.latex_content - - def test_paper_section_repr(self): - """Test string representation of PaperSection.""" - section = PaperSection( - title="Methods", - content="This is a very long methodology section that should be truncated in the repr method for better display.", - ) - - repr_str = repr(section) - assert "Methods" in repr_str - assert "..." in repr_str # Should be truncated - -class TestScientificPaper: - """Test the ScientificPaper dataclass.""" - - def test_scientific_paper_creation(self): - """Test creating a ScientificPaper.""" - sections = [ - PaperSection("Introduction", "Introduction content"), - PaperSection("Methods", "Methods content") - ] - references = ["Author et al. (2024)", "Smith & Jones (2023)"] - - paper = ScientificPaper( - title="Test Paper", - abstract="This is the abstract", - sections=sections, - references=references, - metadata={"model": "cajal-4b"} - ) - - assert paper.title == "Test Paper" - assert paper.abstract == "This is the abstract" - assert len(paper.sections) == 2 - assert len(paper.references) == 2 - assert paper.metadata["model"] == "cajal-4b" - - def test_scientific_paper_repr(self): - """Test string representation of ScientificPaper.""" - paper = ScientificPaper( - title="Climate Change Research", - abstract="Abstract content", - sections=[PaperSection("Intro", "content")], - references=["Ref1", "Ref2"] - ) - - repr_str = repr(paper) - assert "Climate Change Research" in repr_str - assert "sections=1" in repr_str - assert "references=2" in repr_str - -class TestScientificWriterAgent: - """Test the ScientificWriterAgent class.""" - - @patch('praisonaiagents.agent.scientific_writer_agent.Agent') - def test_agent_initialization_defaults(self, mock_agent_class): - """Test ScientificWriterAgent initialization with defaults.""" - mock_agent = MagicMock() - mock_agent_class.return_value = mock_agent - - agent = ScientificWriterAgent() - - # Verify Agent was called with appropriate defaults - mock_agent_class.assert_called_once() - call_kwargs = mock_agent_class.call_args[1] - - assert call_kwargs['name'] == "Scientific Writer" - assert call_kwargs['role'] == "Scientific Paper Writer" - assert "scientific paper writer" in call_kwargs['instructions'].lower() - assert "academic" in call_kwargs['goal'].lower() - - @patch('praisonaiagents.agent.scientific_writer_agent.Agent') - def test_agent_initialization_custom(self, mock_agent_class): - """Test ScientificWriterAgent initialization with custom parameters.""" - mock_agent = MagicMock() - mock_agent_class.return_value = mock_agent - - agent = ScientificWriterAgent( - name="Custom Writer", - model="custom-model", - instructions="Custom instructions", - role="Custom Role" - ) - - call_kwargs = mock_agent_class.call_args[1] - assert call_kwargs['name'] == "Custom Writer" - assert call_kwargs['role'] == "Custom Role" - assert call_kwargs['instructions'] == "Custom instructions" - assert call_kwargs['llm'] == "custom-model" - - @patch('praisonaiagents.agent.scientific_writer_agent.Agent') - def test_cajal_model_detection(self, mock_agent_class): - """Test CAJAL model detection.""" - mock_agent = MagicMock() - mock_agent_class.return_value = mock_agent - - # Test with CAJAL model - agent = ScientificWriterAgent(model="cajal-4b") - assert agent.is_cajal_model == True - - # Test with non-CAJAL model - agent = ScientificWriterAgent(model="gpt-4o-mini") - assert agent.is_cajal_model == False - - @patch('praisonaiagents.agent.scientific_writer_agent.Agent') - def test_write_paper_method(self, mock_agent_class): - """Test the write_paper method.""" - mock_agent = MagicMock() - mock_agent.start.return_value = """ - # Climate Change Effects on Marine Ecosystems - - ## Abstract - This paper examines the impact of climate change on marine ecosystems. - - ## Introduction - Climate change poses significant threats to marine life. - - ## Methodology - We conducted a comprehensive literature review. - - ## Results - Our findings indicate significant coral bleaching. - - ## Discussion - The results suggest immediate action is needed. - - ## Conclusion - Climate change mitigation is crucial for marine conservation. - - References: - - Smith et al. (2024) - - Jones & Brown (2023) - """ - mock_agent_class.return_value = mock_agent - - agent = ScientificWriterAgent() - paper = agent.write_paper("Climate Change Effects on Marine Ecosystems") - - # Verify agent.start was called with a prompt - mock_agent.start.assert_called_once() - call_args = mock_agent.start.call_args[0][0] - assert "Climate Change Effects on Marine Ecosystems" in call_args - assert "academic" in call_args - - # Verify paper structure - assert isinstance(paper, ScientificPaper) - assert paper.title == "Climate Change Effects on Marine Ecosystems" - assert paper.metadata["generated_by"] == "ScientificWriterAgent" - - @patch('praisonaiagents.agent.scientific_writer_agent.Agent') - def test_write_section_method(self, mock_agent_class): - """Test the write_section method.""" - mock_agent = MagicMock() - mock_agent.start.return_value = "This is the methodology section content with detailed procedures." - mock_agent_class.return_value = mock_agent - - agent = ScientificWriterAgent() - section = agent.write_section( - section_title="Methodology", - content_request="Describe the research methodology" - ) - - # Verify agent.start was called - mock_agent.start.assert_called_once() - call_args = mock_agent.start.call_args[0][0] - assert "Methodology" in call_args - assert "research methodology" in call_args - - # Verify section structure - assert isinstance(section, PaperSection) - assert section.title == "Methodology" - assert "methodology section content" in section.content - - @patch('praisonaiagents.agent.scientific_writer_agent.Agent') - def test_review_and_cite_method(self, mock_agent_class): - """Test the review_and_cite method.""" - mock_agent = MagicMock() - mock_agent.start.return_value = "Literature review with citations [1] and proper academic formatting." - mock_agent_class.return_value = mock_agent - - agent = ScientificWriterAgent() - result = agent.review_and_cite( - research_query="machine learning in climate science", - existing_content="Machine learning has applications in climate research." - ) - - # Verify agent.start was called - mock_agent.start.assert_called_once() - call_args = mock_agent.start.call_args[0][0] - assert "machine learning in climate science" in call_args - assert "Machine learning has applications" in call_args - - # Verify result - assert "Literature review" in result - assert "[1]" in result - - @patch('praisonaiagents.agent.scientific_writer_agent.Agent') - def test_get_cajal_model_method(self, mock_agent_class): - """Test the _get_cajal_model method.""" - mock_agent_class.return_value = MagicMock() - - agent = ScientificWriterAgent() - model = agent._get_cajal_model() - - # Should return the HuggingFace model path - assert model == "Agnuxo/CAJAL-4B-P2PCLAW" - - @patch('praisonaiagents.agent.scientific_writer_agent.Agent') - def test_attribute_delegation(self, mock_agent_class): - """Test that unknown attributes are delegated to the underlying agent.""" - mock_agent = MagicMock() - mock_agent.some_method.return_value = "delegated result" - mock_agent_class.return_value = mock_agent - - agent = ScientificWriterAgent() - - # Test method delegation - result = agent.some_method("test_arg") - assert result == "delegated result" - mock_agent.some_method.assert_called_once_with("test_arg") - - # Test attribute access delegation - mock_agent.some_property = "property value" - assert agent.some_property == "property value" - -class TestScientificWriterAgentIntegration: - """Integration tests for ScientificWriterAgent with real Agent class.""" - - def test_real_agentic_test(self): - """Real agentic test - agent runs end-to-end.""" - # This is a simplified test that doesn't require actual LLM calls - # In a real test, this would make an actual LLM call - - print("Testing ScientificWriterAgent integration...") - - try: - # Test import and basic instantiation - from praisonaiagents import ScientificWriterAgent - - agent = ScientificWriterAgent( - name="Test Scientific Writer", - model="gpt-4o-mini", # Use a standard model for testing - instructions="You are a test scientific writer." - ) - - # Verify agent properties - assert agent.agent.name == "Test Scientific Writer" - assert "scientific writer" in agent.agent.instructions.lower() - assert agent.is_cajal_model == False # gpt-4o-mini is not CAJAL - - print("✅ ScientificWriterAgent created successfully") - print(f"Agent name: {agent.agent.name}") - print(f"Is CAJAL model: {agent.is_cajal_model}") - print(f"Model: {agent.model_name}") - - # Test basic functionality without LLM call - # (In a full test, you would call agent.start() here) - - except ImportError as e: - pytest.skip(f"Required dependencies not available: {e}") - except Exception as e: - print(f"❌ Test failed: {e}") - raise - -def test_scientific_writer_import(): - """Test that ScientificWriterAgent can be imported from main package.""" - try: - from praisonaiagents import ScientificWriterAgent, PaperSection, ScientificPaper - assert ScientificWriterAgent is not None - assert PaperSection is not None - assert ScientificPaper is not None - print("✅ All scientific writing classes imported successfully") - except ImportError as e: - pytest.fail(f"Failed to import ScientificWriterAgent: {e}") - -if __name__ == "__main__": - # Run basic smoke tests - print("Running ScientificWriterAgent tests...") - - # Test imports - test_scientific_writer_import() - - # Test basic functionality - integration_test = TestScientificWriterAgentIntegration() - integration_test.test_real_agentic_test() - - print("\n✅ All basic tests passed!") - print("Run 'pytest test_scientific_writer_agent.py' for full test suite.") \ No newline at end of file