├── .env.example ├── Agent1_Peer_Review ├── src │ ├── __init__.py │ ├── reviewer_agents │ │ ├── __init__.py │ │ ├── rigor │ │ │ ├── __init__.py │ │ │ ├── README.md │ │ │ ├── R1_originality_contribution_agent.py │ │ │ ├── R2_impact_significance_agent.py │ │ │ ├── R3_ethics_compliance_agent.py │ │ │ ├── R4_data_code_availability_agent.py │ │ │ ├── R7_consistency_agent.py │ │ │ ├── R5_statistical_rigor_agent.py │ │ │ └── R6_technical_accuracy_agent.py │ │ ├── quality │ │ │ ├── __init__.py │ │ │ └── quality_control_agent.py │ │ ├── section │ │ │ ├── S2_abstract_agent.py │ │ │ ├── S9_references_agent.py │ │ │ ├── S5_methodology_agent.py │ │ │ ├── S3_introduction_agent.py │ │ │ ├── S4_literature_review_agent.py │ │ │ ├── S6_results_agent.py │ │ │ ├── S8_conclusion_agent.py │ │ │ ├── S7_discussion_agent.py │ │ │ ├── S10_supplementary_materials_agent.py │ │ │ └── S1_title_keywords_agent.py │ │ ├── writing │ │ │ ├── W6_citation_formatting_agent.py │ │ │ ├── W1_language_style_agent.py │ │ │ ├── W3_clarity_conciseness_agent.py │ │ │ ├── W2_narrative_structure_agent.py │ │ │ ├── W7_target_audience_agent.py │ │ │ ├── W4_terminology_consistency_agent.py │ │ │ └── W5_inclusive_language_agent.py │ │ ├── controller_agent.py │ │ └── executive_summary_agent.py │ ├── utils │ │ ├── combine_results.py │ │ └── pdf_parser.py │ └── core │ │ ├── base_agent.py │ │ ├── report_template.py │ │ └── config.py ├── logo.png ├── manuscript.json ├── requirements.txt ├── logo.svg ├── run_local_aipeer_review.py ├── run_analysis.py ├── run_executive_summary.py └── run_quality_control.py ├── .gitignore ├── LICENSE.txt ├── README.md └── Agent2_Outlet_Fit └── README.md /.env.example: -------------------------------------------------------------------------------- 1 | # OpenAI API Key 2 | OPENAI_API_KEY=your_api_key_here -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module contains the manuscript reviewer system. 3 | """ -------------------------------------------------------------------------------- /Agent1_Peer_Review/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Agentic-Systems-Lab/rigorous/HEAD/Agent1_Peer_Review/logo.png -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This package contains the reviewer agents for manuscript analysis. 3 | """ -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This package contains the rigor agents for manuscript analysis. 3 | """ -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/quality/__init__.py: -------------------------------------------------------------------------------- 1 | from .quality_control_agent import QualityControlAgent 2 | 3 | __all__ = ['QualityControlAgent'] -------------------------------------------------------------------------------- /Agent1_Peer_Review/manuscript.json: -------------------------------------------------------------------------------- 1 | { 2 | "manuscript_src": "manuscripts/manuscript.pdf", 3 | "publicationOutlets" : "e.g., Nature Medicine", 4 | "reviewFocus" : "e.g., Statistics and Writing" 5 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/requirements.txt: -------------------------------------------------------------------------------- 1 | PyPDF2>=3.0.0 2 | PyMuPDF>=1.22.0 # fitz 3 | Pillow>=10.0.0 # PIL 4 | pytesseract>=0.3.10 5 | numpy>=1.24.0 6 | openai>=1.0.0 7 | python-dotenv>=0.19.0 8 | langchain>=0.1.0 9 | langchain-community>=0.0.10 10 | typing-extensions>=4.0.0 11 | requests>=2.31.0 12 | reportlab>=4.0.0 13 | python-json-logger>=2.0.0 14 | nougat-ocr>=0.1.0 15 | pdf2image>=1.16.3 16 | pydantic>=2.0.0 17 | pytest>=7.0.0 18 | tqdm>=4.65.0 19 | pandas>=2.0.0 -------------------------------------------------------------------------------- /Agent1_Peer_Review/logo.svg: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Environment variables 2 | .env 3 | 4 | # Python 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | *.so 9 | .Python 10 | build/ 11 | develop-eggs/ 12 | dist/ 13 | downloads/ 14 | eggs/ 15 | .eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | wheels/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | venv/ 26 | 27 | # Analysis results 28 | **/analysis_results/ 29 | */results/ 30 | # PDF files 31 | **/manuscripts/*.pdf 32 | */reports/* 33 | 34 | # IDE 35 | .vscode/ 36 | .idea/ 37 | *.swp 38 | *.swo 39 | 40 | # OS 41 | .DS_Store 42 | .DS_Store? 43 | ._* 44 | .Spotlight-V100 45 | .Trashes 46 | ehthumbs.db 47 | Thumbs.db 48 | Agent1_Peer_Review/run_cloud_aipeer_review.py 49 | Agent1_Peer_Review/find_ids.py 50 | Agent1_Peer_Review/tmp.py 51 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Robert Jakob & Kevin O'Sullivan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Agent1_Peer_Review/run_local_aipeer_review.py: -------------------------------------------------------------------------------- 1 | import run_analysis 2 | import run_quality_control 3 | import run_executive_summary 4 | import json 5 | import os 6 | from datetime import datetime 7 | import pdf_generator 8 | import time 9 | 10 | 11 | 12 | 13 | 14 | def get_local_manuscript(): 15 | with open('manuscript.json', "r") as f: 16 | manuscript = json.load(f) 17 | 18 | publication_outlet = manuscript['publicationOutlets'] or '' 19 | review_focus = manuscript['reviewFocus'] or '' 20 | 21 | manuscript['context'] = { 22 | "target_publication_outlets": { 23 | "label": "Target Publication Outlets (optional but recommended)", 24 | "description": "This helps us tailor the review to your target venue's requirements.", 25 | "placeholder": "e.g., Nature Medicine, Science, or specific conferences like NeurIPS 2024", 26 | "user_input": publication_outlet 27 | }, 28 | "review_focus_areas": { 29 | "label": "Review Focus Areas (optional but recommended)", 30 | "description": "Specify any particular aspects you'd like the AI peer reviewers to focus on.", 31 | "placeholder": "e.g., statistical analysis, methodology, experimental design, motivation, or specific aspects you want reviewers to focus on", 32 | "user_input": review_focus 33 | } 34 | } 35 | 36 | return manuscript 37 | 38 | if __name__ == "__main__": 39 | 40 | start_time = time.time() 41 | 42 | base_dir = os.path.dirname(os.path.abspath(__file__)) 43 | 44 | # Get manuscript 45 | manuscript = get_local_manuscript() 46 | 47 | print('manuscript', manuscript) 48 | 49 | # Run analysis 50 | analysis_results = run_analysis.run_analysis(manuscript) 51 | manuscript = manuscript.copy() | analysis_results 52 | 53 | # Run quality control 54 | quality_control_results = run_quality_control.run_quality_control(manuscript) 55 | manuscript['quality_control_results'] = quality_control_results 56 | 57 | executive_summary_results = run_executive_summary.run_executive_summary(manuscript) 58 | manuscript['executive_summary_results'] = executive_summary_results 59 | 60 | current_datetime = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") 61 | manuscript['output_path'] = os.path.join(base_dir, 'reports', f'{current_datetime}_review_report.pdf') 62 | 63 | # Generate PDF 64 | pdf_generator.generate_pdf(manuscript) 65 | 66 | elapsed_time = time.time() - start_time 67 | elapsed_minutes = elapsed_time / 60 68 | print(f"Code block executed in {elapsed_minutes:.2f} minutes.") -------------------------------------------------------------------------------- /Agent1_Peer_Review/run_analysis.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import glob 4 | from src.utils.pdf_parser import PDFParser 5 | from src.reviewer_agents.controller_agent import ControllerAgent 6 | from src.core.config import DEFAULT_MODEL 7 | from src.utils.combine_results import combine_results_by_category 8 | from dotenv import load_dotenv 9 | import pathlib 10 | 11 | # Load environment variables 12 | env_path = pathlib.Path(__file__).parent.parent / '.env' 13 | load_dotenv(env_path) 14 | 15 | 16 | def process_pdf(pdf_url): 17 | """Process PDF and extract text, figures, and tables.""" 18 | 19 | # Pass to PDFParser 20 | parser = PDFParser(pdf_url) 21 | 22 | # Extract all components 23 | text = parser.extract_text() 24 | metadata = parser.get_metadata() 25 | images = parser.extract_images() 26 | tables = parser.extract_tables() 27 | 28 | return { 29 | 'text': text, 30 | 'metadata': metadata, 31 | 'images': images, 32 | 'tables': tables 33 | } 34 | 35 | def run_analysis(manuscript): # Find PDF in manuscripts directory 36 | 37 | # Process the manuscript 38 | manuscript_data = process_pdf(manuscript['manuscript_src']) 39 | 40 | # Initialize controller agent 41 | controller = ControllerAgent(model=DEFAULT_MODEL) 42 | 43 | # Run the analysis 44 | results = controller.run_analysis(text=manuscript_data['text']) 45 | 46 | # Save results 47 | output_dir = "results" 48 | os.makedirs(output_dir, exist_ok=True) 49 | 50 | # Save manuscript data for reference 51 | manuscript_data_file = os.path.join(output_dir, "manuscript_data.json") 52 | with open(manuscript_data_file, "w") as f: 53 | # Convert image data to base64 for JSON serialization 54 | manuscript_json = manuscript_data.copy() 55 | for img in manuscript_json['images']: 56 | img['image_data'] = None # Remove binary image data for JSON 57 | json.dump(manuscript_json, f, indent=2) 58 | 59 | # Save individual agent results 60 | for agent_name, result in results.items(): 61 | output_file = os.path.join(output_dir, f"{agent_name}_results.json") 62 | with open(output_file, "w") as f: 63 | json.dump(result, f, indent=2) 64 | 65 | # Save combined results 66 | combined_output = os.path.join(output_dir, "combined_results.json") 67 | with open(combined_output, "w") as f: 68 | json.dump(results, f, indent=2) 69 | 70 | # Combine results into category-specific files 71 | combined_results = combine_results_by_category(output_dir, output_dir) 72 | 73 | return combined_results 74 | 75 | if __name__ == "__main__": 76 | 77 | with open('manuscript.json', "r") as f: 78 | manuscript = json.load(f) 79 | 80 | # Run the analysis 81 | run_analysis(manuscript) -------------------------------------------------------------------------------- /Agent1_Peer_Review/run_executive_summary.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Script to run the Executive Summary Agent and generate a high-level summary of the review results. 4 | """ 5 | 6 | import os 7 | import json 8 | from src.reviewer_agents.executive_summary_agent import ExecutiveSummaryAgent 9 | 10 | def get_local_manuscript(): 11 | with open('manuscript.json', "r") as f: 12 | manuscript = json.load(f) 13 | 14 | publication_outlet = manuscript['publicationOutlets'] or '' 15 | review_focus = manuscript['reviewFocus'] or '' 16 | 17 | manuscript['context'] = { 18 | "target_publication_outlets": { 19 | "label": "Target Publication Outlets (optional but recommended)", 20 | "description": "This helps us tailor the review to your target venue's requirements.", 21 | "placeholder": "e.g., Nature Medicine, Science, or specific conferences like NeurIPS 2024", 22 | "user_input": publication_outlet 23 | }, 24 | "review_focus_areas": { 25 | "label": "Review Focus Areas (optional but recommended)", 26 | "description": "Specify any particular aspects you'd like the AI peer reviewers to focus on.", 27 | "placeholder": "e.g., statistical analysis, methodology, experimental design, motivation, or specific aspects you want reviewers to focus on", 28 | "user_input": review_focus 29 | } 30 | } 31 | 32 | return manuscript 33 | 34 | def run_executive_summary(inputs): 35 | # Initialize the Executive Summary Agent 36 | agent = ExecutiveSummaryAgent() 37 | 38 | # Define output path 39 | output_path = 'results/executive_summary.json' 40 | 41 | try: 42 | # Process the inputs and generate the executive summary 43 | results = agent.process(inputs) 44 | 45 | # Save the results 46 | agent.save_results(results, output_path) 47 | 48 | print("\nExecutive Summary Generation Complete!", f"Results saved to: {output_path}") 49 | 50 | # Print the scores 51 | print("\nOverall Scores:") 52 | print(f"Section Score: {results['scores']['section_score']:.1f}/5") 53 | print(f"Rigor Score: {results['scores']['rigor_score']:.1f}/5") 54 | print(f"Writing Score: {results['scores']['writing_score']:.1f}/5") 55 | print(f"Final Score: {results['scores']['final_score']:.1f}/5") 56 | 57 | return results 58 | 59 | except Exception as e: 60 | print(f"Error generating executive summary: {str(e)}") 61 | raise 62 | 63 | if __name__ == "__main__": 64 | 65 | manuscript = get_local_manuscript() 66 | 67 | with open('./results/quality_control_results.json', "r") as f: 68 | quality_control_results_json = json.load(f) 69 | 70 | manuscript['quality_control_results'] = quality_control_results_json 71 | 72 | run_executive_summary(manuscript) -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/README.md: -------------------------------------------------------------------------------- 1 | # Scientific Rigor Agents 2 | 3 | These agents ensure research meets high standards of originality, ethics, and accuracy by evaluating various aspects of scientific rigor. 4 | 5 | ## Agent Labels and Descriptions 6 | 7 | ### R1 - Originality and Contribution Agent 8 | - **Purpose**: Assesses research novelty and unique contributions to the field. 9 | - **Key Evaluations**: 10 | - Novelty of research approach 11 | - Unique contributions 12 | - Verification of novelty claims 13 | - Comparison with existing literature 14 | - Knowledge advancement 15 | 16 | ### R2 - Impact and Significance Agent 17 | - **Purpose**: Evaluates research influence and broader implications. 18 | - **Key Evaluations**: 19 | - Field influence potential 20 | - Research advancement potential 21 | - Practical applications 22 | - Policy implications 23 | - Future research directions 24 | 25 | ### R3 - Ethics and Compliance Agent 26 | - **Purpose**: Reviews ethical considerations and research standards compliance. 27 | - **Key Evaluations**: 28 | - Conflicts of interest 29 | - Data privacy and protection 30 | - Informed consent procedures 31 | - Research integrity 32 | - Ethical guidelines adherence 33 | 34 | ### R4 - Data and Code Availability Agent 35 | - **Purpose**: Checks data and code sharing practices and documentation. 36 | - **Key Evaluations**: 37 | - Data availability 38 | - Code availability 39 | - Documentation quality 40 | - Reproducibility 41 | - Sharing practices 42 | 43 | ### R5 - Statistical Rigor Agent 44 | - **Purpose**: Ensures appropriateness and correctness of statistical methods. 45 | - **Key Evaluations**: 46 | - Method appropriateness 47 | - Analysis correctness 48 | - Assumptions validation 49 | - Power analysis 50 | - Reporting completeness 51 | 52 | ### R6 - Technical Accuracy Agent 53 | - **Purpose**: Reviews mathematical derivations and technical content. 54 | - **Key Evaluations**: 55 | - Mathematical correctness 56 | - Algorithm accuracy 57 | - Technical clarity 58 | - Derivation completeness 59 | - Implementation feasibility 60 | 61 | ### R7 - Consistency Agent 62 | - **Purpose**: Checks logical coherence across manuscript sections. 63 | - **Key Evaluations**: 64 | - Methods-Results alignment 65 | - Results-Conclusions alignment 66 | - Claims consistency 67 | - Variable/terminology consistency 68 | - Cross-section coherence 69 | 70 | ## Implementation Details 71 | 72 | Each agent: 73 | - Inherits from `BaseReviewerAgent` 74 | - Uses the `ReportTemplate` for standardized reports 75 | - Provides detailed analysis with subscores 76 | - Generates specific improvement suggestions 77 | - Includes error handling and reporting 78 | - Returns structured JSON output 79 | 80 | ## Usage 81 | 82 | The agents can be used individually or as part of a comprehensive review process. Each agent focuses on specific aspects of scientific rigor while maintaining consistency in reporting format and evaluation standards. -------------------------------------------------------------------------------- /Agent1_Peer_Review/run_quality_control.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import time 4 | from src.reviewer_agents.quality import QualityControlAgent 5 | 6 | def wait_for_files(file_paths: list, timeout: int = 300, check_interval: int = 5) -> bool: 7 | """ 8 | Wait for files to be created and not be empty. 9 | Returns True if all files exist and are not empty, False if timeout is reached. 10 | """ 11 | # Check if files exist and are not empty 12 | for file_path in file_paths: 13 | if not os.path.exists(file_path) or os.path.getsize(file_path) == 0: 14 | return False 15 | return True 16 | 17 | def run_quality_control(inputs): 18 | 19 | # Initialize the quality control agent 20 | agent = QualityControlAgent() 21 | 22 | # Run the quality control analysis 23 | results = agent.process(inputs) 24 | 25 | # Save the results 26 | output_path = os.path.join('./results/', 'quality_control_results.json') 27 | with open(output_path, 'w', encoding='utf-8') as f: 28 | json.dump(results, f, indent=2) 29 | 30 | print(f"Quality control analysis completed. Results saved to: {output_path}") 31 | 32 | return results 33 | 34 | 35 | def create_context_json(manuscript): 36 | 37 | publication_outlet = manuscript['publicationOutlets'] or '' 38 | review_focus = manuscript['reviewFocus'] or '' 39 | 40 | return { 41 | "target_publication_outlets": { 42 | "label": "Target Publication Outlets (optional but recommended)", 43 | "description": "This helps us tailor the review to your target venue's requirements.", 44 | "placeholder": "e.g., Nature Medicine, Science, or specific conferences like NeurIPS 2024", 45 | "user_input": publication_outlet 46 | }, 47 | "review_focus_areas": { 48 | "label": "Review Focus Areas (optional but recommended)", 49 | "description": "Specify any particular aspects you'd like the AI peer reviewers to focus on.", 50 | "placeholder": "e.g., statistical analysis, methodology, experimental design, motivation, or specific aspects you want reviewers to focus on", 51 | "user_input": review_focus 52 | } 53 | } 54 | 55 | if __name__ == '__main__': 56 | 57 | print("Checking for required files...") 58 | for f in map(lambda x: os.path.join('./results', x), ['rigor_results.json', 'section_results.json', 'writing_results.json']): 59 | if not os.path.exists(f): 60 | raise FileNotFoundError(f"Required result file not found: {f}") 61 | 62 | with open('manuscript.json', "r") as f: 63 | manuscript = json.load(f) 64 | 65 | context_json = create_context_json(manuscript) 66 | 67 | with open('./results/rigor_results.json', "r") as f: 68 | rigor_results_json = json.load(f) 69 | 70 | with open('./results/section_results.json', "r") as f: 71 | section_results_json = json.load(f) 72 | 73 | with open('./results/writing_results.json', "r") as f: 74 | writing_results_json = json.load(f) 75 | 76 | inputs = { 77 | 'manuscript_src': './manuscripts/manuscript.pdf', 78 | 'context': context_json, 79 | 'rigor_results': rigor_results_json, 80 | 'section_results': section_results_json, 81 | 'writing_results': writing_results_json 82 | } 83 | 84 | run_quality_control(inputs) -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/utils/combine_results.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Utility functions for combining results from different agents. 4 | 5 | Input files: 6 | - section_results.json: Results from section agents (S1-S10) 7 | - rigor_results.json: Results from rigor agents (R1-R7) 8 | - writing_results.json: Results from writing agents (W1-W7) 9 | """ 10 | 11 | import json 12 | import os 13 | import glob 14 | from typing import Dict, Any 15 | 16 | 17 | def load_json_file(file_path: str) -> Dict[str, Any]: 18 | """Load and parse a JSON file.""" 19 | try: 20 | with open(file_path, 'r', encoding='utf-8') as file: 21 | return json.load(file) 22 | except Exception as e: 23 | print(f"Error loading JSON file {file_path}: {e}") 24 | return {} 25 | 26 | 27 | def save_json_file(data: Dict[str, Any], file_path: str) -> None: 28 | """Save data to a JSON file.""" 29 | try: 30 | with open(file_path, 'w', encoding='utf-8') as file: 31 | json.dump(data, file, indent=2) 32 | print(f"Results successfully saved to {file_path}") 33 | except Exception as e: 34 | print(f"Error saving JSON file: {e}") 35 | 36 | 37 | def combine_results_by_category(results_dir: str, output_dir: str) -> None: 38 | """Combine individual agent results into three category-specific JSON files.""" 39 | # Initialize category-specific result dictionaries 40 | section_results = {} 41 | rigor_results = {} 42 | writing_results = {} 43 | 44 | # Get all JSON files in the results directory 45 | json_files = glob.glob(os.path.join(results_dir, '*_results.json')) 46 | 47 | # Process each JSON file 48 | for file_path in json_files: 49 | # Extract agent name from filename (e.g., 'S1_results.json' -> 'S1') 50 | agent_name = os.path.basename(file_path).split('_')[0] 51 | 52 | # Skip files that are not agent results 53 | if agent_name in ['critical_remarks', 'score', 'detailed_feedback', 'summary', 'improvement_suggestions', 'combined']: 54 | continue 55 | 56 | # Load the agent's results 57 | agent_results = load_json_file(file_path) 58 | 59 | # Skip if the file is empty or contains an error 60 | if not agent_results or (isinstance(agent_results, dict) and 'error' in agent_results): 61 | print(f"Skipping {file_path} due to error or empty file") 62 | continue 63 | 64 | # Categorize and add the agent's results 65 | if agent_name.startswith('S'): 66 | section_results[agent_name] = agent_results 67 | elif agent_name.startswith('R'): 68 | rigor_results[agent_name] = agent_results 69 | elif agent_name.startswith('W'): 70 | writing_results[agent_name] = agent_results 71 | 72 | # Create output directory if it doesn't exist 73 | os.makedirs(output_dir, exist_ok=True) 74 | 75 | # Save the categorized results 76 | save_json_file(section_results, os.path.join(output_dir, 'section_results.json')) 77 | save_json_file(rigor_results, os.path.join(output_dir, 'rigor_results.json')) 78 | save_json_file(writing_results, os.path.join(output_dir, 'writing_results.json')) 79 | 80 | return {"section_results": section_results, "rigor_results": rigor_results, "writing_results": writing_results} 81 | 82 | 83 | def main(): 84 | """Main function to run the script.""" 85 | import argparse 86 | 87 | parser = argparse.ArgumentParser(description='Combine individual agent results into category-specific JSON files') 88 | parser.add_argument('--results-dir', '-r', type=str, 89 | default='results', 90 | help='Directory containing individual agent results') 91 | parser.add_argument('--output-dir', '-o', type=str, 92 | default='results', 93 | help='Directory to save the combined results') 94 | 95 | args = parser.parse_args() 96 | 97 | combine_results_by_category(args.results_dir, args.output_dir) 98 | 99 | 100 | if __name__ == "__main__": 101 | main() -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/core/base_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | import os 4 | from datetime import datetime 5 | from openai import OpenAI 6 | from dotenv import load_dotenv 7 | from .config import DEFAULT_MODEL 8 | import sys 9 | sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) 10 | 11 | class BaseReviewerAgent: 12 | """Base class for all reviewer agents.""" 13 | 14 | def __init__(self, model=DEFAULT_MODEL): 15 | """ 16 | Initialize the base reviewer agent. 17 | 18 | Args: 19 | model (str): The language model to use 20 | name (str): Name of the agent 21 | category (str): Category of the agent (scientific_rigor) 22 | """ 23 | self.name = self.__class__.__name__ 24 | self.category = "Unknown" 25 | self.model = model 26 | 27 | # Initialize OpenAI client with API key from environment 28 | api_key = os.getenv("OPENAI_API_KEY") 29 | if not api_key: 30 | raise ValueError(f"OPENAI_API_KEY environment variable not set. Please check {env_path}") 31 | 32 | # Print debug info 33 | print(f"{self.name} using model: {model}", f"API key found: {'Yes' if api_key else 'No'}") 34 | 35 | self.client = OpenAI(api_key=api_key) 36 | 37 | def llm(self, prompt: str) -> str: 38 | """Call OpenAI API with the given prompt.""" 39 | try: 40 | response = self.client.chat.completions.create( 41 | model=self.model, 42 | messages=[ 43 | {"role": "system", "content": "You are an expert academic reviewer. Provide detailed analysis in JSON format."}, 44 | {"role": "user", "content": prompt} 45 | ], 46 | temperature=0.3, 47 | response_format={"type": "json_object"} 48 | ) 49 | return response.choices[0].message.content 50 | except Exception as e: 51 | raise Exception(f"Error calling language model: {str(e)}") 52 | 53 | def analyze_section(self, text: str, section_name: str) -> Dict[str, Any]: 54 | """Analyze a specific section of the manuscript. 55 | 56 | Args: 57 | text (str): Text content to analyze 58 | section_name (str): Name of the section being analyzed 59 | 60 | Returns: 61 | Dict[str, Any]: Analysis results 62 | """ 63 | prompt = f"""As a {self.name}, analyze the following {section_name} section: 64 | 65 | {text} 66 | 67 | Provide your analysis in the following JSON format: 68 | {{ 69 | "score": <1-5>, 70 | "remarks": [ 71 | "List of specific issues, questions, or observations" 72 | ], 73 | "concrete_suggestions": [ 74 | "List of actionable steps for improvement" 75 | ], 76 | "automated_improvements": [ 77 | "List of AI-generated improvements" 78 | ] 79 | }} 80 | 81 | Ensure your response is valid JSON and includes all required fields.""" 82 | 83 | try: 84 | response = self.client.chat.completions.create( 85 | model=self.model, 86 | messages=[ 87 | {"role": "system", "content": f"You are a {self.name} reviewer."}, 88 | {"role": "user", "content": prompt} 89 | ], 90 | temperature=0.7 91 | ) 92 | 93 | # Extract JSON from response 94 | content = response.choices[0].message.content 95 | start_idx = content.find('{') 96 | end_idx = content.rfind('}') + 1 97 | if start_idx >= 0 and end_idx > start_idx: 98 | analysis = json.loads(content[start_idx:end_idx]) 99 | else: 100 | raise ValueError("No JSON found in response") 101 | 102 | return analysis 103 | 104 | except Exception as e: 105 | print(f"Error analyzing section: {e}") 106 | return {"score": 0, "remarks": [], "concrete_suggestions": [], "automated_improvements": []} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rigorous AI-Powered Scientific Manuscript Analysis 2 | 3 | > **v0.2 Now Live:** The latest version of the AI Reviewer (v0.2) is now available at [https://www.rigorous.review/](https://www.rigorous.review/). Upload your manuscript, provide context on your target journal and receive structured feedback directly online via an interactive interface — now with progress tracking built in. Once initial testing of v0.2 is complete, we will make all module prompts open source to promote transparency and enable community contributions. 4 | 5 | > **Help Us Improve!** Please provide feedback via [this short feedback form](https://docs.google.com/forms/d/1EhQvw-HdGRqfL01jZaayoaiTWLSydZTI4V0lJSvNpds) to help us improve the system. 6 | 7 | > Support AI Reviewer v0.3 by rocking some *peer-reviewed merch* 👕🧠 – [grab yours here](https://rigorous-shop.fourthwall.com/) – GitHub contributors get free gear. 8 | 9 | ## Vision 10 | 11 | This repository is intended for tools that make the creation, evaluation, and distribution of scientific knowledge more transparent, cheaper, faster, and better. Let's build this future together! 12 | 13 | ## Project Structure 14 | 15 | - **Agent1_Peer_Review**: Multiagent AI review system for comprehensive manuscript analysis, detailed feedback, and PDF report generation (v0.1). 16 | - **Agent2_Outlet_Fit**: (In Development) Tool for evaluating manuscript fit with target journals/conferences. 17 | 18 | ## Current Status 19 | 20 | ### Active Tools 21 | - **Agent1_Peer_Review**: ✅ v0.1 Ready for use! 22 | - Comprehensive manuscript analysis with specialized agents 23 | - Detailed feedback on sections, scientific rigor, and writing quality (including quality control loops) 24 | - JSON output with actionable recommendations 25 | - PDF report generation 26 | - [📄 Detailed Documentation and Key Areas for Contribution](https://github.com/robertjakob/rigorous/blob/main/Agent1_Peer_Review/README.md) 27 | 28 | ### In Development 29 | - **Agent2_Outlet_Fit**: 🚧 In Development 30 | - Core functionality being implemented 31 | - Integration with Agent1_Peer_Review in progress 32 | - Testing and validation ongoing 33 | - [🛠️ Development Plan](https://github.com/robertjakob/rigorous/blob/main/Agent2_Outlet_Fit/README.md) 34 | 35 | ### Future Modules and Ideas 36 | - **Embedding-based similarity analysis** (by [@andjar](https://github.com/andjar)): Use embeddings (as in [*The landscape of biomedical research*](https://github.com/berenslab/pubmed-landscape)) to compare a paper’s abstract with existing literature. This could help surface uncited but relevant work and suggest suitable journals based on similarity clusters. 37 | - Support for Drafting Reviewer Reponses. 38 | - Feedback on Research Proposals and Protocols. 39 | - AI-enabled document creation tool ("Cursor for Papers"). 40 | 41 | ## Requirements 42 | 43 | - Python 3.7+ 44 | - OpenAI API key (the system can be adapted to alternative LLMs, including locally hosted ones) 45 | - PDF manuscripts to analyze 46 | - Dependencies listed in each tool's requirements.txt 47 | 48 | ## Contributing 49 | 50 | Contributions are welcome! Please feel free to submit a Pull Request. 51 | 52 | ## Citation 53 | 54 | If you use the Rigorous AI Reviewer in your research or project, please cite: 55 | 56 | ```bibtex 57 | @software{rigorous_ai_reviewer2025, 58 | author = {Jakob, Robert and O'Sullivan, Kevin}, 59 | title = {Rigorous AI Reviewer: Enabling AI for Scientific Manuscript Analysis}, 60 | year = {2025}, 61 | publisher = {GitHub}, 62 | url = {https://github.com/robertjakob/rigorous} 63 | } 64 | ``` 65 | 66 |
67 |
68 |
71 | Follow Robert
72 |
73 |
74 |
75 |
76 |
77 |
78 |
81 | Follow Kevin
82 |
83 |
84 |
85 |
88 | Made with ❤️ in Zurich 89 |
90 | -------------------------------------------------------------------------------- /Agent2_Outlet_Fit/README.md: -------------------------------------------------------------------------------- 1 | # Agent2_Outlet_Fit 2 | 3 | > **Note:** This module is currently in active development. It will help reviewers evaluate manuscripts against specific journal/conference criteria and support desk rejection decisions. 4 | 5 | ## Purpose 6 | 7 | This Agent is designed to: 8 | - Evaluate manuscript fit with target journals/conferences 9 | - Support journals/conferences in (faster) desk rejection decisions 10 | - Enable researchers to pre-check manuscripts before submission 11 | 12 | ## Status 13 | 14 | 🚧 **In Development** 15 | - Core functionality being implemented 16 | - Integration with Agent1_Peer_Review in progress 17 | - Testing and validation ongoing 18 | 19 | ## Contributing 20 | 21 | This project is open source under the MIT License. We welcome contributions from the community to help improve the AI Reviewer system. Please feel free to submit issues, pull requests, or suggestions for improvements. 22 | 23 | ## GAMEPLAN 24 | 25 | ## 🎯 INPUTS: 26 | - journal_query: A string representing a journal, e.g., "I want to publish at NPJ Digital Medicine" found in context folder 27 | - manuscript_pdf: A PDF academic manuscript to be evaluated found in manuscripts folder 28 | 29 | --- 30 | 31 | ## FUNCTIONAL LAYERS & AGENT SPECIFICATIONS: 32 | 33 | 34 | ### 1. OUTLET RESEARCH AGENTS 35 | Goal: Automatically extract journal-specific publishing criteria from online sources. 36 | 37 | **Agents:** 38 | - PolicyCrawlerAgent: Scrapes official submission guidelines, formatting, ethics, and referencing requirements. 39 | - ScopeAnalyzerAgent: Analyzes the journal's aims and scope to determine topical fit. 40 | - EditorialBehaviorAgent: Uses recent articles (titles, abstracts) to infer preferred methodologies and topics. 41 | - LanguageStyleAgent: Learns linguistic norms (hedging, tone, formality) from past published texts. 42 | - ImpactNoveltyAgent: Extracts what kinds of novelty or significance are expected. 43 | - ReviewerExpectationAgent: Simulates or extracts typical reviewer priorities (optional). 44 | 45 | --- 46 | 47 | ### 2. CRITERIA SYNTHESIS AGENTS 48 | Goal: Convert raw data into structured, weighted publishing criteria. 49 | 50 | **Agents:** 51 | - CriteriaGeneratorAgent: Translates scraped data into JSON/YAML schemas for validation. 52 | - CriteriaWeightingAgent: Assigns priorities or must-have/optional tags to criteria. 53 | - RiskHeuristicAgent: Estimates desk-rejection risk based on missing or weak components. 54 | 55 | --- 56 | 57 | ### 3. MANUSCRIPT EVALUATION AGENTS 58 | Goal: Assess the manuscript against journal-specific requirements. 59 | 60 | **Agents:** 61 | - PDFParserAgent: Extracts and segments text from the manuscript PDF. 62 | - SectionValidatorAgent: Verifies section presence, structure, and ordering. 63 | - ScopeFitAgent: Checks if manuscript topic aligns with journal scope (via semantic similarity). 64 | - LanguageConformityAgent: Assesses tone and style match with outlet norms. 65 | - ReferenceStyleCheckerAgent: Verifies correct citation and formatting style. 66 | - OverallFitSummaryAgent: Outputs a summary of compliance, risks, and improvement suggestions. 67 | 68 | --- 69 | 70 | ## 🧱 ARCHITECTURE: 71 | Use LangChain or CrewAI to orchestrate agents. 72 | 73 | Each agent should: 74 | - Be modular and reusable 75 | - Accept clearly defined input/output types 76 | - Use tools such as: 77 | - Browser-Use, Playwright, BeautifulSoup → web scraping 78 | - FAISS, OpenAI Embeddings → semantic matching 79 | - PyMuPDF or GROBID → PDF parsing 80 | - LLM API → reasoning and language evaluation 81 | 82 | --- 83 | 84 | ## ✅ OUTPUT: 85 | A JSON report that includes: 86 | - ✔️ Fulfilled requirements 87 | - ❌ Missing elements 88 | - 📈 Desk rejection likelihood (1-5 scale) 89 | - ✍️ Specific suggestions to better fit the journal 90 | 91 | --- 92 | 93 | ## GOAL: 94 | Build a multiagent pipeline that automatically reverse-engineers a target outlet's expectations and assesses a manuscript's fit. The tool serves three key purposes: 95 | 96 | 1. **For Reviewers**: Streamline the review process by automatically checking manuscripts against journal/conference criteria 97 | 2. **For Journals/Conferences**: Support faster desk rejection decisions by providing automated preliminary screening and fast feedback to authors 98 | 3. **For Researchers**: Enable pre-submission self-assessment to identify potential issues before formal submission 99 | 100 | This comprehensive approach aims to reduce desk rejection risk, improve submission strategy, and make the peer review process faster and more efficient for all stakeholders. 101 | -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S2_abstract_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class AbstractAgentS2(BaseReviewerAgent): 7 | """Agent responsible for evaluating the abstract of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S2_Abstract_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_abstract(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the abstract of the manuscript.""" 16 | prompt = f"""Analyze the following abstract for quality and completeness. Focus on: 17 | 1. Structure and organization 18 | 2. Content completeness 19 | 3. Clarity and readability 20 | 4. Methodology description 21 | 5. Results presentation 22 | 6. Conclusion strength 23 | 7. Scientific writing standards 24 | 8. Field-specific requirements 25 | 9. Impact communication 26 | 10. Technical accuracy 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Structure: Organization, flow, section presence 30 | - Content: Completeness, accuracy, technical details 31 | - Clarity: Language, readability, technical terms 32 | - Standards: Scientific writing, field conventions 33 | - Impact: Significance, implications, contributions 34 | 35 | Text to analyze: {text} 36 | Research type: {research_type} 37 | 38 | Provide a detailed analysis in the following JSON format: 39 | {{ 40 | "score": int, # Single comprehensive score (1-5) 41 | 42 | "critical_remarks": [{{ 43 | "category": str, # "structure", "content", "clarity", "standards", "impact" 44 | "location": str, # Section reference 45 | "issue": str, # Detailed description of the issue 46 | "severity": str, # "high", "medium", "low" 47 | "impact": str # How this affects manuscript quality 48 | }}], 49 | 50 | "improvement_suggestions": [{{ 51 | "original_text": str, # The problematic text 52 | "improved_version": str, # AI-generated improvement 53 | "explanation": str, # Why this improvement helps 54 | "location": str, # Where to apply this change 55 | "category": str, # "structure", "content", "clarity", "standards", "impact" 56 | "focus": str # "organization", "completeness", "readability", "methodology", "results", "conclusion" 57 | }}], 58 | 59 | "detailed_feedback": {{ 60 | "structure_analysis": str, # Detailed paragraph about abstract structure 61 | "content_analysis": str, # Detailed paragraph about content completeness 62 | "clarity_assessment": str, # Detailed paragraph about readability 63 | "standards_compliance": str, # Detailed paragraph about scientific standards 64 | "impact_evaluation": str # Detailed paragraph about significance 65 | }}, 66 | 67 | "summary": str # Overall assessment paragraph 68 | }} 69 | 70 | Important: Generate at least 5-10 improvement suggestions across different categories. 71 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the abstract. 72 | """ 73 | 74 | try: 75 | response = self.llm(prompt) 76 | analysis = json.loads(response) 77 | return analysis 78 | except Exception as e: 79 | return self._generate_error_report(f"Error analyzing abstract: {str(e)}") 80 | 81 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 82 | """Generates a structured error report.""" 83 | return { 84 | "score": 0, 85 | "critical_remarks": [], 86 | "improvement_suggestions": [], 87 | "detailed_feedback": { 88 | "structure_analysis": "", 89 | "content_analysis": "", 90 | "clarity_assessment": "", 91 | "standards_compliance": "", 92 | "impact_evaluation": "" 93 | }, 94 | "summary": f"Error in analysis: {error_message}", 95 | "error": True 96 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/R1_originality_contribution_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class OriginalityContributionAgent(BaseReviewerAgent): 7 | """Agent responsible for assessing research novelty and unique contributions.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "R1_Originality_Contribution_Agent" 12 | self.category = "Scientific Rigor" 13 | 14 | def analyze_originality_contribution(self, text: str, field_context: Dict[str, Any]) -> Dict[str, Any]: 15 | """Analyzes the originality and contribution of the research.""" 16 | prompt = f"""Analyze the following text for originality and contribution to the field. Focus on: 17 | 1. Novelty of the research approach 18 | 2. Unique contributions to the field 19 | 3. Verification of stated novelty claims 20 | 4. Comparison with existing literature 21 | 5. Advancement of knowledge 22 | 23 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 24 | - Abstract: Clarity of novelty statement, contribution highlights 25 | - Introduction: Research gap identification, novelty claims 26 | - Literature Review: Comparison with existing work, gap analysis 27 | - Methodology: Novel approach description, innovation details 28 | - Results: Contribution presentation, advancement demonstration 29 | - Discussion: Impact assessment, future implications 30 | - Conclusion: Contribution summary, field advancement 31 | 32 | Text to analyze: {text} 33 | Field context: {json.dumps(field_context, indent=2)} 34 | 35 | Provide a detailed analysis in the following JSON format: 36 | {{ 37 | "originality_contribution_score": int, # Single comprehensive score (1-5) 38 | 39 | "critical_remarks": [{{ 40 | "category": str, # "novelty", "contribution", "verification", "comparison", "advancement" 41 | "location": str, # Section/paragraph reference 42 | "issue": str, # Detailed description of the issue 43 | "severity": str, # "high", "medium", "low" 44 | "impact": str # How this affects the research validity 45 | }}], 46 | 47 | "improvement_suggestions": [{{ 48 | "original_text": str, # The problematic text 49 | "improved_version": str, # AI-generated improvement 50 | "explanation": str, # Why this improvement helps 51 | "location": str, # Where to apply this change 52 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion" 53 | "focus": str # "novelty", "contribution", "verification", "comparison", "advancement" 54 | }}], 55 | 56 | "detailed_feedback": {{ 57 | "novelty_assessment": str, # Detailed paragraph about research novelty 58 | "contribution_analysis": str, # Detailed paragraph about contributions 59 | "verification_status": str, # Detailed paragraph about novelty claims 60 | "comparative_analysis": str, # Detailed paragraph about literature comparison 61 | "advancement_evaluation": str # Detailed paragraph about knowledge advancement 62 | }}, 63 | 64 | "summary": str # Overall assessment paragraph 65 | }} 66 | 67 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 68 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the research. 69 | """ 70 | 71 | try: 72 | response = self.llm(prompt) 73 | analysis = json.loads(response) 74 | return analysis 75 | except Exception as e: 76 | return self._generate_error_report(f"Error analyzing originality and contribution: {str(e)}") 77 | 78 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 79 | """Generates a structured error report.""" 80 | return { 81 | "originality_contribution_score": 0, 82 | "critical_remarks": [], 83 | "improvement_suggestions": [], 84 | "detailed_feedback": { 85 | "novelty_assessment": "", 86 | "contribution_analysis": "", 87 | "verification_status": "", 88 | "comparative_analysis": "", 89 | "advancement_evaluation": "" 90 | }, 91 | "summary": f"Error in analysis: {error_message}", 92 | "error": True 93 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S9_references_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class ReferencesAgentS9(BaseReviewerAgent): 7 | """Agent responsible for evaluating the references of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S9_References_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_references(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the references of the manuscript.""" 16 | prompt = f"""Analyze the reference list (bibliography) provided at the end of the manuscript. Focus exclusively on the reference list, not in-text citations. Assess: 17 | 1. Completeness of reference details (authors, title, journal, year, etc.) 18 | 2. Consistency and correctness of reference formatting 19 | 3. Relevance and recency of sources 20 | 4. Diversity of sources (journals, books, etc.) 21 | 5. Organization and ordering of the reference list 22 | 6. Adherence to the required style guide for the reference list 23 | 7. Cross-reference accuracy (do all references correspond to actual entries in the list?) 24 | 25 | For each aspect, provide at least 2-3 improvement suggestions. Consider these categories: 26 | - Completeness: Are all necessary details present for each reference? 27 | - Format: Is the reference list formatted consistently and according to the required style? 28 | - Quality: Are the sources relevant, recent, and diverse? 29 | - Organization: Is the reference list well-organized and correctly ordered? 30 | 31 | Text to analyze: {text} 32 | Research type: {research_type} 33 | 34 | Provide a detailed analysis in the following JSON format: 35 | {{ 36 | "score": int, # Single comprehensive score (1-5) 37 | # 1 = Poor: Major issues that significantly impact quality 38 | # 2 = Below Average: Several notable issues that need attention 39 | # 3 = Average: Some issues but generally acceptable 40 | # 4 = Good: Minor issues that don't significantly impact quality 41 | # 5 = Excellent: Very few or no issues, high quality 42 | "critical_remarks": [{{ 43 | "category": str, # "completeness", "format", "quality", "organization" 44 | "location": str, # Reference number or section 45 | "issue": str, # Detailed description of the issue 46 | "severity": str, # "high", "medium", "low" 47 | "impact": str # How this affects manuscript quality 48 | }}], 49 | "improvement_suggestions": [{{ 50 | "original_text": str, # The problematic reference 51 | "improved_version": str, # AI-generated improvement 52 | "explanation": str, # Why this improvement helps 53 | "location": str, # Where to apply this change 54 | "category": str, # "completeness", "format", "quality", "organization" 55 | "focus": str # "reference", "format", "style", "relevance", "recency", "diversity" 56 | }}], 57 | "detailed_feedback": {{ 58 | "completeness_analysis": str, # Detailed paragraph about reference completeness 59 | "format_analysis": str, # Detailed paragraph about format consistency 60 | "quality_analysis": str, # Detailed paragraph about source quality 61 | "organization_analysis": str # Detailed paragraph about reference organization 62 | }}, 63 | "summary": str # Overall assessment paragraph 64 | }} 65 | 66 | Focus on 3-5 highest-impact improvements that would significantly enhance the research value. 67 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the reference list. 68 | """ 69 | 70 | try: 71 | response = self.llm(prompt) 72 | analysis = json.loads(response) 73 | return analysis 74 | except Exception as e: 75 | return self._generate_error_report(f"Error analyzing references: {str(e)}") 76 | 77 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 78 | """Generates a structured error report.""" 79 | return { 80 | "score": 0, 81 | "critical_remarks": [], 82 | "improvement_suggestions": [], 83 | "detailed_feedback": { 84 | "completeness_analysis": "", 85 | "format_analysis": "", 86 | "quality_analysis": "", 87 | "organization_analysis": "" 88 | }, 89 | "summary": f"Error in analysis: {error_message}", 90 | "error": True 91 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S5_methodology_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class MethodologyAgentS5(BaseReviewerAgent): 7 | """Agent responsible for evaluating the methodology of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S5_Methodology_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_methodology(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the methodology of the manuscript.""" 16 | prompt = f"""Analyze the following methodology for quality and completeness. Focus on: 17 | 1. Research design 18 | 2. Data collection 19 | 3. Sampling approach 20 | 4. Instrumentation 21 | 5. Procedures 22 | 6. Analysis methods 23 | 7. Validity measures 24 | 8. Reliability assessment 25 | 9. Ethical considerations 26 | 10. Limitations handling 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Design: Approach, framework, rationale 30 | - Methods: Techniques, procedures, tools 31 | - Analysis: Statistical methods, qualitative approaches 32 | - Quality: Validity, reliability, rigor 33 | - Ethics: Consent, approval, considerations 34 | 35 | Text to analyze: {text} 36 | Research type: {research_type} 37 | 38 | Provide a detailed analysis in the following JSON format: 39 | {{ 40 | "score": int, # Single comprehensive score (1-5) 41 | # IMPORTANT: The score MUST be between 1 and 5, where: 42 | # 1 = Poor: Major issues that significantly impact quality 43 | # 2 = Below Average: Several notable issues that need attention 44 | # 3 = Average: Some issues but generally acceptable 45 | # 4 = Good: Minor issues that don't significantly impact quality 46 | # 5 = Excellent: Very few or no issues, high quality 47 | 48 | "critical_remarks": [{{ 49 | "category": str, # "design", "methods", "analysis", "quality", "ethics" 50 | "location": str, # Section reference 51 | "issue": str, # Detailed description of the issue 52 | "severity": str, # "high", "medium", "low" 53 | "impact": str # How this affects manuscript quality 54 | }}], 55 | 56 | "improvement_suggestions": [{{ 57 | "original_text": str, # The problematic text 58 | "improved_version": str, # AI-generated improvement 59 | "explanation": str, # Why this improvement helps 60 | "location": str, # Where to apply this change 61 | "category": str, # "design", "methods", "analysis", "quality", "ethics" 62 | "focus": str # "approach", "techniques", "procedures", "validity", "reliability" 63 | }}], 64 | 65 | "detailed_feedback": {{ 66 | "design_analysis": str, # Detailed paragraph about research design 67 | "methods_assessment": str, # Detailed paragraph about methodology 68 | "analysis_evaluation": str, # Detailed paragraph about analysis approach 69 | "quality_review": str, # Detailed paragraph about validity and reliability 70 | "ethics_compliance": str # Detailed paragraph about ethical considerations 71 | }}, 72 | 73 | "summary": str # Overall assessment paragraph 74 | }} 75 | 76 | Important: Generate at least 5-10 improvement suggestions across different categories. 77 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the methodology. 78 | """ 79 | 80 | try: 81 | response = self.llm(prompt) 82 | analysis = json.loads(response) 83 | return analysis 84 | except Exception as e: 85 | return self._generate_error_report(f"Error analyzing methodology: {str(e)}") 86 | 87 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 88 | """Generates a structured error report.""" 89 | return { 90 | "score": 0, 91 | "critical_remarks": [], 92 | "improvement_suggestions": [], 93 | "detailed_feedback": { 94 | "design_analysis": "", 95 | "methods_assessment": "", 96 | "analysis_evaluation": "", 97 | "quality_review": "", 98 | "ethics_compliance": "" 99 | }, 100 | "summary": f"Error in analysis: {error_message}", 101 | "error": True 102 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S3_introduction_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class IntroductionAgentS3(BaseReviewerAgent): 7 | """Agent responsible for evaluating the introduction of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S3_Introduction_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_introduction(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the introduction of the manuscript.""" 16 | prompt = f"""Analyze the following introduction for quality and effectiveness. Focus on: 17 | 1. Background context 18 | 2. Problem statement 19 | 3. Research gap identification 20 | 4. Objectives clarity 21 | 5. Significance justification 22 | 6. Literature integration 23 | 7. Flow and organization 24 | 8. Technical accuracy 25 | 9. Research scope 26 | 10. Hypothesis/questions 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Context: Background, field overview 30 | - Problem: Issue identification, gap analysis 31 | - Objectives: Goals, research questions 32 | - Significance: Impact, contribution 33 | - Structure: Organization, flow 34 | 35 | Text to analyze: {text} 36 | Research type: {research_type} 37 | 38 | Provide a detailed analysis in the following JSON format: 39 | {{ 40 | "score": int, # Single comprehensive score (1-5) 41 | # IMPORTANT: The score MUST be between 1 and 5, where: 42 | # 1 = Poor: Major issues that significantly impact quality 43 | # 2 = Below Average: Several notable issues that need attention 44 | # 3 = Average: Some issues but generally acceptable 45 | # 4 = Good: Minor issues that don't significantly impact quality 46 | # 5 = Excellent: Very few or no issues, high quality 47 | 48 | "critical_remarks": [{{ 49 | "category": str, # "context", "problem", "objectives", "significance", "structure" 50 | "location": str, # Section reference 51 | "issue": str, # Detailed description of the issue 52 | "severity": str, # "high", "medium", "low" 53 | "impact": str # How this affects manuscript quality 54 | }}], 55 | 56 | "improvement_suggestions": [{{ 57 | "original_text": str, # The problematic text 58 | "improved_version": str, # AI-generated improvement 59 | "explanation": str, # Why this improvement helps 60 | "location": str, # Where to apply this change 61 | "category": str, # "context", "problem", "objectives", "significance", "structure" 62 | "focus": str # "background", "problem", "gap", "objectives", "significance", "flow" 63 | }}], 64 | 65 | "detailed_feedback": {{ 66 | "context_analysis": str, # Detailed paragraph about background 67 | "problem_analysis": str, # Detailed paragraph about problem statement 68 | "objectives_analysis": str, # Detailed paragraph about research goals 69 | "significance_assessment": str, # Detailed paragraph about impact 70 | "structure_evaluation": str # Detailed paragraph about organization 71 | }}, 72 | 73 | "summary": str # Overall assessment paragraph 74 | }} 75 | 76 | Important: Generate at least 5-10 improvement suggestions across different categories. 77 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the introduction. 78 | """ 79 | 80 | try: 81 | response = self.llm(prompt) 82 | analysis = json.loads(response) 83 | return analysis 84 | except Exception as e: 85 | return self._generate_error_report(f"Error analyzing introduction: {str(e)}") 86 | 87 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 88 | """Generates a structured error report.""" 89 | return { 90 | "score": 0, 91 | "critical_remarks": [], 92 | "improvement_suggestions": [], 93 | "detailed_feedback": { 94 | "context_analysis": "", 95 | "problem_analysis": "", 96 | "objectives_analysis": "", 97 | "significance_assessment": "", 98 | "structure_evaluation": "" 99 | }, 100 | "summary": f"Error in analysis: {error_message}", 101 | "error": True 102 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S4_literature_review_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class LiteratureReviewAgentS4(BaseReviewerAgent): 7 | """Agent responsible for evaluating the literature review of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S4_Literature_Review_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_literature_review(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the literature review of the manuscript.""" 16 | prompt = f"""Analyze the following literature review for quality and comprehensiveness. Focus on: 17 | 1. Coverage breadth 18 | 2. Historical context 19 | 3. Current state 20 | 4. Critical analysis 21 | 5. Gap identification 22 | 6. Theoretical framework 23 | 7. Methodological review 24 | 8. Citation quality 25 | 9. Organization logic 26 | 10. Synthesis depth 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Coverage: Breadth, depth, relevance 30 | - Analysis: Critical thinking, synthesis 31 | - Structure: Organization, flow 32 | - Citations: Quality, recency 33 | - Integration: Connection to research 34 | 35 | Text to analyze: {text} 36 | Research type: {research_type} 37 | 38 | Provide a detailed analysis in the following JSON format: 39 | {{ 40 | "score": int, # Single comprehensive score (1-5) 41 | # IMPORTANT: The score MUST be between 1 and 5, where: 42 | # 1 = Poor: Major issues that significantly impact quality 43 | # 2 = Below Average: Several notable issues that need attention 44 | # 3 = Average: Some issues but generally acceptable 45 | # 4 = Good: Minor issues that don't significantly impact quality 46 | # 5 = Excellent: Very few or no issues, high quality 47 | 48 | "critical_remarks": [{{ 49 | "category": str, # "coverage", "analysis", "structure", "citations", "integration" 50 | "location": str, # Section reference 51 | "issue": str, # Detailed description of the issue 52 | "severity": str, # "high", "medium", "low" 53 | "impact": str # How this affects manuscript quality 54 | }}], 55 | 56 | "improvement_suggestions": [{{ 57 | "original_text": str, # The problematic text 58 | "improved_version": str, # AI-generated improvement 59 | "explanation": str, # Why this improvement helps 60 | "location": str, # Where to apply this change 61 | "category": str, # "coverage", "analysis", "structure", "citations", "integration" 62 | "focus": str # "breadth", "depth", "synthesis", "organization", "relevance" 63 | }}], 64 | 65 | "detailed_feedback": {{ 66 | "coverage_analysis": str, # Detailed paragraph about literature coverage 67 | "analysis_quality": str, # Detailed paragraph about critical analysis 68 | "structure_evaluation": str, # Detailed paragraph about organization 69 | "citation_assessment": str, # Detailed paragraph about citation quality 70 | "integration_review": str # Detailed paragraph about research connection 71 | }}, 72 | 73 | "summary": str # Overall assessment paragraph 74 | }} 75 | 76 | Important: Generate at least 5-10 improvement suggestions across different categories. 77 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the literature review. 78 | """ 79 | 80 | try: 81 | response = self.llm(prompt) 82 | analysis = json.loads(response) 83 | return analysis 84 | except Exception as e: 85 | return self._generate_error_report(f"Error analyzing literature review: {str(e)}") 86 | 87 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 88 | """Generates a structured error report.""" 89 | return { 90 | "score": 0, 91 | "critical_remarks": [], 92 | "improvement_suggestions": [], 93 | "detailed_feedback": { 94 | "coverage_analysis": "", 95 | "analysis_quality": "", 96 | "structure_evaluation": "", 97 | "citation_assessment": "", 98 | "integration_review": "" 99 | }, 100 | "summary": f"Error in analysis: {error_message}", 101 | "error": True 102 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S6_results_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class ResultsAgentS6(BaseReviewerAgent): 7 | """Agent responsible for evaluating the results of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S6_Results_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_results(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the results of the manuscript.""" 16 | prompt = f"""Analyze the following results for quality and presentation. Focus on: 17 | 1. Data presentation 18 | 2. Statistical analysis 19 | 3. Figure/table quality 20 | 4. Result interpretation 21 | 5. Significance reporting 22 | 6. Effect sizes 23 | 7. Confidence intervals 24 | 8. Statistical tests 25 | 9. Data visualization 26 | 10. Result organization 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Presentation: Clarity, organization, visualization 30 | - Analysis: Statistical methods, significance 31 | - Interpretation: Meaning, implications 32 | - Quality: Accuracy, completeness 33 | - Impact: Significance, effect sizes 34 | 35 | Text to analyze: {text} 36 | Research type: {research_type} 37 | 38 | Provide a detailed analysis in the following JSON format: 39 | {{ 40 | "score": int, # Single comprehensive score (1-5) 41 | # IMPORTANT: The score MUST be between 1 and 5, where: 42 | # 1 = Poor: Major issues that significantly impact quality 43 | # 2 = Below Average: Several notable issues that need attention 44 | # 3 = Average: Some issues but generally acceptable 45 | # 4 = Good: Minor issues that don't significantly impact quality 46 | # 5 = Excellent: Very few or no issues, high quality 47 | 48 | "critical_remarks": [{{ 49 | "category": str, # "presentation", "analysis", "interpretation", "quality", "impact" 50 | "location": str, # Section reference 51 | "issue": str, # Detailed description of the issue 52 | "severity": str, # "high", "medium", "low" 53 | "impact": str # How this affects manuscript quality 54 | }}], 55 | 56 | "improvement_suggestions": [{{ 57 | "original_text": str, # The problematic text 58 | "improved_version": str, # AI-generated improvement 59 | "explanation": str, # Why this improvement helps 60 | "location": str, # Where to apply this change 61 | "category": str, # "presentation", "analysis", "interpretation", "quality", "impact" 62 | "focus": str # "clarity", "statistics", "visualization", "interpretation", "significance" 63 | }}], 64 | 65 | "detailed_feedback": {{ 66 | "presentation_analysis": str, # Detailed paragraph about data presentation 67 | "analysis_quality": str, # Detailed paragraph about statistical analysis 68 | "interpretation_review": str, # Detailed paragraph about result interpretation 69 | "visualization_assessment": str, # Detailed paragraph about figures/tables 70 | "significance_evaluation": str # Detailed paragraph about statistical significance 71 | }}, 72 | 73 | "summary": str # Overall assessment paragraph 74 | }} 75 | 76 | Important: Generate at least 5-10 improvement suggestions across different categories. 77 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the results section. 78 | """ 79 | 80 | try: 81 | response = self.llm(prompt) 82 | analysis = json.loads(response) 83 | return analysis 84 | except Exception as e: 85 | return self._generate_error_report(f"Error analyzing results: {str(e)}") 86 | 87 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 88 | """Generates a structured error report.""" 89 | return { 90 | "score": 0, 91 | "critical_remarks": [], 92 | "improvement_suggestions": [], 93 | "detailed_feedback": { 94 | "presentation_analysis": "", 95 | "analysis_quality": "", 96 | "interpretation_review": "", 97 | "visualization_assessment": "", 98 | "significance_evaluation": "" 99 | }, 100 | "summary": f"Error in analysis: {error_message}", 101 | "error": True 102 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S8_conclusion_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class ConclusionAgentS8(BaseReviewerAgent): 7 | """Agent responsible for evaluating the conclusion of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S8_Conclusion_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_conclusion(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the conclusion of the manuscript.""" 16 | prompt = f"""Analyze the following conclusion for quality and completeness. Focus on: 17 | 1. Support from results 18 | 2. Research objective fulfillment 19 | 3. Key findings summary 20 | 4. Contribution clarity 21 | 5. Practical implications 22 | 6. Theoretical implications 23 | 7. Future research suggestions 24 | 8. Final statement strength 25 | 9. Avoidance of new information 26 | 10. Conciseness and clarity 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Support: Evidence-based, result alignment 30 | - Objectives: Fulfillment, contribution clarity 31 | - Implications: Practical, theoretical, future directions 32 | - Presentation: Clarity, conciseness, strength 33 | 34 | Text to analyze: {text} 35 | Research type: {research_type} 36 | 37 | Provide a detailed analysis in the following JSON format: 38 | {{ 39 | "score": int, # Single comprehensive score (1-5) 40 | # IMPORTANT: The score MUST be between 1 and 5, where: 41 | # 1 = Poor: Major issues that significantly impact quality 42 | # 2 = Below Average: Several notable issues that need attention 43 | # 3 = Average: Some issues but generally acceptable 44 | # 4 = Good: Minor issues that don't significantly impact quality 45 | # 5 = Excellent: Very few or no issues, high quality 46 | 47 | "critical_remarks": [{{ 48 | "category": str, # "support", "objectives", "implications", "presentation" 49 | "location": str, # Section reference 50 | "issue": str, # Detailed description of the issue 51 | "severity": str, # "high", "medium", "low" 52 | "impact": str # How this affects manuscript quality 53 | }}], 54 | 55 | "improvement_suggestions": [{{ 56 | "original_text": str, # The problematic text 57 | "improved_version": str, # AI-generated improvement 58 | "explanation": str, # Why this improvement helps 59 | "location": str, # Where to apply this change 60 | "category": str, # "support", "objectives", "implications", "presentation" 61 | "focus": str # "evidence", "fulfillment", "clarity", "implications", "future_directions", "strength" 62 | }}], 63 | 64 | "detailed_feedback": {{ 65 | "support_analysis": str, # Detailed paragraph about result support 66 | "objective_fulfillment": str, # Detailed paragraph about research objective fulfillment 67 | "implications_analysis": str, # Detailed paragraph about implications 68 | "presentation_analysis": str, # Detailed paragraph about presentation quality 69 | "contribution_analysis": str # Detailed paragraph about contribution clarity 70 | }}, 71 | 72 | "summary": str # Overall assessment paragraph 73 | }} 74 | 75 | Important: Generate at least 5-10 improvement suggestions across different categories. 76 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the conclusion. 77 | """ 78 | 79 | try: 80 | response = self.llm(prompt) 81 | analysis = json.loads(response) 82 | return analysis 83 | except Exception as e: 84 | return self._generate_error_report(f"Error analyzing conclusion: {str(e)}") 85 | 86 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 87 | """Generates a structured error report.""" 88 | return { 89 | "score": 0, 90 | "critical_remarks": [], 91 | "improvement_suggestions": [], 92 | "detailed_feedback": { 93 | "support_analysis": "", 94 | "objective_fulfillment": "", 95 | "implications_analysis": "", 96 | "presentation_analysis": "", 97 | "contribution_analysis": "" 98 | }, 99 | "summary": f"Error in analysis: {error_message}", 100 | "error": True 101 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/core/report_template.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from datetime import datetime 4 | 5 | class ReportTemplate: 6 | """Template for generating standardized review reports.""" 7 | 8 | def __init__(self): 9 | """Initialize the report template.""" 10 | self.template = { 11 | "metadata": { 12 | "timestamp": datetime.now().isoformat(), 13 | "agent_name": "", 14 | "category": "", 15 | "model_used": "", 16 | "version": "1.0" 17 | }, 18 | "analysis": { 19 | "overall_score": 0, 20 | "critical_remarks": [], 21 | "improvement_suggestions": [], 22 | "detailed_feedback": {}, 23 | "summary": "" 24 | } 25 | } 26 | 27 | def generate_report(self, agent_name: str, category: str, model: str, 28 | analysis_results: Dict[str, Any], output_path: str) -> None: 29 | """ 30 | Generate a standardized review report. 31 | 32 | Args: 33 | agent_name (str): Name of the agent 34 | category (str): Category of the agent 35 | model (str): Model used for analysis 36 | analysis_results (Dict[str, Any]): Results of the analysis 37 | output_path (str): Path to save the report 38 | """ 39 | report = self.template.copy() 40 | report["metadata"].update({ 41 | "agent_name": agent_name, 42 | "category": category, 43 | "model_used": model 44 | }) 45 | report["analysis"].update(analysis_results) 46 | 47 | with open(output_path, 'w') as f: 48 | f.write(f"Review Report - {agent_name}\n") 49 | f.write("=" * (len(agent_name) + 13) + "\n\n") 50 | 51 | f.write("Metadata\n") 52 | f.write("-" * 8 + "\n") 53 | f.write(json.dumps(report["metadata"], indent=2)) 54 | f.write("\n\n") 55 | 56 | f.write("Analysis Results\n") 57 | f.write("-" * 16 + "\n") 58 | f.write(json.dumps(report["analysis"], indent=2)) 59 | f.write("\n") 60 | 61 | @staticmethod 62 | def create_template(agent_name: str, section_name: str) -> Dict[str, Any]: 63 | """Create a standardized report template. 64 | 65 | Args: 66 | agent_name (str): Name of the reviewer agent 67 | section_name (str): Name of the section being reviewed 68 | 69 | Returns: 70 | Dict[str, Any]: Standardized report template 71 | """ 72 | return { 73 | "agent_name": agent_name, 74 | "section_name": section_name, 75 | "timestamp": datetime.now().isoformat(), 76 | "score": None, # 1-5 score 77 | "remarks": [], # List of issues, questions, or observations 78 | "concrete_suggestions": [], # Actionable steps for each remark 79 | "automated_suggestions": [], # AI-generated improvements 80 | "section_specific_analysis": {} # Additional section-specific analysis 81 | } 82 | 83 | @staticmethod 84 | def save_report(report: Dict[str, Any], output_dir: str) -> str: 85 | """Save the report to a text file. 86 | 87 | Args: 88 | report (Dict[str, Any]): The report to save 89 | output_dir (str): Directory to save the report in 90 | 91 | Returns: 92 | str: Path to the saved report file 93 | """ 94 | timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") 95 | filename = f"{report['agent_name'].lower().replace(' ', '_')}_{timestamp}.txt" 96 | filepath = f"{output_dir}/{filename}" 97 | 98 | with open(filepath, 'w') as f: 99 | f.write(f"Review Report - {report['agent_name']}\n") 100 | f.write(f"Section: {report['section_name']}\n") 101 | f.write(f"Timestamp: {report['timestamp']}\n\n") 102 | 103 | f.write(f"Score: {report['score']}/5\n\n") 104 | 105 | f.write("Remarks:\n") 106 | for remark in report['remarks']: 107 | f.write(f"- {remark}\n") 108 | f.write("\n") 109 | 110 | f.write("Concrete Suggestions:\n") 111 | for suggestion in report['concrete_suggestions']: 112 | f.write(f"- {suggestion}\n") 113 | f.write("\n") 114 | 115 | f.write("Automated Suggestions:\n") 116 | for suggestion in report['automated_suggestions']: 117 | f.write(f"- {suggestion}\n") 118 | f.write("\n") 119 | 120 | if report['section_specific_analysis']: 121 | f.write("Section-Specific Analysis:\n") 122 | f.write(json.dumps(report['section_specific_analysis'], indent=2)) 123 | 124 | return filepath -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S7_discussion_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class DiscussionAgentS7(BaseReviewerAgent): 7 | """Agent responsible for evaluating the discussion of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S7_Discussion_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_discussion(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the discussion of the manuscript.""" 16 | prompt = f"""Analyze the following discussion for quality and completeness. Focus on: 17 | 1. Result interpretation 18 | 2. Literature comparison 19 | 3. Limitation analysis 20 | 4. Future work 21 | 5. Practical implications 22 | 6. Theoretical contributions 23 | 7. Research gap addressing 24 | 8. Methodology reflection 25 | 9. Result significance 26 | 10. Conclusion alignment 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Interpretation: Result analysis, significance 30 | - Context: Literature comparison, research gaps 31 | - Reflection: Limitations, future work 32 | - Impact: Practical implications, theoretical contributions 33 | - Quality: Completeness, coherence 34 | 35 | Text to analyze: {text} 36 | Research type: {research_type} 37 | 38 | Provide a detailed analysis in the following JSON format: 39 | {{ 40 | "score": int, # Single comprehensive score (1-5) 41 | # IMPORTANT: The score MUST be between 1 and 5, where: 42 | # 1 = Poor: Major issues that significantly impact quality 43 | # 2 = Below Average: Several notable issues that need attention 44 | # 3 = Average: Some issues but generally acceptable 45 | # 4 = Good: Minor issues that don't significantly impact quality 46 | # 5 = Excellent: Very few or no issues, high quality 47 | 48 | "critical_remarks": [{{ 49 | "category": str, # "interpretation", "context", "reflection", "impact", "quality" 50 | "location": str, # Section reference 51 | "issue": str, # Detailed description of the issue 52 | "severity": str, # "high", "medium", "low" 53 | "impact": str # How this affects manuscript quality 54 | }}], 55 | 56 | "improvement_suggestions": [{{ 57 | "original_text": str, # The problematic text 58 | "improved_version": str, # AI-generated improvement 59 | "explanation": str, # Why this improvement helps 60 | "location": str, # Where to apply this change 61 | "category": str, # "interpretation", "context", "reflection", "impact", "quality" 62 | "focus": str # "interpretation", "comparison", "limitations", "implications", "significance" 63 | }}], 64 | 65 | "detailed_feedback": {{ 66 | "interpretation_analysis": str, # Detailed paragraph about result interpretation 67 | "context_review": str, # Detailed paragraph about literature comparison 68 | "reflection_assessment": str, # Detailed paragraph about limitations/future work 69 | "impact_evaluation": str, # Detailed paragraph about practical/theoretical impact 70 | "quality_analysis": str # Detailed paragraph about overall discussion quality 71 | }}, 72 | 73 | "summary": str # Overall assessment paragraph 74 | }} 75 | 76 | Important: Generate at least 5-10 improvement suggestions across different categories. 77 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the discussion. 78 | """ 79 | 80 | try: 81 | response = self.llm(prompt) 82 | analysis = json.loads(response) 83 | return analysis 84 | except Exception as e: 85 | return self._generate_error_report(f"Error analyzing discussion: {str(e)}") 86 | 87 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 88 | """Generates a structured error report.""" 89 | return { 90 | "score": 0, 91 | "critical_remarks": [], 92 | "improvement_suggestions": [], 93 | "detailed_feedback": { 94 | "interpretation_analysis": "", 95 | "context_review": "", 96 | "reflection_assessment": "", 97 | "impact_evaluation": "", 98 | "quality_analysis": "" 99 | }, 100 | "summary": f"Error in analysis: {error_message}", 101 | "error": True 102 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/R2_impact_significance_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class ImpactSignificanceAgent(BaseReviewerAgent): 7 | """Agent responsible for evaluating research impact and significance.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "R2_Impact_Significance_Agent" 12 | self.category = "Scientific Rigor" 13 | 14 | def analyze_impact_significance(self, text: str, field_context: Dict[str, Any]) -> Dict[str, Any]: 15 | """Analyzes the impact and significance of the research.""" 16 | prompt = f"""Analyze the following text for impact and significance. Focus on: 17 | 1. Potential influence on the field 18 | 2. Broader implications of findings 19 | 3. Influence on future research 20 | 4. Practical applications 21 | 5. Policy implications 22 | 23 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 24 | - Abstract: Impact statement, significance highlights 25 | - Introduction: Research importance, field relevance 26 | - Literature Review: Gap impact, field advancement 27 | - Methodology: Innovation potential, scalability 28 | - Results: Key findings impact, practical value 29 | - Discussion: Broader implications, future directions 30 | - Conclusion: Impact summary, application potential 31 | 32 | Text to analyze: {text} 33 | Field context: {json.dumps(field_context, indent=2)} 34 | 35 | Provide a detailed analysis in the following JSON format: 36 | {{ 37 | "impact_significance_score": int, # Single comprehensive score (1-5) 38 | # IMPORTANT: The score MUST be between 1 and 5, where: 39 | # 1 = Poor: Major issues that significantly impact quality 40 | # 2 = Below Average: Several notable issues that need attention 41 | # 3 = Average: Some issues but generally acceptable 42 | # 4 = Good: Minor issues that don't significantly impact quality 43 | # 5 = Excellent: Very few or no issues, high quality 44 | 45 | "critical_remarks": [{{ 46 | "category": str, # "field_influence", "implications", "future_research", "applications", "policy" 47 | "location": str, # Section/paragraph reference 48 | "issue": str, # Detailed description of the issue 49 | "severity": str, # "high", "medium", "low" 50 | "impact": str # How this affects the research significance 51 | }}], 52 | 53 | "improvement_suggestions": [{{ 54 | "original_text": str, # The problematic text 55 | "improved_version": str, # AI-generated improvement 56 | "explanation": str, # Why this improvement helps 57 | "location": str, # Where to apply this change 58 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion" 59 | "focus": str # "field_influence", "implications", "future_research", "applications", "policy" 60 | }}], 61 | 62 | "detailed_feedback": {{ 63 | "field_influence": str, # Detailed paragraph about field influence 64 | "broader_implications": str, # Detailed paragraph about implications 65 | "future_research_impact": str, # Detailed paragraph about future research 66 | "practical_applications": str, # Detailed paragraph about applications 67 | "policy_implications": str # Detailed paragraph about policy 68 | }}, 69 | 70 | "summary": str # Overall assessment paragraph 71 | }} 72 | 73 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 74 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the research impact and significance. 75 | """ 76 | 77 | try: 78 | response = self.llm(prompt) 79 | analysis = json.loads(response) 80 | return analysis 81 | except Exception as e: 82 | return self._generate_error_report(f"Error analyzing impact and significance: {str(e)}") 83 | 84 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 85 | """Generates a structured error report.""" 86 | return { 87 | "impact_significance_score": 0, 88 | "critical_remarks": [], 89 | "improvement_suggestions": [], 90 | "detailed_feedback": { 91 | "field_influence": "", 92 | "broader_implications": "", 93 | "future_research_impact": "", 94 | "practical_applications": "", 95 | "policy_implications": "" 96 | }, 97 | "summary": f"Error in analysis: {error_message}", 98 | "error": True 99 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S10_supplementary_materials_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class SupplementaryMaterialsAgentS10(BaseReviewerAgent): 7 | """Agent responsible for evaluating the supplementary materials of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S10_Supplementary_Materials_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_supplementary_materials(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the supplementary materials of the manuscript.""" 16 | prompt = f"""Analyze the following supplementary materials for quality and completeness. Focus on: 17 | 1. Relevance to main text 18 | 2. Clarity of presentation 19 | 3. Consistency with main text 20 | 4. Completeness of information 21 | 5. Organization and structure 22 | 6. Data presentation 23 | 7. Methodological details 24 | 8. Additional results 25 | 9. Reference to main text 26 | 10. Accessibility and usability 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Relevance: Connection to main text, value addition 30 | - Clarity: Presentation, organization, accessibility 31 | - Consistency: Alignment with main text, coherence 32 | - Completeness: Information detail, methodological thoroughness 33 | 34 | Text to analyze: {text} 35 | Research type: {research_type} 36 | 37 | Provide a detailed analysis in the following JSON format: 38 | {{ 39 | "score": int, # Single comprehensive score (1-5) 40 | # IMPORTANT: The score MUST be between 1 and 5, where: 41 | # 1 = Poor: Major issues that significantly impact quality 42 | # 2 = Below Average: Several notable issues that need attention 43 | # 3 = Average: Some issues but generally acceptable 44 | # 4 = Good: Minor issues that don't significantly impact quality 45 | # 5 = Excellent: Very few or no issues, high quality 46 | 47 | "critical_remarks": [{{ 48 | "category": str, # "relevance", "clarity", "consistency", "completeness" 49 | "location": str, # Section reference 50 | "issue": str, # Detailed description of the issue 51 | "severity": str, # "high", "medium", "low" 52 | "impact": str # How this affects manuscript quality 53 | }}], 54 | 55 | "improvement_suggestions": [{{ 56 | "original_text": str, # The problematic text 57 | "improved_version": str, # AI-generated improvement 58 | "explanation": str, # Why this improvement helps 59 | "location": str, # Where to apply this change 60 | "category": str, # "relevance", "clarity", "consistency", "completeness" 61 | "focus": str # "connection", "presentation", "organization", "accessibility", "alignment", "coherence", "detail", "thoroughness" 62 | }}], 63 | 64 | "detailed_feedback": {{ 65 | "relevance_analysis": str, # Detailed paragraph about relevance to main text 66 | "clarity_analysis": str, # Detailed paragraph about presentation clarity 67 | "consistency_analysis": str, # Detailed paragraph about consistency with main text 68 | "completeness_analysis": str, # Detailed paragraph about information completeness 69 | "organization_analysis": str # Detailed paragraph about structure and organization 70 | }}, 71 | 72 | "summary": str # Overall assessment paragraph 73 | }} 74 | 75 | Important: Generate at least 5-10 improvement suggestions across different categories. 76 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the supplementary materials. 77 | """ 78 | 79 | try: 80 | response = self.llm(prompt) 81 | analysis = json.loads(response) 82 | return analysis 83 | except Exception as e: 84 | return self._generate_error_report(f"Error analyzing supplementary materials: {str(e)}") 85 | 86 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 87 | """Generates a structured error report.""" 88 | return { 89 | "score": 0, 90 | "critical_remarks": [], 91 | "improvement_suggestions": [], 92 | "detailed_feedback": { 93 | "relevance_analysis": "", 94 | "clarity_analysis": "", 95 | "consistency_analysis": "", 96 | "completeness_analysis": "", 97 | "organization_analysis": "" 98 | }, 99 | "summary": f"Error in analysis: {error_message}", 100 | "error": True 101 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/R3_ethics_compliance_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class EthicsComplianceAgent(BaseReviewerAgent): 7 | """Agent responsible for reviewing ethical considerations and research standards.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "R3_Ethics_Compliance_Agent" 12 | self.category = "Scientific Rigor" 13 | 14 | def analyze_ethics_compliance(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes ethical considerations and compliance with research standards.""" 16 | prompt = f"""Analyze the following text for ethical considerations and research standards compliance. Focus on: 17 | 1. Conflicts of interest 18 | 2. Data privacy and protection 19 | 3. Informed consent procedures 20 | 4. Research integrity 21 | 5. Adherence to ethical guidelines 22 | 23 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 24 | - Abstract: Ethical statement, compliance summary 25 | - Introduction: Research ethics framework, compliance approach 26 | - Methodology: Ethical procedures, consent process 27 | - Data Collection: Privacy measures, protection protocols 28 | - Analysis: Integrity measures, bias prevention 29 | - Results: Ethical presentation, privacy maintenance 30 | - Discussion: Ethical implications, compliance reflection 31 | - Conclusion: Ethical summary, compliance assurance 32 | 33 | Text to analyze: {text} 34 | Research type: {research_type} 35 | 36 | Provide a detailed analysis in the following JSON format: 37 | {{ 38 | "ethics_compliance_score": int, # Single comprehensive score (1-5) 39 | # IMPORTANT: The score MUST be between 1 and 5, where: 40 | # 1 = Poor: Major issues that significantly impact quality 41 | # 2 = Below Average: Several notable issues that need attention 42 | # 3 = Average: Some issues but generally acceptable 43 | # 4 = Good: Minor issues that don't significantly impact quality 44 | # 5 = Excellent: Very few or no issues, high quality 45 | 46 | "critical_remarks": [{{ 47 | "category": str, # "conflicts", "privacy", "consent", "integrity", "guidelines" 48 | "location": str, # Section/paragraph reference 49 | "issue": str, # Detailed description of the issue 50 | "severity": str, # "high", "medium", "low" 51 | "impact": str # How this affects ethical compliance 52 | }}], 53 | 54 | "improvement_suggestions": [{{ 55 | "original_text": str, # The problematic text 56 | "improved_version": str, # AI-generated improvement 57 | "explanation": str, # Why this improvement helps 58 | "location": str, # Where to apply this change 59 | "category": str, # "abstract", "introduction", "methodology", "data_collection", "analysis", "results", "discussion", "conclusion" 60 | "focus": str # "conflicts", "privacy", "consent", "integrity", "guidelines" 61 | }}], 62 | 63 | "detailed_feedback": {{ 64 | "conflicts_assessment": str, # Detailed paragraph about conflicts of interest 65 | "privacy_compliance": str, # Detailed paragraph about data privacy 66 | "consent_procedures": str, # Detailed paragraph about informed consent 67 | "research_integrity": str, # Detailed paragraph about research integrity 68 | "guidelines_adherence": str # Detailed paragraph about ethical guidelines 69 | }}, 70 | 71 | "summary": str # Overall assessment paragraph 72 | }} 73 | 74 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 75 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances ethical compliance and research standards. 76 | """ 77 | 78 | try: 79 | response = self.llm(prompt) 80 | analysis = json.loads(response) 81 | return analysis 82 | except Exception as e: 83 | return self._generate_error_report(f"Error analyzing ethics and compliance: {str(e)}") 84 | 85 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 86 | """Generates a structured error report.""" 87 | return { 88 | "ethics_compliance_score": 0, 89 | "critical_remarks": [], 90 | "improvement_suggestions": [], 91 | "detailed_feedback": { 92 | "conflicts_assessment": "", 93 | "privacy_compliance": "", 94 | "consent_procedures": "", 95 | "research_integrity": "", 96 | "guidelines_adherence": "" 97 | }, 98 | "summary": f"Error in analysis: {error_message}", 99 | "error": True 100 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/R4_data_code_availability_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class DataCodeAvailabilityAgent(BaseReviewerAgent): 7 | """Agent responsible for evaluating data and code availability.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "R4_Data_Code_Availability_Agent" 12 | self.category = "Scientific Rigor" 13 | 14 | def analyze_data_code_availability(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes data and code availability.""" 16 | prompt = f"""Analyze the following text for data and code availability. Focus on: 17 | 1. Data sharing practices 18 | 2. Code repository availability 19 | 3. Documentation completeness 20 | 4. Access restrictions justification 21 | 5. Reproducibility support 22 | 23 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 24 | - Abstract: Data/code availability statement 25 | - Introduction: Research transparency approach 26 | - Methodology: Data collection details, code implementation 27 | - Data Description: Dataset structure, access methods 28 | - Code Documentation: Implementation details, usage instructions 29 | - Results: Data presentation, code results 30 | - Discussion: Reproducibility considerations 31 | - Conclusion: Availability summary, access information 32 | 33 | Text to analyze: {text} 34 | Research type: {research_type} 35 | 36 | Provide a detailed analysis in the following JSON format: 37 | {{ 38 | "data_code_availability_score": int, # Single comprehensive score (1-5) 39 | # IMPORTANT: The score MUST be between 1 and 5, where: 40 | # 1 = Poor: Major issues that significantly impact quality 41 | # 2 = Below Average: Several notable issues that need attention 42 | # 3 = Average: Some issues but generally acceptable 43 | # 4 = Good: Minor issues that don't significantly impact quality 44 | # 5 = Excellent: Very few or no issues, high quality 45 | 46 | "critical_remarks": [{{ 47 | "category": str, # "data_sharing", "code_availability", "documentation", "restrictions", "reproducibility" 48 | "location": str, # Section/paragraph reference 49 | "issue": str, # Detailed description of the issue 50 | "severity": str, # "high", "medium", "low" 51 | "impact": str # How this affects research transparency 52 | }}], 53 | 54 | "improvement_suggestions": [{{ 55 | "original_text": str, # The problematic text 56 | "improved_version": str, # AI-generated improvement 57 | "explanation": str, # Why this improvement helps 58 | "location": str, # Where to apply this change 59 | "category": str, # "abstract", "introduction", "methodology", "data_description", "code_documentation", "results", "discussion", "conclusion" 60 | "focus": str # "data_sharing", "code_availability", "documentation", "restrictions", "reproducibility" 61 | }}], 62 | 63 | "detailed_feedback": {{ 64 | "data_sharing_assessment": str, # Detailed paragraph about data sharing 65 | "code_availability": str, # Detailed paragraph about code availability 66 | "documentation_completeness": str, # Detailed paragraph about documentation 67 | "restrictions_justification": str, # Detailed paragraph about access restrictions 68 | "reproducibility_support": str # Detailed paragraph about reproducibility 69 | }}, 70 | 71 | "summary": str # Overall assessment paragraph 72 | }} 73 | 74 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 75 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances data and code availability. 76 | """ 77 | 78 | try: 79 | response = self.llm(prompt) 80 | analysis = json.loads(response) 81 | return analysis 82 | except Exception as e: 83 | return self._generate_error_report(f"Error analyzing data and code availability: {str(e)}") 84 | 85 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 86 | """Generates a structured error report.""" 87 | return { 88 | "data_code_availability_score": 0, 89 | "critical_remarks": [], 90 | "improvement_suggestions": [], 91 | "detailed_feedback": { 92 | "data_sharing_assessment": "", 93 | "code_availability": "", 94 | "documentation_completeness": "", 95 | "restrictions_justification": "", 96 | "reproducibility_support": "" 97 | }, 98 | "summary": f"Error in analysis: {error_message}", 99 | "error": True 100 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/writing/W6_citation_formatting_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class CitationFormattingAgent(BaseReviewerAgent): 7 | """Agent responsible for evaluating citation formatting and consistency.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "W6_Citation_Formatting_Agent" 12 | self.category = "Writing and Presentation" 13 | 14 | def analyze_citation_formatting(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the formatting and consistency of citations in the text.""" 16 | prompt = f"""Analyze the following manuscript text for in-text citation formatting, style, and consistency. Focus exclusively on in-text citations (not the reference list). Assess: 17 | 1. In-text citation style (e.g., APA, Vancouver, Harvard, etc.) 18 | 2. Consistency of in-text citation formatting throughout the manuscript 19 | 3. Correct placement and ordering of in-text citations 20 | 4. Proper use of et al., author names, and years (if applicable) 21 | 5. Consistency in citation delimiters (parentheses, brackets, superscripts, etc.) 22 | 6. Cross-reference accuracy (do all in-text citations correspond to entries in the reference list?) 23 | 7. Handling of multiple citations in a single location 24 | 8. Citation of figures, tables, and supplementary materials (if applicable) 25 | 9. Adherence to the required style guide for in-text citations 26 | 27 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 28 | - In-text format: Is the citation style consistent and correct? 29 | - Placement: Are citations placed appropriately in the text? 30 | - Style consistency: Are delimiters, author lists, and years handled consistently? 31 | - Cross-reference: Do all in-text citations match the reference list? 32 | 33 | Text to analyze: {text} 34 | Research type: {research_type} 35 | 36 | Provide a detailed analysis in the following JSON format: 37 | {{ 38 | "citation_formatting_score": int, # Single comprehensive score (1-5) 39 | # 1 = Poor: Major issues that significantly impact citation quality 40 | # 2 = Below Average: Several notable issues that need attention 41 | # 3 = Average: Some issues but generally acceptable 42 | # 4 = Good: Minor issues that don't significantly impact quality 43 | # 5 = Excellent: Very few or no issues, high quality 44 | "critical_remarks": [{{ 45 | "category": str, # "in_text_format", "placement", "style_consistency", "cross_reference" 46 | "location": str, # Section/paragraph reference 47 | "issue": str, # Detailed description of the issue 48 | "severity": str, # "high", "medium", "low" 49 | "impact": str # How this affects citation quality 50 | }}], 51 | "improvement_suggestions": [{{ 52 | "original_text": str, # The problematic in-text citation 53 | "improved_version": str, # AI-generated improvement 54 | "explanation": str, # Why this improvement helps 55 | "location": str, # Where to apply this change 56 | "category": str, # "in_text_format", "placement", "style_consistency", "cross_reference" 57 | "focus": str # "in_text_format", "placement", "style_consistency", "cross_reference" 58 | }}], 59 | "detailed_feedback": {{ 60 | "in_text_citation_format": str, # Detailed paragraph about in-text citation format 61 | "placement_analysis": str, # Detailed paragraph about citation placement 62 | "style_consistency_analysis": str, # Detailed paragraph about style consistency 63 | "cross_reference_accuracy": str # Detailed paragraph about cross-reference accuracy 64 | }}, 65 | "summary": str # Overall assessment paragraph 66 | }} 67 | 68 | Important: Generate at least 5-10 improvement suggestions across different categories, focusing only on in-text citations. 69 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances in-text citation formatting and consistency. 70 | """ 71 | 72 | try: 73 | response = self.llm(prompt) 74 | analysis = json.loads(response) 75 | return analysis 76 | except Exception as e: 77 | return self._generate_error_report(f"Error analyzing citation formatting: {str(e)}") 78 | 79 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 80 | """Generates a structured error report.""" 81 | return { 82 | "citation_formatting_score": 0, 83 | "critical_remarks": [], 84 | "improvement_suggestions": [], 85 | "detailed_feedback": { 86 | "in_text_citation_format": "", 87 | "placement_analysis": "", 88 | "style_consistency_analysis": "", 89 | "cross_reference_accuracy": "" 90 | }, 91 | "summary": f"Error in analysis: {error_message}", 92 | "error": True 93 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/writing/W1_language_style_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class LanguageStyleAgent(BaseReviewerAgent): 7 | """Agent responsible for reviewing grammar, spelling, and punctuation.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "W1_Language_Style_Agent" 12 | self.category = "Writing and Presentation" 13 | 14 | def analyze_language_style(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes grammar, spelling, and punctuation in the text.""" 16 | prompt = f"""Analyze the following text for grammar, spelling, and punctuation issues. Focus on: 17 | 1. Grammar correctness 18 | 2. Spelling accuracy 19 | 3. Punctuation usage 20 | 4. Sentence structure 21 | 5. Verb tense consistency 22 | 6. Subject-verb agreement 23 | 7. Article usage 24 | 8. Preposition usage 25 | 9. Conjunction usage 26 | 10. Academic writing conventions 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Conciseness and clarity 30 | - Introduction: Academic tone and flow 31 | - Literature Review: Citation language 32 | - Methodology: Technical description 33 | - Results: Data presentation 34 | - Discussion: Argument structure 35 | - Conclusion: Summary language 36 | - References: Citation format 37 | 38 | Text to analyze: {text} 39 | Research type: {research_type} 40 | 41 | Provide a detailed analysis in the following JSON format: 42 | {{ 43 | "language_style_score": int, # Single comprehensive score (1-5) 44 | 45 | "critical_remarks": [{{ 46 | "category": str, # "grammar", "spelling", "punctuation", "sentence_structure", "verb_tense", "subject_verb", "articles", "prepositions", "conjunctions", "academic_conventions" 47 | "location": str, # Section/paragraph reference 48 | "issue": str, # Detailed description of the issue 49 | "severity": str, # "high", "medium", "low" 50 | "impact": str # How this affects readability 51 | }}], 52 | 53 | "improvement_suggestions": [{{ 54 | "original_text": str, # The problematic text 55 | "improved_version": str, # AI-generated improvement 56 | "explanation": str, # Why this improvement helps 57 | "location": str, # Where to apply this change 58 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion", "references" 59 | "focus": str # "grammar", "spelling", "punctuation", "sentence_structure", "verb_tense", "subject_verb", "articles", "prepositions", "conjunctions", "academic_conventions" 60 | }}], 61 | 62 | "detailed_feedback": {{ 63 | "grammar_correctness": str, # Detailed paragraph about grammar issues 64 | "spelling_accuracy": str, # Detailed paragraph about spelling issues 65 | "punctuation_usage": str, # Detailed paragraph about punctuation issues 66 | "sentence_structure": str, # Detailed paragraph about sentence structure 67 | "verb_tense_consistency": str, # Detailed paragraph about verb tense consistency 68 | "subject_verb_agreement": str, # Detailed paragraph about subject-verb agreement 69 | "article_usage": str, # Detailed paragraph about article usage 70 | "preposition_usage": str, # Detailed paragraph about preposition usage 71 | "conjunction_usage": str, # Detailed paragraph about conjunction usage 72 | "academic_conventions": str # Detailed paragraph about academic writing conventions 73 | }}, 74 | 75 | "summary": str # Overall assessment paragraph 76 | }} 77 | 78 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 79 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the language and style. 80 | """ 81 | 82 | try: 83 | response = self.llm(prompt) 84 | analysis = json.loads(response) 85 | return analysis 86 | except Exception as e: 87 | return self._generate_error_report(f"Error analyzing language style: {str(e)}") 88 | 89 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 90 | """Generates a structured error report.""" 91 | return { 92 | "language_style_score": 0, 93 | "critical_remarks": [], 94 | "improvement_suggestions": [], 95 | "detailed_feedback": { 96 | "grammar_correctness": "", 97 | "spelling_accuracy": "", 98 | "punctuation_usage": "", 99 | "sentence_structure": "", 100 | "verb_tense_consistency": "", 101 | "subject_verb_agreement": "", 102 | "article_usage": "", 103 | "preposition_usage": "", 104 | "conjunction_usage": "", 105 | "academic_conventions": "" 106 | }, 107 | "summary": f"Error in analysis: {error_message}", 108 | "error": True 109 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/section/S1_title_keywords_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class TitleKeywordsAgentS1(BaseReviewerAgent): 7 | """Agent responsible for evaluating the title and keywords of a manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "S1_Title_Keywords_Agent" 12 | self.category = "Section Review" 13 | 14 | def analyze_title_keywords(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the title and keywords of the manuscript.""" 16 | prompt = f"""Analyze the title and keywords section of the manuscript. Follow these steps: 17 | 18 | 1. FIRST, check if there is a dedicated "Keywords:" or "Keywords" section in the text. 19 | - Look for a line that starts with "Keywords:" or "Keywords" 20 | - If no such section is found, set has_keywords = false 21 | - If found, set has_keywords = true and extract the keywords 22 | 23 | 2. For the title analysis: 24 | - Analyze the current title considering ALL aspects simultaneously: 25 | * Clarity: Is it clear and understandable? 26 | * Accuracy: Does it accurately represent the content? 27 | * Impact: Does it capture attention and significance? 28 | * SEO: Is it optimized for search engines? 29 | * Standards: Does it follow field conventions? 30 | - Generate ONE comprehensive improvement suggestion that addresses all these aspects 31 | - The improved title should be the optimal balance of all these factors 32 | 33 | 3. For keywords analysis (ONLY if has_keywords = true): 34 | - Analyze relevance, coverage, and specificity 35 | - Provide improvement suggestions 36 | - Consider search engine optimization 37 | 38 | 4. If has_keywords = false: 39 | - Set all keyword-related fields to empty or null 40 | - Do not generate any keyword-related feedback 41 | - Do not make assumptions about keywords from other text 42 | 43 | Text to analyze: {text} 44 | Research type: {research_type} 45 | 46 | Provide a detailed analysis in the following JSON format: 47 | {{ 48 | "title_keywords_score": int, # Single comprehensive score (1-5) 49 | 50 | "critical_remarks": [{{ 51 | "category": str, # "title_clarity", "title_length", "keywords_relevance", "keywords_coverage", "guidelines", "discoverability" 52 | "location": str, # "Title" or "Keywords" 53 | "issue": str, # Detailed description of the issue 54 | "severity": str, # "high", "medium", "low" 55 | "impact": str # How this affects manuscript quality 56 | }}], 57 | 58 | "improvement_suggestions": [{{ 59 | "original_text": str, # The current title 60 | "improved_version": str, # ONE comprehensive improved title that balances all aspects 61 | "explanation": str, # Detailed explanation of how the improved title addresses clarity, accuracy, impact, SEO, and standards 62 | "location": str, # "Title" 63 | "category": str, # "title" 64 | "focus": str # "comprehensive_improvement" 65 | }}], 66 | 67 | "detailed_feedback": {{ 68 | "title_analysis": str, # Detailed paragraph about title quality 69 | "keywords_analysis": str, # "No keywords section found" if has_keywords = false 70 | "guidelines_compliance": str, # Detailed paragraph about field conventions 71 | "discoverability_assessment": str, # Detailed paragraph about search optimization 72 | "audience_alignment": str # Detailed paragraph about appeal and significance 73 | }}, 74 | 75 | "summary": str # Overall assessment paragraph 76 | }} 77 | 78 | Important: 79 | 1. ONLY analyze the title and keywords section 80 | 2. If no "Keywords:" or "Keywords" section is found: 81 | - Set keywords_analysis to "No keywords section found" 82 | - Do not include any keyword-related critical remarks 83 | - Do not include any keyword-related improvement suggestions 84 | - Do not make assumptions about keywords from other text 85 | 3. Generate ONE comprehensive title improvement that considers all aspects simultaneously 86 | 4. The title improvement should balance clarity, accuracy, impact, SEO, and standards 87 | 5. All locations should be either "Title" or "Keywords", never "Abstract" 88 | 6. Focus on improving discoverability and search optimization 89 | """ 90 | 91 | try: 92 | response = self.llm(prompt) 93 | analysis = json.loads(response) 94 | return analysis 95 | except Exception as e: 96 | return self._generate_error_report(f"Error analyzing title and keywords: {str(e)}") 97 | 98 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 99 | """Generates a structured error report.""" 100 | return { 101 | "title_keywords_score": 0, 102 | "critical_remarks": [], 103 | "improvement_suggestions": [], 104 | "detailed_feedback": { 105 | "title_analysis": "", 106 | "keywords_analysis": "", 107 | "guidelines_compliance": "", 108 | "discoverability_assessment": "", 109 | "audience_alignment": "" 110 | }, 111 | "summary": f"Error in analysis: {error_message}", 112 | "error": True 113 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/R7_consistency_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class ConsistencyAgent(BaseReviewerAgent): 7 | """Agent responsible for checking logical coherence across sections.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "R7_Consistency_Agent" 12 | self.category = "Scientific Rigor" 13 | 14 | def analyze_consistency(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes logical coherence across sections.""" 16 | prompt = f"""Analyze the following text for logical coherence and consistency across sections. Focus on: 17 | 1. Alignment between methods and results 18 | 2. Consistency between results and conclusions 19 | 3. Logical flow between sections 20 | 4. Terminology consistency 21 | 5. Hypothesis-testing alignment 22 | 6. Data interpretation consistency 23 | 7. Citation consistency 24 | 8. Figure-text alignment 25 | 9. Table-text alignment 26 | 10. Supplementary material consistency 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Consistency with main text 30 | - Introduction: Alignment with methodology 31 | - Literature Review: Citation consistency 32 | - Methodology: Methods-results alignment 33 | - Results: Results-conclusions alignment 34 | - Discussion: Interpretation consistency 35 | - Conclusion: Overall coherence 36 | - Figures/Tables: Text alignment 37 | - Supplementary: Main text consistency 38 | 39 | Text to analyze: {text} 40 | Research type: {research_type} 41 | 42 | Provide a detailed analysis in the following JSON format: 43 | {{ 44 | "consistency_score": int, # Single comprehensive score (1-5) 45 | 46 | "critical_remarks": [{{ 47 | "category": str, # "methods_results", "results_conclusions", "logical_flow", "terminology", "hypothesis", "interpretation", "citations", "figures", "tables", "supplementary" 48 | "location": str, # Section/paragraph reference 49 | "issue": str, # Detailed description of the issue 50 | "severity": str, # "high", "medium", "low" 51 | "impact": str # How this affects consistency 52 | }}], 53 | 54 | "improvement_suggestions": [{{ 55 | "original_text": str, # The problematic text 56 | "improved_version": str, # AI-generated improvement 57 | "explanation": str, # Why this improvement helps 58 | "location": str, # Where to apply this change 59 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion", "figures_tables", "supplementary" 60 | "focus": str # "methods_results", "results_conclusions", "logical_flow", "terminology", "hypothesis", "interpretation", "citations", "figures", "tables", "supplementary" 61 | }}], 62 | 63 | "detailed_feedback": {{ 64 | "methods_results_alignment": str, # Detailed paragraph about methods-results alignment 65 | "results_conclusions_alignment": str, # Detailed paragraph about results-conclusions alignment 66 | "logical_flow": str, # Detailed paragraph about logical flow 67 | "terminology_consistency": str, # Detailed paragraph about terminology consistency 68 | "hypothesis_testing": str, # Detailed paragraph about hypothesis-testing alignment 69 | "interpretation_consistency": str, # Detailed paragraph about interpretation consistency 70 | "citation_consistency": str, # Detailed paragraph about citation consistency 71 | "figure_text_alignment": str, # Detailed paragraph about figure-text alignment 72 | "table_text_alignment": str, # Detailed paragraph about table-text alignment 73 | "supplementary_consistency": str # Detailed paragraph about supplementary material consistency 74 | }}, 75 | 76 | "summary": str # Overall assessment paragraph 77 | }} 78 | 79 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 80 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances logical coherence and consistency. 81 | """ 82 | 83 | try: 84 | response = self.llm(prompt) 85 | analysis = json.loads(response) 86 | return analysis 87 | except Exception as e: 88 | return self._generate_error_report(f"Error analyzing consistency: {str(e)}") 89 | 90 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 91 | """Generates a structured error report.""" 92 | return { 93 | "consistency_score": 0, 94 | "critical_remarks": [], 95 | "improvement_suggestions": [], 96 | "detailed_feedback": { 97 | "methods_results_alignment": "", 98 | "results_conclusions_alignment": "", 99 | "logical_flow": "", 100 | "terminology_consistency": "", 101 | "hypothesis_testing": "", 102 | "interpretation_consistency": "", 103 | "citation_consistency": "", 104 | "figure_text_alignment": "", 105 | "table_text_alignment": "", 106 | "supplementary_consistency": "" 107 | }, 108 | "summary": f"Error in analysis: {error_message}", 109 | "error": True 110 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/writing/W3_clarity_conciseness_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class ClarityConcisenessAgent(BaseReviewerAgent): 7 | """Agent responsible for evaluating clarity and conciseness of the manuscript.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "W3_Clarity_Conciseness_Agent" 12 | self.category = "Writing and Presentation" 13 | 14 | def analyze_clarity_conciseness(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the clarity and conciseness of the text.""" 16 | prompt = f"""Analyze the following text for clarity and conciseness. Focus on: 17 | 1. Language simplicity 18 | 2. Jargon usage 19 | 3. Wordiness 20 | 4. Sentence length 21 | 5. Paragraph length 22 | 6. Active vs. passive voice 23 | 7. Redundancy 24 | 8. Ambiguity 25 | 9. Readability 26 | 10. Information density 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Key message clarity 30 | - Introduction: Background conciseness 31 | - Literature Review: Synthesis clarity 32 | - Methodology: Process description 33 | - Results: Finding presentation 34 | - Discussion: Argument clarity 35 | - Conclusion: Message conciseness 36 | - Technical Content: Jargon explanation 37 | 38 | Text to analyze: {text} 39 | Research type: {research_type} 40 | 41 | Provide a detailed analysis in the following JSON format: 42 | {{ 43 | "clarity_conciseness_score": int, # Single comprehensive score (1-5) 44 | # IMPORTANT: The score MUST be between 1 and 5, where: 45 | # 1 = Poor: Major issues that significantly impact quality 46 | # 2 = Below Average: Several notable issues that need attention 47 | # 3 = Average: Some issues but generally acceptable 48 | # 4 = Good: Minor issues that don't significantly impact quality 49 | # 5 = Excellent: Very few or no issues, high quality 50 | 51 | "critical_remarks": [{{ 52 | "category": str, # "language_simplicity", "jargon", "wordiness", "sentence_length", "paragraph_length", "voice", "redundancy", "ambiguity", "readability", "information_density" 53 | "location": str, # Section/paragraph reference 54 | "issue": str, # Detailed description of the issue 55 | "severity": str, # "high", "medium", "low" 56 | "impact": str # How this affects clarity 57 | }}], 58 | 59 | "improvement_suggestions": [{{ 60 | "original_text": str, # The problematic text 61 | "improved_version": str, # AI-generated improvement 62 | "explanation": str, # Why this improvement helps 63 | "location": str, # Where to apply this change 64 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion", "technical" 65 | "focus": str # "language_simplicity", "jargon", "wordiness", "sentence_length", "paragraph_length", "voice", "redundancy", "ambiguity", "readability", "information_density" 66 | }}], 67 | 68 | "detailed_feedback": {{ 69 | "language_simplicity": str, # Detailed paragraph about language simplicity 70 | "jargon_usage": str, # Detailed paragraph about jargon usage 71 | "wordiness": str, # Detailed paragraph about wordiness 72 | "sentence_length": str, # Detailed paragraph about sentence length 73 | "paragraph_length": str, # Detailed paragraph about paragraph length 74 | "active_passive_voice": str, # Detailed paragraph about active vs. passive voice 75 | "redundancy": str, # Detailed paragraph about redundancy 76 | "ambiguity": str, # Detailed paragraph about ambiguity 77 | "readability": str, # Detailed paragraph about readability 78 | "information_density": str # Detailed paragraph about information density 79 | }}, 80 | 81 | "summary": str # Overall assessment paragraph 82 | }} 83 | 84 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 85 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances clarity and conciseness. 86 | """ 87 | 88 | try: 89 | response = self.llm(prompt) 90 | analysis = json.loads(response) 91 | return analysis 92 | except Exception as e: 93 | return self._generate_error_report(f"Error analyzing clarity and conciseness: {str(e)}") 94 | 95 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 96 | """Generates a structured error report.""" 97 | return { 98 | "clarity_conciseness_score": 0, 99 | "critical_remarks": [], 100 | "improvement_suggestions": [], 101 | "detailed_feedback": { 102 | "language_simplicity": "", 103 | "jargon_usage": "", 104 | "wordiness": "", 105 | "sentence_length": "", 106 | "paragraph_length": "", 107 | "active_passive_voice": "", 108 | "redundancy": "", 109 | "ambiguity": "", 110 | "readability": "", 111 | "information_density": "" 112 | }, 113 | "summary": f"Error in analysis: {error_message}", 114 | "error": True 115 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/writing/W2_narrative_structure_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class NarrativeStructureAgent(BaseReviewerAgent): 7 | """Agent responsible for evaluating the overall flow, coherence, and logical organization of the paper.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "W2_Narrative_Structure_Agent" 12 | self.category = "Writing and Presentation" 13 | 14 | def analyze_narrative_structure(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the narrative flow and structural organization of the text.""" 16 | prompt = f"""Analyze the following text for narrative flow and structural organization. Focus on: 17 | 1. Overall narrative coherence 18 | 2. Logical progression of ideas 19 | 3. Section transitions 20 | 4. Paragraph organization 21 | 5. Topic sentence effectiveness 22 | 6. Supporting evidence integration 23 | 7. Conclusion alignment with introduction 24 | 8. Research question/hypothesis tracking 25 | 9. Visual element integration 26 | 10. Reader engagement 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Research narrative overview 30 | - Introduction: Research context and flow 31 | - Literature Review: Evidence synthesis 32 | - Methodology: Process description 33 | - Results: Finding presentation 34 | - Discussion: Argument development 35 | - Conclusion: Research story closure 36 | - Figures/Tables: Visual narrative 37 | 38 | Text to analyze: {text} 39 | Research type: {research_type} 40 | 41 | Provide a detailed analysis in the following JSON format: 42 | {{ 43 | "narrative_structure_score": int, # Single comprehensive score (1-5) 44 | 45 | "critical_remarks": [{{ 46 | "category": str, # "narrative_coherence", "logical_progression", "transitions", "paragraph_organization", "topic_sentences", "evidence_integration", "conclusion_alignment", "hypothesis_tracking", "visual_integration", "reader_engagement" 47 | "location": str, # Section/paragraph reference 48 | "issue": str, # Detailed description of the issue 49 | "severity": str, # "high", "medium", "low" 50 | "impact": str # How this affects the narrative 51 | }}], 52 | 53 | "improvement_suggestions": [{{ 54 | "original_text": str, # The problematic text 55 | "improved_version": str, # AI-generated improvement 56 | "explanation": str, # Why this improvement helps 57 | "location": str, # Where to apply this change 58 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion", "figures_tables" 59 | "focus": str # "narrative_coherence", "logical_progression", "transitions", "paragraph_organization", "topic_sentences", "evidence_integration", "conclusion_alignment", "hypothesis_tracking", "visual_integration", "reader_engagement" 60 | }}], 61 | 62 | "detailed_feedback": {{ 63 | "narrative_coherence": str, # Detailed paragraph about narrative coherence 64 | "logical_progression": str, # Detailed paragraph about logical progression 65 | "section_transitions": str, # Detailed paragraph about section transitions 66 | "paragraph_organization": str, # Detailed paragraph about paragraph organization 67 | "topic_sentence_effectiveness": str, # Detailed paragraph about topic sentence effectiveness 68 | "supporting_evidence_integration": str, # Detailed paragraph about supporting evidence integration 69 | "conclusion_alignment": str, # Detailed paragraph about conclusion alignment 70 | "hypothesis_tracking": str, # Detailed paragraph about hypothesis tracking 71 | "visual_element_integration": str, # Detailed paragraph about visual element integration 72 | "reader_engagement": str # Detailed paragraph about reader engagement 73 | }}, 74 | 75 | "summary": str # Overall assessment paragraph 76 | }} 77 | 78 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 79 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances the narrative structure. 80 | """ 81 | 82 | try: 83 | response = self.llm(prompt) 84 | analysis = json.loads(response) 85 | return analysis 86 | except Exception as e: 87 | return self._generate_error_report(f"Error analyzing narrative structure: {str(e)}") 88 | 89 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 90 | """Generates a structured error report.""" 91 | return { 92 | "narrative_structure_score": 0, 93 | "critical_remarks": [], 94 | "improvement_suggestions": [], 95 | "detailed_feedback": { 96 | "narrative_coherence": "", 97 | "logical_progression": "", 98 | "section_transitions": "", 99 | "paragraph_organization": "", 100 | "topic_sentence_effectiveness": "", 101 | "supporting_evidence_integration": "", 102 | "conclusion_alignment": "", 103 | "hypothesis_tracking": "", 104 | "visual_element_integration": "", 105 | "reader_engagement": "" 106 | }, 107 | "summary": f"Error in analysis: {error_message}", 108 | "error": True 109 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/writing/W7_target_audience_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class TargetAudienceAlignmentAgent(BaseReviewerAgent): 7 | """Agent responsible for evaluating writing style and formatting alignment with target audience.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "W7_Target_Audience_Alignment_Agent" 12 | self.category = "Writing and Presentation" 13 | 14 | def analyze_target_audience_alignment(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes how well the writing style and formatting align with the target audience.""" 16 | prompt = f"""Analyze the following text for target audience alignment and writing style appropriateness. Focus on: 17 | 1. Technical depth and complexity 18 | 2. Field-specific terminology usage 19 | 3. Writing style formality 20 | 4. Section organization 21 | 5. Visual element integration 22 | 6. Reference style and depth 23 | 7. Methodology description detail 24 | 8. Results presentation 25 | 9. Discussion depth 26 | 10. Conclusion format 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Conciseness and technical level 30 | - Introduction: Background depth 31 | - Literature Review: Reference depth 32 | - Methodology: Technical detail 33 | - Results: Data presentation 34 | - Discussion: Analysis depth 35 | - Conclusion: Summary style 36 | - Visual Elements: Integration and complexity 37 | 38 | Text to analyze: {text} 39 | Research type: {research_type} 40 | 41 | Provide a detailed analysis in the following JSON format: 42 | {{ 43 | "audience_alignment_score": int, # Single comprehensive score (1-5) 44 | # IMPORTANT: The score MUST be between 1 and 5, where: 45 | # 1 = Poor: Major issues that significantly impact quality 46 | # 2 = Below Average: Several notable issues that need attention 47 | # 3 = Average: Some issues but generally acceptable 48 | # 4 = Good: Minor issues that don't significantly impact quality 49 | # 5 = Excellent: Very few or no issues, high quality 50 | 51 | "critical_remarks": [{{ 52 | "category": str, # "technical_depth", "terminology", "formality", "organization", "visuals", "references", "methodology", "results", "discussion", "conclusion" 53 | "location": str, # Section/paragraph reference 54 | "issue": str, # Detailed description of the issue 55 | "severity": str, # "high", "medium", "low" 56 | "impact": str # How this affects audience engagement 57 | }}], 58 | 59 | "improvement_suggestions": [{{ 60 | "original_text": str, # The problematic text 61 | "improved_version": str, # AI-generated improvement 62 | "explanation": str, # Why this improvement helps 63 | "location": str, # Where to apply this change 64 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion", "visuals" 65 | "focus": str # "technical_depth", "terminology", "formality", "organization", "visuals", "references", "methodology", "results", "discussion", "conclusion" 66 | }}], 67 | 68 | "detailed_feedback": {{ 69 | "technical_depth": str, # Detailed paragraph about technical depth appropriateness 70 | "terminology_usage": str, # Detailed paragraph about field-specific terminology 71 | "writing_formality": str, # Detailed paragraph about writing style formality 72 | "section_organization": str, # Detailed paragraph about section organization 73 | "visual_integration": str, # Detailed paragraph about visual element integration 74 | "reference_style": str, # Detailed paragraph about reference style and depth 75 | "methodology_detail": str, # Detailed paragraph about methodology description 76 | "results_presentation": str, # Detailed paragraph about results presentation 77 | "discussion_depth": str, # Detailed paragraph about discussion depth 78 | "conclusion_format": str # Detailed paragraph about conclusion format 79 | }}, 80 | 81 | "summary": str # Overall assessment paragraph 82 | }} 83 | 84 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 85 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances audience alignment. 86 | """ 87 | 88 | try: 89 | response = self.llm(prompt) 90 | analysis = json.loads(response) 91 | return analysis 92 | except Exception as e: 93 | return self._generate_error_report(f"Error analyzing target audience alignment: {str(e)}") 94 | 95 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 96 | """Generates a structured error report.""" 97 | return { 98 | "audience_alignment_score": 0, 99 | "critical_remarks": [], 100 | "improvement_suggestions": [], 101 | "detailed_feedback": { 102 | "technical_depth": "", 103 | "terminology_usage": "", 104 | "writing_formality": "", 105 | "section_organization": "", 106 | "visual_integration": "", 107 | "reference_style": "", 108 | "methodology_detail": "", 109 | "results_presentation": "", 110 | "discussion_depth": "", 111 | "conclusion_format": "" 112 | }, 113 | "summary": f"Error in analysis: {error_message}", 114 | "error": True 115 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/R5_statistical_rigor_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class StatisticalRigorAgent(BaseReviewerAgent): 7 | """Agent responsible for evaluating statistical methods appropriateness and correctness.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "R5_Statistical_Rigor_Agent" 12 | self.category = "Scientific Rigor" 13 | 14 | def analyze_statistical_rigor(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes statistical methods appropriateness and correctness.""" 16 | prompt = f"""Analyze the following text for statistical methods appropriateness and correctness. Focus on: 17 | 1. Statistical test selection 18 | 2. Assumption verification 19 | 3. Sample size justification 20 | 4. Multiple comparison handling 21 | 5. Effect size reporting 22 | 6. Confidence intervals 23 | 7. P-value interpretation 24 | 8. Statistical power 25 | 9. Missing data handling 26 | 10. Outlier treatment 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Statistical approach summary 30 | - Introduction: Statistical framework overview 31 | - Methodology: Statistical methods description 32 | - Data Preparation: Assumption checks, data cleaning 33 | - Analysis: Statistical test implementation 34 | - Results: Statistical findings presentation 35 | - Discussion: Statistical interpretation 36 | - Conclusion: Statistical significance summary 37 | 38 | Text to analyze: {text} 39 | Research type: {research_type} 40 | 41 | Provide a detailed analysis in the following JSON format: 42 | {{ 43 | "statistical_rigor_score": int, # Single comprehensive score (1-5) 44 | # IMPORTANT: The score MUST be between 1 and 5, where: 45 | # 1 = Poor: Major issues that significantly impact quality 46 | # 2 = Below Average: Several notable issues that need attention 47 | # 3 = Average: Some issues but generally acceptable 48 | # 4 = Good: Minor issues that don't significantly impact quality 49 | # 5 = Excellent: Very few or no issues, high quality 50 | 51 | "critical_remarks": [{{ 52 | "category": str, # "test_selection", "assumptions", "sample_size", "multiple_comparisons", "effect_size", "confidence_intervals", "p_value", "power", "missing_data", "outliers" 53 | "location": str, # Section/paragraph reference 54 | "issue": str, # Detailed description of the issue 55 | "severity": str, # "high", "medium", "low" 56 | "impact": str # How this affects statistical validity 57 | }}], 58 | 59 | "improvement_suggestions": [{{ 60 | "original_text": str, # The problematic text 61 | "improved_version": str, # AI-generated improvement 62 | "explanation": str, # Why this improvement helps 63 | "location": str, # Where to apply this change 64 | "category": str, # "abstract", "introduction", "methodology", "data_preparation", "analysis", "results", "discussion", "conclusion" 65 | "focus": str # "test_selection", "assumptions", "sample_size", "multiple_comparisons", "effect_size", "confidence_intervals", "p_value", "power", "missing_data", "outliers" 66 | }}], 67 | 68 | "detailed_feedback": {{ 69 | "test_selection": str, # Detailed paragraph about statistical test selection 70 | "assumption_verification": str, # Detailed paragraph about assumption verification 71 | "sample_size_justification": str, # Detailed paragraph about sample size 72 | "multiple_comparison_handling": str, # Detailed paragraph about multiple comparisons 73 | "effect_size_reporting": str, # Detailed paragraph about effect size 74 | "confidence_intervals": str, # Detailed paragraph about confidence intervals 75 | "p_value_interpretation": str, # Detailed paragraph about p-value interpretation 76 | "statistical_power": str, # Detailed paragraph about statistical power 77 | "missing_data_handling": str, # Detailed paragraph about missing data 78 | "outlier_treatment": str # Detailed paragraph about outlier treatment 79 | }}, 80 | 81 | "summary": str # Overall assessment paragraph 82 | }} 83 | 84 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 85 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances statistical rigor. 86 | """ 87 | 88 | try: 89 | response = self.llm(prompt) 90 | analysis = json.loads(response) 91 | return analysis 92 | except Exception as e: 93 | return self._generate_error_report(f"Error analyzing statistical rigor: {str(e)}") 94 | 95 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 96 | """Generates a structured error report.""" 97 | return { 98 | "statistical_rigor_score": 0, 99 | "critical_remarks": [], 100 | "improvement_suggestions": [], 101 | "detailed_feedback": { 102 | "test_selection": "", 103 | "assumption_verification": "", 104 | "sample_size_justification": "", 105 | "multiple_comparison_handling": "", 106 | "effect_size_reporting": "", 107 | "confidence_intervals": "", 108 | "p_value_interpretation": "", 109 | "statistical_power": "", 110 | "missing_data_handling": "", 111 | "outlier_treatment": "" 112 | }, 113 | "summary": f"Error in analysis: {error_message}", 114 | "error": True 115 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/writing/W4_terminology_consistency_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class TerminologyConsistencyAgent(BaseReviewerAgent): 7 | """Agent responsible for ensuring consistent use of terms, notations, and acronyms.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "W4_Terminology_Consistency_Agent" 12 | self.category = "Writing and Presentation" 13 | 14 | def analyze_terminology_consistency(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the consistency of terminology, notations, and acronyms in the text.""" 16 | prompt = f"""Analyze the following text for terminology consistency. Focus on: 17 | 1. Term usage consistency 18 | 2. Notation consistency 19 | 3. Acronym usage and definition 20 | 4. Variable naming consistency 21 | 5. Unit notation consistency 22 | 6. Abbreviation consistency 23 | 7. Technical term consistency 24 | 8. Field-specific terminology 25 | 9. Cross-reference consistency 26 | 10. Definition consistency 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Term introduction 30 | - Introduction: Field terminology 31 | - Literature Review: Citation terms 32 | - Methodology: Technical terms 33 | - Results: Variable names 34 | - Discussion: Term usage 35 | - Conclusion: Term consistency 36 | - Equations: Notation style 37 | 38 | Text to analyze: {text} 39 | Research type: {research_type} 40 | 41 | Provide a detailed analysis in the following JSON format: 42 | {{ 43 | "terminology_consistency_score": int, # Single comprehensive score (1-5) 44 | # IMPORTANT: The score MUST be between 1 and 5, where: 45 | # 1 = Poor: Major issues that significantly impact quality 46 | # 2 = Below Average: Several notable issues that need attention 47 | # 3 = Average: Some issues but generally acceptable 48 | # 4 = Good: Minor issues that don't significantly impact quality 49 | # 5 = Excellent: Very few or no issues, high quality 50 | 51 | "critical_remarks": [{{ 52 | "category": str, # "term_usage", "notation", "acronyms", "variable_naming", "unit_notation", "abbreviations", "technical_terms", "field_terminology", "cross_references", "definitions" 53 | "location": str, # Section/paragraph reference 54 | "issue": str, # Detailed description of the issue 55 | "severity": str, # "high", "medium", "low" 56 | "impact": str # How this affects consistency 57 | }}], 58 | 59 | "improvement_suggestions": [{{ 60 | "original_text": str, # The problematic text 61 | "improved_version": str, # AI-generated improvement 62 | "explanation": str, # Why this improvement helps 63 | "location": str, # Where to apply this change 64 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion", "equations" 65 | "focus": str # "term_usage", "notation", "acronyms", "variable_naming", "unit_notation", "abbreviations", "technical_terms", "field_terminology", "cross_references", "definitions" 66 | }}], 67 | 68 | "detailed_feedback": {{ 69 | "term_usage_consistency": str, # Detailed paragraph about term usage consistency 70 | "notation_consistency": str, # Detailed paragraph about notation consistency 71 | "acronym_usage": str, # Detailed paragraph about acronym usage 72 | "variable_naming_consistency": str, # Detailed paragraph about variable naming consistency 73 | "unit_notation_consistency": str, # Detailed paragraph about unit notation consistency 74 | "abbreviation_consistency": str, # Detailed paragraph about abbreviation consistency 75 | "technical_term_consistency": str, # Detailed paragraph about technical term consistency 76 | "field_terminology": str, # Detailed paragraph about field-specific terminology 77 | "cross_reference_consistency": str, # Detailed paragraph about cross-reference consistency 78 | "definition_consistency": str # Detailed paragraph about definition consistency 79 | }}, 80 | 81 | "summary": str # Overall assessment paragraph 82 | }} 83 | 84 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 85 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances terminology consistency. 86 | """ 87 | 88 | try: 89 | response = self.llm(prompt) 90 | analysis = json.loads(response) 91 | return analysis 92 | except Exception as e: 93 | return self._generate_error_report(f"Error analyzing terminology consistency: {str(e)}") 94 | 95 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 96 | """Generates a structured error report.""" 97 | return { 98 | "terminology_consistency_score": 0, 99 | "critical_remarks": [], 100 | "improvement_suggestions": [], 101 | "detailed_feedback": { 102 | "term_usage_consistency": "", 103 | "notation_consistency": "", 104 | "acronym_usage": "", 105 | "variable_naming_consistency": "", 106 | "unit_notation_consistency": "", 107 | "abbreviation_consistency": "", 108 | "technical_term_consistency": "", 109 | "field_terminology": "", 110 | "cross_reference_consistency": "", 111 | "definition_consistency": "" 112 | }, 113 | "summary": f"Error in analysis: {error_message}", 114 | "error": True 115 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/rigor/R6_technical_accuracy_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class TechnicalAccuracyAgent(BaseReviewerAgent): 7 | """Agent responsible for reviewing mathematical derivations, algorithms, and technical content.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "R6_Technical_Accuracy_Agent" 12 | self.category = "Scientific Rigor" 13 | 14 | def analyze_technical_accuracy(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes mathematical derivations, algorithms, and technical content.""" 16 | prompt = f"""Analyze the following text for technical accuracy. Focus on: 17 | 1. Mathematical derivation correctness 18 | 2. Algorithm correctness and efficiency 19 | 3. Technical terminology accuracy 20 | 4. Equation clarity and presentation 21 | 5. Technical content completeness 22 | 6. Logical consistency 23 | 7. Implementation details 24 | 8. Edge case handling 25 | 9. Complexity analysis 26 | 10. Technical documentation 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Technical approach summary 30 | - Introduction: Technical framework overview 31 | - Methodology: Technical methods description 32 | - Mathematical Framework: Derivation presentation 33 | - Algorithm Description: Implementation details 34 | - Technical Analysis: Complexity and efficiency 35 | - Results: Technical findings presentation 36 | - Discussion: Technical implications 37 | - Conclusion: Technical significance summary 38 | 39 | Text to analyze: {text} 40 | Research type: {research_type} 41 | 42 | Provide a detailed analysis in the following JSON format: 43 | {{ 44 | "technical_accuracy_score": int, # Single comprehensive score (1-5) 45 | # IMPORTANT: The score MUST be between 1 and 5, where: 46 | # 1 = Poor: Major issues that significantly impact quality 47 | # 2 = Below Average: Several notable issues that need attention 48 | # 3 = Average: Some issues but generally acceptable 49 | # 4 = Good: Minor issues that don't significantly impact quality 50 | # 5 = Excellent: Very few or no issues, high quality 51 | 52 | "critical_remarks": [{{ 53 | "category": str, # "derivations", "algorithms", "terminology", "equations", "completeness", "consistency", "implementation", "edge_cases", "complexity", "documentation" 54 | "location": str, # Section/paragraph reference 55 | "issue": str, # Detailed description of the issue 56 | "severity": str, # "high", "medium", "low" 57 | "impact": str # How this affects technical accuracy 58 | }}], 59 | 60 | "improvement_suggestions": [{{ 61 | "original_text": str, # The problematic text 62 | "improved_version": str, # AI-generated improvement 63 | "explanation": str, # Why this improvement helps 64 | "location": str, # Where to apply this change 65 | "category": str, # "abstract", "introduction", "methodology", "mathematical_framework", "algorithm_description", "technical_analysis", "results", "discussion", "conclusion" 66 | "focus": str # "derivations", "algorithms", "terminology", "equations", "completeness", "consistency", "implementation", "edge_cases", "complexity", "documentation" 67 | }}], 68 | 69 | "detailed_feedback": {{ 70 | "derivation_correctness": str, # Detailed paragraph about mathematical derivations 71 | "algorithm_accuracy": str, # Detailed paragraph about algorithm correctness 72 | "terminology_accuracy": str, # Detailed paragraph about technical terminology 73 | "equation_clarity": str, # Detailed paragraph about equation presentation 74 | "content_completeness": str, # Detailed paragraph about technical content 75 | "logical_consistency": str, # Detailed paragraph about logical consistency 76 | "implementation_details": str, # Detailed paragraph about implementation 77 | "edge_case_handling": str, # Detailed paragraph about edge cases 78 | "complexity_analysis": str, # Detailed paragraph about complexity 79 | "technical_documentation": str # Detailed paragraph about documentation 80 | }}, 81 | 82 | "summary": str # Overall assessment paragraph 83 | }} 84 | 85 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 86 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances technical accuracy. 87 | """ 88 | 89 | try: 90 | response = self.llm(prompt) 91 | analysis = json.loads(response) 92 | return analysis 93 | except Exception as e: 94 | return self._generate_error_report(f"Error analyzing technical accuracy: {str(e)}") 95 | 96 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 97 | """Generates a structured error report.""" 98 | return { 99 | "technical_accuracy_score": 0, 100 | "critical_remarks": [], 101 | "improvement_suggestions": [], 102 | "detailed_feedback": { 103 | "derivation_correctness": "", 104 | "algorithm_accuracy": "", 105 | "terminology_accuracy": "", 106 | "equation_clarity": "", 107 | "content_completeness": "", 108 | "logical_consistency": "", 109 | "implementation_details": "", 110 | "edge_case_handling": "", 111 | "complexity_analysis": "", 112 | "technical_documentation": "" 113 | }, 114 | "summary": f"Error in analysis: {error_message}", 115 | "error": True 116 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/writing/W5_inclusive_language_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | from ...core.base_agent import BaseReviewerAgent 4 | from ...core.report_template import ReportTemplate 5 | 6 | class InclusiveLanguageAgent(BaseReviewerAgent): 7 | """Agent responsible for evaluating inclusive, unbiased language usage.""" 8 | 9 | def __init__(self, model="gpt-4.1-nano"): 10 | super().__init__(model) 11 | self.name = "W5_Inclusive_Language_Agent" 12 | self.category = "Writing and Presentation" 13 | 14 | def analyze_inclusive_language(self, text: str, research_type: str) -> Dict[str, Any]: 15 | """Analyzes the use of inclusive and unbiased language in the text.""" 16 | prompt = f"""Analyze the following text for inclusive and unbiased language usage. Focus on: 17 | 1. Gender-neutral language 18 | 2. Cultural sensitivity 19 | 3. Age-appropriate terminology 20 | 4. Disability-inclusive language 21 | 5. Socioeconomic sensitivity 22 | 6. Geographic inclusivity 23 | 7. Professional title usage 24 | 8. Stereotype avoidance 25 | 9. Identity-first vs. person-first language 26 | 10. Historical context sensitivity 27 | 28 | For each section, provide at least 2-3 improvement suggestions. Consider these categories: 29 | - Abstract: Overall tone and inclusivity 30 | - Introduction: Background description 31 | - Literature Review: Participant descriptions 32 | - Methodology: Sample descriptions 33 | - Results: Participant representation 34 | - Discussion: Interpretation language 35 | - Conclusion: Generalizability statements 36 | - References: Author representation 37 | 38 | Text to analyze: {text} 39 | Research type: {research_type} 40 | 41 | Provide a detailed analysis in the following JSON format: 42 | {{ 43 | "inclusive_language_score": int, # Single comprehensive score (1-5) 44 | # IMPORTANT: The score MUST be between 1 and 5, where: 45 | # 1 = Poor: Major issues that significantly impact quality 46 | # 2 = Below Average: Several notable issues that need attention 47 | # 3 = Average: Some issues but generally acceptable 48 | # 4 = Good: Minor issues that don't significantly impact quality 49 | # 5 = Excellent: Very few or no issues, high quality 50 | 51 | "critical_remarks": [{{ 52 | "category": str, # "gender_neutrality", "cultural_sensitivity", "age_terminology", "disability_inclusion", "socioeconomic_sensitivity", "geographic_inclusivity", "professional_titles", "stereotypes", "identity_language", "historical_context" 53 | "location": str, # Section/paragraph reference 54 | "issue": str, # Detailed description of the issue 55 | "severity": str, # "high", "medium", "low" 56 | "impact": str # How this affects inclusivity 57 | }}], 58 | 59 | "improvement_suggestions": [{{ 60 | "original_text": str, # The problematic text 61 | "improved_version": str, # AI-generated improvement 62 | "explanation": str, # Why this improvement helps 63 | "location": str, # Where to apply this change 64 | "category": str, # "abstract", "introduction", "literature", "methodology", "results", "discussion", "conclusion", "references" 65 | "focus": str # "gender_neutrality", "cultural_sensitivity", "age_terminology", "disability_inclusion", "socioeconomic_sensitivity", "geographic_inclusivity", "professional_titles", "stereotypes", "identity_language", "historical_context" 66 | }}], 67 | 68 | "detailed_feedback": {{ 69 | "gender_neutral_language": str, # Detailed paragraph about gender-neutral language 70 | "cultural_sensitivity": str, # Detailed paragraph about cultural sensitivity 71 | "age_appropriate_terminology": str, # Detailed paragraph about age-appropriate terminology 72 | "disability_inclusive_language": str, # Detailed paragraph about disability-inclusive language 73 | "socioeconomic_sensitivity": str, # Detailed paragraph about socioeconomic sensitivity 74 | "geographic_inclusivity": str, # Detailed paragraph about geographic inclusivity 75 | "professional_title_usage": str, # Detailed paragraph about professional title usage 76 | "stereotypes": str, # Detailed paragraph about stereotype avoidance 77 | "identity_language": str, # Detailed paragraph about identity-first vs. person-first language 78 | "historical_context": str # Detailed paragraph about historical context sensitivity 79 | }}, 80 | 81 | "summary": str # Overall assessment paragraph 82 | }} 83 | 84 | Important: Generate at least 5-10 improvement suggestions across different sections and categories. 85 | Each suggestion should be specific, actionable, and include clear explanations of how it enhances inclusivity. 86 | """ 87 | 88 | try: 89 | response = self.llm(prompt) 90 | analysis = json.loads(response) 91 | return analysis 92 | except Exception as e: 93 | return self._generate_error_report(f"Error analyzing inclusive language: {str(e)}") 94 | 95 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 96 | """Generates a structured error report.""" 97 | return { 98 | "inclusive_language_score": 0, 99 | "critical_remarks": [], 100 | "improvement_suggestions": [], 101 | "detailed_feedback": { 102 | "gender_neutral_language": "", 103 | "cultural_sensitivity": "", 104 | "age_appropriate_terminology": "", 105 | "disability_inclusive_language": "", 106 | "socioeconomic_sensitivity": "", 107 | "geographic_inclusivity": "", 108 | "professional_title_usage": "", 109 | "stereotypes": "", 110 | "identity_language": "", 111 | "historical_context": "" 112 | }, 113 | "summary": f"Error in analysis: {error_message}", 114 | "error": True 115 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/controller_agent.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any, List 2 | import json 3 | import os 4 | from datetime import datetime 5 | import sys 6 | sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) 7 | 8 | from ..core.base_agent import BaseReviewerAgent 9 | 10 | # Section agents 11 | from .section.S1_title_keywords_agent import TitleKeywordsAgentS1 12 | from .section.S2_abstract_agent import AbstractAgentS2 13 | from .section.S3_introduction_agent import IntroductionAgentS3 14 | from .section.S4_literature_review_agent import LiteratureReviewAgentS4 15 | from .section.S5_methodology_agent import MethodologyAgentS5 16 | from .section.S6_results_agent import ResultsAgentS6 17 | from .section.S7_discussion_agent import DiscussionAgentS7 18 | from .section.S8_conclusion_agent import ConclusionAgentS8 19 | from .section.S9_references_agent import ReferencesAgentS9 20 | from .section.S10_supplementary_materials_agent import SupplementaryMaterialsAgentS10 21 | 22 | # Rigor agents 23 | from .rigor.R1_originality_contribution_agent import OriginalityContributionAgent 24 | from .rigor.R2_impact_significance_agent import ImpactSignificanceAgent 25 | from .rigor.R3_ethics_compliance_agent import EthicsComplianceAgent 26 | from .rigor.R4_data_code_availability_agent import DataCodeAvailabilityAgent 27 | from .rigor.R5_statistical_rigor_agent import StatisticalRigorAgent 28 | from .rigor.R6_technical_accuracy_agent import TechnicalAccuracyAgent 29 | from .rigor.R7_consistency_agent import ConsistencyAgent 30 | 31 | # Writing agents 32 | from .writing.W1_language_style_agent import LanguageStyleAgent 33 | from .writing.W2_narrative_structure_agent import NarrativeStructureAgent 34 | from .writing.W3_clarity_conciseness_agent import ClarityConcisenessAgent 35 | from .writing.W4_terminology_consistency_agent import TerminologyConsistencyAgent 36 | from .writing.W5_inclusive_language_agent import InclusiveLanguageAgent 37 | from .writing.W6_citation_formatting_agent import CitationFormattingAgent 38 | from .writing.W7_target_audience_agent import TargetAudienceAlignmentAgent 39 | 40 | class ControllerAgent: 41 | """Controller agent that coordinates all reviewer agents.""" 42 | 43 | def __init__(self, model="gpt-4.1-nano"): 44 | self.model = model 45 | self.agents = { 46 | # Section agents 47 | 'S1': TitleKeywordsAgentS1(model), 48 | 'S2': AbstractAgentS2(model), 49 | 'S3': IntroductionAgentS3(model), 50 | 'S4': LiteratureReviewAgentS4(model), 51 | 'S5': MethodologyAgentS5(model), 52 | 'S6': ResultsAgentS6(model), 53 | 'S7': DiscussionAgentS7(model), 54 | 'S8': ConclusionAgentS8(model), 55 | 'S9': ReferencesAgentS9(model), 56 | 'S10': SupplementaryMaterialsAgentS10(model), 57 | 58 | # Rigor agents 59 | 'R1': OriginalityContributionAgent(model), 60 | 'R2': ImpactSignificanceAgent(model), 61 | 'R3': EthicsComplianceAgent(model), 62 | 'R4': DataCodeAvailabilityAgent(model), 63 | 'R5': StatisticalRigorAgent(model), 64 | 'R6': TechnicalAccuracyAgent(model), 65 | 'R7': ConsistencyAgent(model), 66 | 67 | # Writing agents 68 | 'W1': LanguageStyleAgent(model), 69 | 'W2': NarrativeStructureAgent(model), 70 | 'W3': ClarityConcisenessAgent(model), 71 | 'W4': TerminologyConsistencyAgent(model), 72 | 'W5': InclusiveLanguageAgent(model), 73 | 'W6': CitationFormattingAgent(model), 74 | 'W7': TargetAudienceAlignmentAgent(model) 75 | } 76 | 77 | def run_analysis(self, text: str) -> Dict[str, Any]: 78 | """Runs analyses using all agents.""" 79 | try: 80 | # Determine research type 81 | research_type = self._determine_research_type(text) 82 | 83 | # Run analyses for each agent 84 | results = {} 85 | 86 | # Run section agent analyses 87 | results["S1"] = self.agents["S1"].analyze_title_keywords(text, research_type) 88 | results["S2"] = self.agents["S2"].analyze_abstract(text, research_type) 89 | results["S3"] = self.agents["S3"].analyze_introduction(text, research_type) 90 | results["S4"] = self.agents["S4"].analyze_literature_review(text, research_type) 91 | results["S5"] = self.agents["S5"].analyze_methodology(text, research_type) 92 | results["S6"] = self.agents["S6"].analyze_results(text, research_type) 93 | results["S7"] = self.agents["S7"].analyze_discussion(text, research_type) 94 | results["S8"] = self.agents["S8"].analyze_conclusion(text, research_type) 95 | results["S9"] = self.agents["S9"].analyze_references(text, research_type) 96 | results["S10"] = self.agents["S10"].analyze_supplementary_materials(text, research_type) 97 | 98 | # Run rigor agent analyses 99 | results["R1"] = self.agents["R1"].analyze_originality_contribution(text, research_type) 100 | results["R2"] = self.agents["R2"].analyze_impact_significance(text, research_type) 101 | results["R3"] = self.agents["R3"].analyze_ethics_compliance(text, research_type) 102 | results["R4"] = self.agents["R4"].analyze_data_code_availability(text, research_type) 103 | results["R5"] = self.agents["R5"].analyze_statistical_rigor(text, research_type) 104 | results["R6"] = self.agents["R6"].analyze_technical_accuracy(text, research_type) 105 | results["R7"] = self.agents["R7"].analyze_consistency(text, research_type) 106 | 107 | # Run writing agent analyses 108 | results["W1"] = self.agents["W1"].analyze_language_style(text, research_type) 109 | results["W2"] = self.agents["W2"].analyze_narrative_structure(text, research_type) 110 | results["W3"] = self.agents["W3"].analyze_clarity_conciseness(text, research_type) 111 | results["W4"] = self.agents["W4"].analyze_terminology_consistency(text, research_type) 112 | results["W5"] = self.agents["W5"].analyze_inclusive_language(text, research_type) 113 | results["W6"] = self.agents["W6"].analyze_citation_formatting(text, research_type) 114 | results["W7"] = self.agents["W7"].analyze_target_audience_alignment(text, research_type) 115 | 116 | return results 117 | except Exception as e: 118 | return self._generate_error_report(f"Error in analysis: {str(e)}") 119 | 120 | def _determine_research_type(self, text: str) -> str: 121 | """Determine the type of research paper.""" 122 | # Simple heuristic based on keywords 123 | text_lower = text.lower() 124 | 125 | if any(word in text_lower for word in ['experiment', 'methodology', 'data collection']): 126 | return 'experimental' 127 | elif any(word in text_lower for word in ['review', 'literature', 'meta-analysis']): 128 | return 'review' 129 | elif any(word in text_lower for word in ['theory', 'framework', 'model']): 130 | return 'theoretical' 131 | else: 132 | return 'general' 133 | 134 | def _generate_error_report(self, error_message: str) -> Dict[str, Any]: 135 | """Generates a structured error report.""" 136 | return { 137 | "error": True, 138 | "message": f"Error in analysis: {error_message}", 139 | "score": 0, 140 | "critical_remarks": [], 141 | "improvement_suggestions": [], 142 | "detailed_feedback": {}, 143 | "summary": f"Analysis failed due to error: {error_message}" 144 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/utils/pdf_parser.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | from typing import Dict, Any, List, Tuple 4 | import PyPDF2 5 | import fitz # PyMuPDF for better PDF handling 6 | import pytesseract 7 | from PIL import Image 8 | import io 9 | import numpy as np 10 | import requests 11 | from io import BytesIO 12 | 13 | class PDFParser: 14 | """Enhanced PDF parser with figure and table detection capabilities.""" 15 | 16 | def __init__(self, pdf_source: str): 17 | """Initialize the PDF parser. 18 | 19 | Args: 20 | pdf_path (str): Path to the PDF file 21 | """ 22 | if pdf_source.startswith("http://") or pdf_source.startswith("https://"): 23 | # Source is a URL 24 | response = requests.get(pdf_source) 25 | response.raise_for_status() 26 | pdf_file = BytesIO(response.content) 27 | self.doc = fitz.open("pdf", pdf_file) # Open from bytes 28 | else: 29 | # Source is a local file path 30 | if not os.path.exists(pdf_source): 31 | raise FileNotFoundError(f"PDF file not found: {pdf_source}") 32 | self.doc = fitz.open(pdf_source) # Open from file path 33 | 34 | def __del__(self): 35 | """Clean up by closing the document.""" 36 | if hasattr(self, 'doc'): 37 | self.doc.close() 38 | 39 | def extract_text(self) -> str: 40 | """Extract text from the PDF using PyMuPDF for better accuracy.""" 41 | text = "" 42 | try: 43 | for page in self.doc: 44 | text += page.get_text() + "\n" 45 | return text 46 | except Exception as e: 47 | raise Exception(f"Failed to extract text from PDF: {str(e)}") 48 | 49 | def get_metadata(self) -> Dict[str, str]: 50 | """Extract metadata from the PDF.""" 51 | try: 52 | metadata = self.doc.metadata 53 | 54 | metadata_res = { 55 | 'title': metadata.get('title', 'Unknown'), 56 | 'author': metadata.get('author', 'Unknown'), 57 | 'creation_date': metadata.get('creationDate', 'Unknown'), 58 | 'page_count': str(self.doc.page_count) 59 | } 60 | 61 | return metadata_res 62 | except Exception as e: 63 | raise Exception(f"Failed to extract metadata from PDF: {str(e)}") 64 | 65 | def extract_images(self) -> List[Dict[str, Any]]: 66 | """Extract images from the PDF with their locations and captions.""" 67 | images = [] 68 | try: 69 | for page_num, page in enumerate(self.doc): 70 | # Extract images 71 | image_list = page.get_images() 72 | 73 | for img_idx, img in enumerate(image_list): 74 | xref = img[0] 75 | base_image = self.doc.extract_image(xref) 76 | 77 | if base_image: 78 | # Convert image data to PIL Image for analysis 79 | image_data = base_image["image"] 80 | image = Image.open(io.BytesIO(image_data)) 81 | 82 | # Get image location on page 83 | image_rects = page.get_image_rects(xref) 84 | if not image_rects: # If no rectangles found, skip this image 85 | continue 86 | 87 | rect = image_rects[0] # Get first occurrence 88 | 89 | # Try to find caption near the image 90 | caption = self._find_caption_near_rect(page, rect, "Figure") 91 | 92 | images.append({ 93 | 'page': page_num + 1, 94 | 'index': img_idx + 1, 95 | 'bbox': [rect.x0, rect.y0, rect.x1, rect.y1], # Convert to list for JSON 96 | 'size': image.size, 97 | 'format': base_image["ext"], 98 | 'caption': caption, 99 | 'image_data': image_data # Raw image data 100 | }) 101 | 102 | return images 103 | except Exception as e: 104 | # If no images are found, return empty list instead of raising exception 105 | if "list index out of range" in str(e): 106 | return [] 107 | raise Exception(f"Failed to extract images from PDF: {str(e)}") 108 | 109 | def extract_tables(self) -> List[Dict[str, Any]]: 110 | """Extract tables from the PDF using text analysis.""" 111 | tables = [] 112 | try: 113 | for page_num, page in enumerate(self.doc): 114 | # Find potential table regions using text analysis 115 | blocks = page.get_text("blocks") 116 | table_regions = self._identify_table_regions(blocks) 117 | 118 | for region_idx, region in enumerate(table_regions): 119 | # Extract region text 120 | table_text = page.get_text(clip=region) 121 | 122 | # Try to find caption near the table 123 | caption = self._find_caption_near_rect(page, region, "Table") 124 | 125 | tables.append({ 126 | 'page': page_num + 1, 127 | 'index': region_idx + 1, 128 | 'bbox': [region.x0, region.y0, region.x1, region.y1], # Convert to list for JSON 129 | 'text': table_text, 130 | 'caption': caption 131 | }) 132 | 133 | return tables 134 | except Exception as e: 135 | raise Exception(f"Failed to extract tables from PDF: {str(e)}") 136 | 137 | def _identify_table_regions(self, blocks: List[Any]) -> List[fitz.Rect]: 138 | """Identify potential table regions using text block analysis.""" 139 | table_regions = [] 140 | current_region = None 141 | 142 | for block in blocks: 143 | text = block[4] 144 | rect = fitz.Rect(block[:4]) 145 | 146 | # Heuristics for table detection 147 | if (self._looks_like_table_content(text) or 148 | self._looks_like_table_header(text)): 149 | if current_region is None: 150 | current_region = rect 151 | else: 152 | current_region = current_region | rect # Union of rectangles 153 | elif current_region is not None: 154 | table_regions.append(current_region) 155 | current_region = None 156 | 157 | if current_region is not None: 158 | table_regions.append(current_region) 159 | 160 | return table_regions 161 | 162 | def _looks_like_table_content(self, text: str) -> bool: 163 | """Check if text block looks like table content.""" 164 | # Heuristics for table content detection 165 | if not text.strip(): 166 | return False 167 | 168 | # Check for regular patterns of numbers or short text segments 169 | lines = text.split('\n') 170 | if len(lines) < 2: 171 | return False 172 | 173 | # Check for consistent delimiters or spacing 174 | delimiter_pattern = re.compile(r'[\t|,]|\s{2,}') 175 | delimiter_counts = [len(re.findall(delimiter_pattern, line)) for line in lines] 176 | 177 | # If most lines have the same number of delimiters, likely a table 178 | return len(set(delimiter_counts)) <= 2 179 | 180 | def _looks_like_table_header(self, text: str) -> bool: 181 | """Check if text block looks like table header.""" 182 | # Common table header indicators 183 | header_indicators = ['mean', 'std', 'min', 'max', 'total', 'average', 184 | 'value', 'type', 'name', 'id', 'description'] 185 | 186 | text_lower = text.lower() 187 | words = text_lower.split() 188 | 189 | # Check for header-like words 190 | return any(indicator in words for indicator in header_indicators) 191 | 192 | def _find_caption_near_rect(self, page: Any, rect: fitz.Rect, 193 | element_type: str) -> str: 194 | """Find caption near a given rectangle on the page.""" 195 | # Create expanded search area 196 | margin = 20 # points 197 | search_rect = fitz.Rect( 198 | rect.x0 - margin, 199 | rect.y0 - margin, 200 | rect.x1 + margin, 201 | rect.y1 + margin 202 | ) 203 | 204 | # Get text in the search area 205 | nearby_text = page.get_text("text", clip=search_rect) 206 | 207 | # Look for caption patterns 208 | caption_pattern = f"{element_type}\s*\d+[.:](.*?)(?:\n\n|$)" 209 | match = re.search(caption_pattern, nearby_text, re.IGNORECASE | re.DOTALL) 210 | 211 | if match: 212 | return match.group(1).strip() 213 | return "" -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/core/config.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Any 2 | import os 3 | from dotenv import load_dotenv 4 | 5 | # Load environment variables 6 | load_dotenv() 7 | 8 | # OpenAI API Configuration 9 | OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") 10 | if not OPENAI_API_KEY: 11 | raise ValueError("OPENAI_API_KEY environment variable is not set") 12 | DEFAULT_MODEL = os.getenv("DEFAULT_MODEL", "gpt-4.1-nano") 13 | 14 | # Agent configurations 15 | AGENT_CONFIGS = { 16 | "scientific_rigor": [ 17 | { 18 | "name": "R1_Methodology_Agent", 19 | "category": "Scientific Rigor", 20 | "expertise": ["Research Design", "Methodology", "Experimental Setup"], 21 | "focus_areas": [ 22 | "Methodology robustness", 23 | "Experimental design", 24 | "Control conditions", 25 | "Sample size justification", 26 | "Data collection procedures" 27 | ] 28 | }, 29 | { 30 | "name": "R2_Impact_Significance_Agent", 31 | "category": "Scientific Rigor", 32 | "expertise": ["Research Impact", "Scientific Significance", "Field Contribution"], 33 | "focus_areas": [ 34 | "Scientific impact", 35 | "Field contribution", 36 | "Practical implications", 37 | "Future research directions" 38 | ] 39 | }, 40 | { 41 | "name": "R3_Ethics_Compliance_Agent", 42 | "category": "Scientific Rigor", 43 | "expertise": ["Research Ethics", "Compliance", "Data Protection"], 44 | "focus_areas": [ 45 | "Ethical considerations", 46 | "Conflict of interest", 47 | "Data privacy", 48 | "Informed consent", 49 | "Research integrity" 50 | ] 51 | }, 52 | { 53 | "name": "R4_Data_Code_Availability_Agent", 54 | "category": "Scientific Rigor", 55 | "expertise": ["Data Management", "Code Availability", "Reproducibility"], 56 | "focus_areas": [ 57 | "Data availability", 58 | "Code sharing", 59 | "Documentation", 60 | "Reproducibility", 61 | "Access restrictions" 62 | ] 63 | }, 64 | { 65 | "name": "R5_Statistical_Rigor_Agent", 66 | "category": "Scientific Rigor", 67 | "expertise": ["Statistical Analysis", "Data Validation", "Statistical Methods"], 68 | "focus_areas": [ 69 | "Statistical methods", 70 | "Data validation", 71 | "Statistical significance", 72 | "Error analysis", 73 | "Statistical reporting" 74 | ] 75 | }, 76 | { 77 | "name": "R6_Technical_Accuracy_Agent", 78 | "category": "Scientific Rigor", 79 | "expertise": ["Technical Content", "Mathematical Rigor", "Algorithm Analysis"], 80 | "focus_areas": [ 81 | "Technical accuracy", 82 | "Mathematical correctness", 83 | "Algorithm validation", 84 | "Technical clarity", 85 | "Implementation details" 86 | ] 87 | }, 88 | { 89 | "name": "R7_Consistency_Agent", 90 | "category": "Scientific Rigor", 91 | "expertise": ["Logical Coherence", "Cross-section Analysis", "Consistency Checking"], 92 | "focus_areas": [ 93 | "Logical coherence", 94 | "Cross-section consistency", 95 | "Terminology consistency", 96 | "Results alignment", 97 | "Conclusion support" 98 | ] 99 | } 100 | ], 101 | "writing_presentation": [ 102 | { 103 | "name": "W1_Language_Style_Agent", 104 | "category": "Writing and Presentation", 105 | "expertise": ["Grammar", "Spelling", "Punctuation"], 106 | "focus_areas": [ 107 | "Grammar correctness", 108 | "Spelling accuracy", 109 | "Punctuation usage", 110 | "Sentence structure", 111 | "Academic writing conventions" 112 | ] 113 | }, 114 | { 115 | "name": "W2_Narrative_Structure_Agent", 116 | "category": "Writing and Presentation", 117 | "expertise": ["Narrative Flow", "Structural Organization", "Logical Progression"], 118 | "focus_areas": [ 119 | "Narrative coherence", 120 | "Logical progression", 121 | "Section transitions", 122 | "Paragraph organization", 123 | "Reader engagement" 124 | ] 125 | }, 126 | { 127 | "name": "W3_Clarity_Conciseness_Agent", 128 | "category": "Writing and Presentation", 129 | "expertise": ["Language Simplicity", "Jargon Reduction", "Conciseness"], 130 | "focus_areas": [ 131 | "Language simplicity", 132 | "Jargon usage", 133 | "Wordiness", 134 | "Readability", 135 | "Information density" 136 | ] 137 | }, 138 | { 139 | "name": "W4_Terminology_Consistency_Agent", 140 | "category": "Writing and Presentation", 141 | "expertise": ["Terminology Consistency", "Notation Standards", "Acronym Usage"], 142 | "focus_areas": [ 143 | "Term usage consistency", 144 | "Notation consistency", 145 | "Acronym usage", 146 | "Variable naming", 147 | "Definition consistency" 148 | ] 149 | } 150 | ] 151 | } 152 | 153 | # Review criteria 154 | REVIEW_CRITERIA = { 155 | "scientific_rigor": { 156 | "methodology": { 157 | "weight": 0.15, 158 | "criteria": [ 159 | "Research design appropriateness", 160 | "Methodology robustness", 161 | "Experimental setup completeness", 162 | "Control conditions adequacy", 163 | "Sample size justification" 164 | ] 165 | }, 166 | "impact": { 167 | "weight": 0.15, 168 | "criteria": [ 169 | "Scientific significance", 170 | "Field contribution", 171 | "Practical implications", 172 | "Future research potential" 173 | ] 174 | }, 175 | "ethics": { 176 | "weight": 0.15, 177 | "criteria": [ 178 | "Ethical considerations", 179 | "Conflict of interest disclosure", 180 | "Data privacy protection", 181 | "Informed consent procedures", 182 | "Research integrity" 183 | ] 184 | }, 185 | "data_code": { 186 | "weight": 0.15, 187 | "criteria": [ 188 | "Data availability", 189 | "Code sharing", 190 | "Documentation completeness", 191 | "Reproducibility", 192 | "Access restrictions justification" 193 | ] 194 | }, 195 | "statistics": { 196 | "weight": 0.15, 197 | "criteria": [ 198 | "Statistical methods appropriateness", 199 | "Data validation", 200 | "Statistical significance", 201 | "Error analysis", 202 | "Statistical reporting" 203 | ] 204 | }, 205 | "technical": { 206 | "weight": 0.15, 207 | "criteria": [ 208 | "Technical accuracy", 209 | "Mathematical correctness", 210 | "Algorithm validation", 211 | "Technical clarity", 212 | "Implementation details" 213 | ] 214 | }, 215 | "consistency": { 216 | "weight": 0.10, 217 | "criteria": [ 218 | "Logical coherence", 219 | "Cross-section consistency", 220 | "Terminology consistency", 221 | "Results alignment", 222 | "Conclusion support" 223 | ] 224 | } 225 | }, 226 | "writing_presentation": { 227 | "language_style": { 228 | "weight": 0.25, 229 | "criteria": [ 230 | "Grammar correctness", 231 | "Spelling accuracy", 232 | "Punctuation usage", 233 | "Sentence structure", 234 | "Academic writing conventions" 235 | ] 236 | }, 237 | "narrative_structure": { 238 | "weight": 0.25, 239 | "criteria": [ 240 | "Narrative coherence", 241 | "Logical progression", 242 | "Section transitions", 243 | "Paragraph organization", 244 | "Reader engagement" 245 | ] 246 | }, 247 | "clarity_conciseness": { 248 | "weight": 0.25, 249 | "criteria": [ 250 | "Language simplicity", 251 | "Jargon usage", 252 | "Wordiness", 253 | "Readability", 254 | "Information density" 255 | ] 256 | }, 257 | "terminology_consistency": { 258 | "weight": 0.25, 259 | "criteria": [ 260 | "Term usage consistency", 261 | "Notation consistency", 262 | "Acronym usage", 263 | "Variable naming", 264 | "Definition consistency" 265 | ] 266 | } 267 | } 268 | } 269 | 270 | # Controller Agent Configuration 271 | CONTROLLER_CONFIG = { 272 | "review_steps": [ 273 | "initial_analysis", 274 | "agent_review_comparison", 275 | "remark_ranking", 276 | "report_generation" 277 | ], 278 | "output_formats": ["json", "text"], 279 | "score_range": (1, 5) 280 | } 281 | 282 | # PDF Processing Configuration 283 | PDF_PROCESSOR_CONFIG = { 284 | "supported_formats": ["pdf"], 285 | "max_pages": 100, 286 | "image_quality": "high", 287 | "ocr_enabled": True 288 | } 289 | 290 | # File Paths 291 | PATHS = { 292 | "manuscripts": "manuscripts/", 293 | "results": "results/", 294 | "tests": "tests/", 295 | "logs": "logs/" 296 | } 297 | 298 | # Create directories if they don't exist 299 | for path in PATHS.values(): 300 | os.makedirs(path, exist_ok=True) -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/quality/quality_control_agent.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | from typing import Dict, List, Any 4 | import openai 5 | import PyPDF2 6 | import requests 7 | from io import BytesIO 8 | from ...core.base_agent import BaseReviewerAgent 9 | 10 | class QualityControlAgent(BaseReviewerAgent): 11 | """ 12 | Quality Control Agent that reviews and validates the outputs from all other agents. 13 | It ensures the quality and consistency of the review process and provides a final, 14 | streamlined report. 15 | """ 16 | 17 | def __init__(self, model: str = "gpt-4.1"): 18 | super().__init__(model) 19 | self.required_inputs = { 20 | 'manuscript_path': str, 21 | 'context_path': str, 22 | 'rigor_results_path': str, 23 | 'section_results_path': str, 24 | 'writing_results_path': str 25 | } 26 | 27 | # Define section mappings with full names 28 | self.section_mappings = { 29 | 'section_results': { 30 | 'S1': 'Title and Keywords', 31 | 'S2': 'Abstract', 32 | 'S3': 'Introduction', 33 | 'S4': 'Literature Review', 34 | 'S5': 'Methodology', 35 | 'S6': 'Results', 36 | 'S7': 'Discussion', 37 | 'S8': 'Conclusion', 38 | 'S9': 'References', 39 | 'S10': 'Supplementary Materials' 40 | }, 41 | 'rigor_results': { 42 | 'R1': 'Originality and Contribution', 43 | 'R2': 'Impact and Significance', 44 | 'R3': 'Ethics and Compliance', 45 | 'R4': 'Data and Code Availability', 46 | 'R5': 'Statistical Rigor', 47 | 'R6': 'Technical Accuracy', 48 | 'R7': 'Consistency' 49 | }, 50 | 'writing_results': { 51 | 'W1': 'Language and Style', 52 | 'W2': 'Narrative and Structure', 53 | 'W3': 'Clarity and Conciseness', 54 | 'W4': 'Terminology Consistency', 55 | 'W5': 'Inclusive Language', 56 | 'W6': 'Citation Formatting', 57 | 'W7': 'Target Audience Alignment' 58 | } 59 | } 60 | 61 | def load_json_file(self, file_path: str) -> Dict: 62 | """Load and parse a JSON file.""" 63 | with open(file_path, 'r', encoding='utf-8') as f: 64 | return json.load(f) 65 | 66 | def extract_pdf_text(self, pdf_source: str) -> str: 67 | """Extract text from a PDF file or URL.""" 68 | text = "" 69 | 70 | if pdf_source.startswith("http://") or pdf_source.startswith("https://"): 71 | # Source is a URL 72 | response = requests.get(pdf_source) 73 | response.raise_for_status() # Raises error if the download failed 74 | pdf_file = BytesIO(response.content) 75 | else: 76 | # Source is a local file path 77 | pdf_file = open(pdf_source, 'rb') 78 | 79 | try: 80 | pdf_reader = PyPDF2.PdfReader(pdf_file) 81 | for page in pdf_reader.pages: 82 | extracted_text = page.extract_text() 83 | if extracted_text: 84 | text += extracted_text + "\n" 85 | finally: 86 | if not isinstance(pdf_file, BytesIO): 87 | pdf_file.close() 88 | 89 | return text 90 | 91 | def process(self, inputs: Dict[str, Any]) -> Dict[str, Any]: 92 | """ 93 | Main processing method that: 94 | 1. Validates inputs 95 | 2. Loads and analyzes all review outputs 96 | 3. Produces a quality-controlled final report 97 | """ 98 | 99 | # Load all input data 100 | context = inputs['context'] 101 | rigor_results = inputs['rigor_results'] 102 | section_results = inputs['section_results'] 103 | writing_results = inputs['writing_results'] 104 | 105 | # Extract manuscript text 106 | manuscript_text = self.extract_pdf_text(inputs['manuscript_src']) 107 | 108 | # Process each category separately 109 | final_results = {} 110 | 111 | # Process section results 112 | print("Processing section results...") 113 | section_prompt = self.generate_category_prompt( 114 | 'section_results', 115 | section_results, 116 | manuscript_text, 117 | context 118 | ) 119 | section_analysis = json.loads(self.llm(section_prompt)) 120 | final_results['section_results'] = section_analysis.get('section_results', {}) 121 | 122 | # Process rigor results 123 | print("Processing rigor results...") 124 | rigor_prompt = self.generate_category_prompt( 125 | 'rigor_results', 126 | rigor_results, 127 | manuscript_text, 128 | context 129 | ) 130 | rigor_analysis = json.loads(self.llm(rigor_prompt)) 131 | final_results['rigor_results'] = rigor_analysis.get('rigor_results', {}) 132 | 133 | # Process writing results 134 | print("Processing writing results...") 135 | writing_prompt = self.generate_category_prompt( 136 | 'writing_results', 137 | writing_results, 138 | manuscript_text, 139 | context 140 | ) 141 | writing_analysis = json.loads(self.llm(writing_prompt)) 142 | final_results['writing_results'] = writing_analysis.get('writing_results', {}) 143 | 144 | # Format the output 145 | formatted_output = self.format_output(final_results) 146 | 147 | return formatted_output 148 | 149 | def generate_category_prompt(self, category: str, results: Dict, manuscript_text: str, context: Dict) -> str: 150 | """ 151 | Generate a prompt for analyzing a specific category of results. 152 | """ 153 | # Get section mappings for this category 154 | sections = self.section_mappings[category] 155 | 156 | # Create section headers 157 | section_headers = [] 158 | for code, name in sections.items(): 159 | section_headers.append(f"o {code} – {name}") 160 | 161 | # Create example JSON structure for this category 162 | example_json = { 163 | category: { 164 | list(sections.keys())[0]: { 165 | "section_name": sections[list(sections.keys())[0]], 166 | "score": 4, 167 | "summary": "Critical remarks, tips, and positive aspects...", 168 | "suggestions": [ 169 | { 170 | "remarks": "Issue description", 171 | "original_text": "Original text from manuscript", 172 | "improved_version": "Suggested improvement", 173 | "explanation": "Explanation for the improvement" 174 | } 175 | ] 176 | } 177 | } 178 | } 179 | 180 | prompt = f"""You are a Quality Control Agent responsible for reviewing and validating the outputs from AI review agents. Your task is to analyze the {category.replace('_', ' ')} category: 181 | 182 | Category Sections: 183 | {''.join(section_headers)} 184 | 185 | For each section, you should: 186 | 1. Validate the accuracy and relevance of the feedback 187 | 2. Identify the most critical and helpful suggestions (aim for ~3 per section) 188 | 3. Add any additional valuable insights 189 | 4. Note if any section is not applicable 190 | 5. Reassess the 1-5 score for each section 191 | 192 | Structure your analysis in the following format for each section: 193 | - A summary paragraph highlighting: 194 | * Critical remarks 195 | * Tips for improvement 196 | * Positive aspects of the manuscript 197 | - For each suggestion (up to 3 per section): 198 | * Remarks 199 | * Original Text 200 | * Improved Version 201 | * Explanation for the improvement 202 | 203 | Important guidelines: 204 | - Avoid duplicate issues 205 | - Focus on the most severe and helpful remarks 206 | - Clearly mark non-applicable sections 207 | - Maintain the existing JSON structure 208 | - Ensure all feedback is constructive and actionable 209 | 210 | Please analyze the following inputs: 211 | 212 | Manuscript Text (Preview): 213 | {manuscript_text[:1000]}... 214 | 215 | Context: 216 | {json.dumps(context, indent=2)} 217 | 218 | {category.replace('_', ' ').title()} Results: 219 | {json.dumps(results, indent=2)} 220 | 221 | Provide your analysis in a structured JSON format that exactly matches this structure: 222 | {json.dumps(example_json, indent=2)} 223 | 224 | For each section: 225 | 1. Include the full section name 226 | 2. Provide a score (1-5) 227 | 3. Include a summary paragraph 228 | 4. Include up to 3 suggestions with remarks, original text, improved version, and explanation 229 | 5. If a section is not applicable, set status to "not_applicable" and include an appropriate message 230 | 231 | Ensure your response is valid JSON and includes all required fields.""" 232 | 233 | return prompt 234 | 235 | def format_output(self, analysis_results: Dict[str, Any]) -> Dict[str, Any]: 236 | """ 237 | Format the analysis results into the required JSON structure. 238 | """ 239 | try: 240 | # Validate the structure 241 | if not isinstance(analysis_results, dict): 242 | raise ValueError("Analysis results must be a dictionary") 243 | 244 | # Ensure all required sections are present with full names 245 | for category, sections in self.section_mappings.items(): 246 | if category not in analysis_results: 247 | raise ValueError(f"Missing category: {category}") 248 | 249 | for code, name in sections.items(): 250 | if code not in analysis_results[category]: 251 | analysis_results[category][code] = { 252 | 'status': 'not_applicable', 253 | 'message': f'Not applicable - no {name} content detected', 254 | 'score': 0, 255 | 'section_name': name 256 | } 257 | else: 258 | # Add section name to existing results 259 | analysis_results[category][code]['section_name'] = name 260 | 261 | return analysis_results 262 | 263 | except Exception as e: 264 | return { 265 | 'status': 'error', 266 | 'message': f'Error formatting output: {str(e)}', 267 | 'results': analysis_results 268 | } -------------------------------------------------------------------------------- /Agent1_Peer_Review/src/reviewer_agents/executive_summary_agent.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | from typing import Dict, Any 4 | import PyPDF2 5 | import requests 6 | from io import BytesIO 7 | from ..core.base_agent import BaseReviewerAgent 8 | 9 | class ExecutiveSummaryAgent(BaseReviewerAgent): 10 | """ 11 | Executive Summary Agent that generates a high-level summary of the review results 12 | and calculates overall scores based on the quality control results. 13 | """ 14 | 15 | def __init__(self, model: str = "gpt-4.1"): 16 | super().__init__(model) 17 | self.required_inputs = { 18 | 'manuscript_path': str, 19 | 'context_path': str, 20 | 'quality_control_results_path': str 21 | } 22 | 23 | def load_json_file(self, file_path: str) -> Dict: 24 | """Load and parse a JSON file.""" 25 | with open(file_path, 'r', encoding='utf-8') as f: 26 | return json.load(f) 27 | 28 | def extract_pdf_text(self, pdf_source: str) -> str: 29 | """Extract text from a PDF file or URL.""" 30 | text = "" 31 | 32 | if pdf_source.startswith("http://") or pdf_source.startswith("https://"): 33 | # Source is a URL 34 | response = requests.get(pdf_source) 35 | response.raise_for_status() # Raises error if the download failed 36 | pdf_file = BytesIO(response.content) 37 | else: 38 | # Source is a local file path 39 | pdf_file = open(pdf_source, 'rb') 40 | 41 | try: 42 | pdf_reader = PyPDF2.PdfReader(pdf_file) 43 | for page in pdf_reader.pages: 44 | extracted_text = page.extract_text() 45 | if extracted_text: 46 | text += extracted_text + "\n" 47 | finally: 48 | if not isinstance(pdf_file, BytesIO): 49 | pdf_file.close() 50 | 51 | return text 52 | 53 | def extract_title(self, pdf_path: str) -> str: 54 | """Extract title from the first page of the PDF.""" 55 | with open(pdf_path, 'rb') as file: 56 | pdf_reader = PyPDF2.PdfReader(file) 57 | first_page = pdf_reader.pages[0] 58 | text = first_page.extract_text() 59 | # Assuming title is in the first few lines 60 | lines = text.split('\n') 61 | for line in lines[:5]: # Check first 5 lines 62 | if line.strip() and len(line.strip()) > 10: # Basic title validation 63 | return line.strip() 64 | return "Title not found" 65 | 66 | def calculate_scores(self, quality_control_results: Dict) -> Dict[str, float]: 67 | """Calculate overall scores from quality control results.""" 68 | scores = { 69 | 'section_score': 0.0, 70 | 'rigor_score': 0.0, 71 | 'writing_score': 0.0, 72 | 'final_score': 0.0 73 | } 74 | 75 | # Calculate section score (S1-S10) 76 | section_scores = [] 77 | for i in range(1, 11): 78 | section_key = f'S{i}' 79 | if section_key in quality_control_results.get('section_results', {}): 80 | section_scores.append(quality_control_results['section_results'][section_key]['score']) 81 | if section_scores: 82 | scores['section_score'] = sum(section_scores) / len(section_scores) 83 | 84 | # Calculate rigor score (R1-R7) 85 | rigor_scores = [] 86 | for i in range(1, 8): 87 | rigor_key = f'R{i}' 88 | if rigor_key in quality_control_results.get('rigor_results', {}): 89 | rigor_scores.append(quality_control_results['rigor_results'][rigor_key]['score']) 90 | if rigor_scores: 91 | scores['rigor_score'] = sum(rigor_scores) / len(rigor_scores) 92 | 93 | # Calculate writing score (W1-W7) 94 | writing_scores = [] 95 | for i in range(1, 8): 96 | writing_key = f'W{i}' 97 | if writing_key in quality_control_results.get('writing_results', {}): 98 | writing_scores.append(quality_control_results['writing_results'][writing_key]['score']) 99 | if writing_scores: 100 | scores['writing_score'] = sum(writing_scores) / len(writing_scores) 101 | 102 | # Calculate final score 103 | category_scores = [scores['section_score'], scores['rigor_score'], scores['writing_score']] 104 | if category_scores: 105 | scores['final_score'] = sum(category_scores) / len(category_scores) 106 | 107 | return scores 108 | 109 | def validate_context(self, context: Dict) -> Dict: 110 | """Validate and sanitize context data, providing defaults for missing or invalid values.""" 111 | # Initialize default values 112 | sanitized_context = { 113 | 'target_publication_outlets': { 114 | 'user_input': 'the target journal' 115 | }, 116 | 'review_focus_areas': { 117 | 'user_input': 'general aspects' 118 | } 119 | } 120 | 121 | # Validate target publication outlets 122 | if isinstance(context.get('target_publication_outlets'), dict): 123 | user_input = context['target_publication_outlets'].get('user_input') 124 | if isinstance(user_input, str) and user_input.strip(): 125 | sanitized_context['target_publication_outlets']['user_input'] = user_input.strip() 126 | 127 | # Validate review focus areas 128 | if isinstance(context.get('review_focus_areas'), dict): 129 | user_input = context['review_focus_areas'].get('user_input') 130 | if isinstance(user_input, str) and user_input.strip(): 131 | sanitized_context['review_focus_areas']['user_input'] = user_input.strip() 132 | 133 | return sanitized_context 134 | 135 | def generate_independent_review(self, manuscript_text: str, context: Dict) -> str: 136 | """Generate an independent high-level review of the manuscript using GPT-4.1.""" 137 | # Sanitize context 138 | sanitized_context = self.validate_context(context) 139 | target_journal = sanitized_context['target_publication_outlets']['user_input'] 140 | focus_areas = sanitized_context['review_focus_areas']['user_input'] 141 | 142 | prompt = f"""You are an expert reviewer for {target_journal}. Read the following manuscript content and user priorities, then independently write a high-level review in three paragraphs: 143 | 144 | Manuscript Content: 145 | {manuscript_text[:6000]} 146 | 147 | User Priorities: 148 | - Target Journal: {target_journal} 149 | - Focus Areas: {focus_areas} 150 | 151 | Write: 152 | 1. A summary of what the manuscript is about 153 | 2. The main strengths and weaknesses, with special attention to {focus_areas} 154 | 3. The most critical suggestions for improvement, considering {target_journal} standards 155 | 156 | Be concise, professional, and focus on the most important points. Do not reference any other reviews or JSON files yet.""" 157 | response = self.llm(prompt) 158 | return response.strip() 159 | 160 | def generate_balanced_summary(self, independent_review: str, quality_control_results: Dict, context: Dict) -> str: 161 | """Balance the agent's own review with the quality-controlled review JSON.""" 162 | # Sanitize context 163 | sanitized_context = self.validate_context(context) 164 | target_journal = sanitized_context['target_publication_outlets']['user_input'] 165 | focus_areas = sanitized_context['review_focus_areas']['user_input'] 166 | 167 | prompt = f"""You are an Executive Summary Agent for {target_journal}. You have two sources: 168 | 1. Your own independent review of the manuscript (below) 169 | 2. The quality-controlled review JSON (below) 170 | 171 | First, extract the manuscript's title from the content. Then, write a unified executive summary in three paragraphs that: 172 | - Provides a clear, concise overview of the manuscript 173 | - Presents a balanced assessment of strengths and weaknesses 174 | - Offers specific, actionable recommendations for improvement 175 | 176 | IMPORTANT: While the quality-controlled review JSON provides valuable insights, your executive summary should: 177 | - Draw naturally from both your independent review and the quality control findings 178 | - Focus on the most significant and impactful points, regardless of source 179 | - Present a cohesive narrative that flows naturally 180 | - Avoid mechanically listing points from either source 181 | 182 | Your Own Review: 183 | {independent_review} 184 | 185 | User Priorities: 186 | - Target Journal: {target_journal} 187 | - Focus Areas: {focus_areas} 188 | 189 | Quality-Controlled Review (JSON): 190 | {json.dumps(quality_control_results, indent=2)} 191 | 192 | First, extract the manuscript's title. Then write a cohesive executive summary that: 193 | 1. Summarizes the manuscript's content and contribution, highlighting its key insights and significance 194 | 2. Evaluates its strengths and weaknesses, with special attention to {focus_areas} 195 | 3. Provides clear, actionable recommendations for improvement 196 | 197 | Format your response as a JSON object with two fields: 198 | 1. "title": The extracted manuscript title 199 | 2. "executive_summary": The three-paragraph summary 200 | 201 | Keep the summary within half a page (about 250 words), use professional language, and be specific and constructive. Write as a single, unified document that flows naturally while incorporating insights from both sources.""" 202 | response = self.llm(prompt) 203 | return response.strip() 204 | 205 | def process(self, inputs: Dict[str, Any]) -> Dict[str, Any]: 206 | """ 207 | Main processing method that: 208 | 1. Validates inputs 209 | 2. Extracts necessary information 210 | 3. Generates an independent review 211 | 4. Synthesizes a balanced executive summary 212 | 5. Calculates scores 213 | 6. Produces final output 214 | """ 215 | 216 | 217 | context = inputs['context'] 218 | quality_control_results = inputs['quality_control_results'] 219 | 220 | # Extract manuscript text 221 | manuscript_text = self.extract_pdf_text(inputs['manuscript_src']) 222 | 223 | # Step 1: Generate independent review 224 | independent_review = self.generate_independent_review(manuscript_text, context) 225 | 226 | # Step 2: Synthesize balanced executive summary and extract title 227 | summary_response = self.generate_balanced_summary(independent_review, quality_control_results, context) 228 | try: 229 | summary_data = json.loads(summary_response) 230 | title = summary_data.get('title', 'Title not found') 231 | summary = summary_data.get('executive_summary', '') 232 | except json.JSONDecodeError: 233 | print("Warning: Could not parse summary response as JSON. Using raw response.") 234 | title = 'Title not found' 235 | summary = summary_response 236 | 237 | # Calculate scores 238 | scores = self.calculate_scores(quality_control_results) 239 | 240 | # Prepare output 241 | output = { 242 | 'manuscript_title': title, 243 | 'executive_summary': summary, 244 | 'publication_outlets': context['target_publication_outlets']['user_input'], 245 | 'review_focus': context['review_focus_areas']['user_input'], 246 | 'independent_review': independent_review, 247 | 'scores': scores 248 | } 249 | 250 | return output 251 | 252 | def save_results(self, results: Dict[str, Any], output_path: str) -> None: 253 | """Save the results to a JSON file.""" 254 | os.makedirs(os.path.dirname(output_path), exist_ok=True) 255 | with open(output_path, 'w', encoding='utf-8') as f: 256 | json.dump(results, f, indent=2) 257 | print(f"Executive summary results saved to {output_path}") --------------------------------------------------------------------------------