Ananthakr1shnan's picture
Upload 80 files
519c06d verified
#!/usr/bin/env python3
"""
ResearchMate Setup Script
Complete setup and configuration for ResearchMate
"""
import os
import sys
import json
import shutil
import subprocess
import logging
from pathlib import Path
from typing import Dict, List, Optional, Any
import configparser
import getpass
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(Path(__file__).parent.parent.parent / 'logs' / 'setup.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class ResearchMateSetup:
"""Complete setup system for ResearchMate"""
def __init__(self, project_root: Optional[Path] = None):
self.project_root = project_root or Path(__file__).parent.parent.parent
self.config_dir = self.project_root / "config"
self.settings_file = self.config_dir / "settings.json"
self.env_file = self.project_root / ".env"
def print_banner(self):
"""Print setup banner"""
banner = """
ResearchMate Setup System
============================
AI Research Assistant Configuration
Version: 2.0.0
"""
print(banner)
logger.info("Starting ResearchMate setup")
def create_config_structure(self):
"""Create configuration directory structure"""
try:
logger.info("Creating configuration structure...")
# Create directories
directories = [
"config",
"logs",
"uploads",
"chroma_db",
"chroma_persist",
"src/templates",
"src/tests"
]
for directory in directories:
dir_path = self.project_root / directory
dir_path.mkdir(parents=True, exist_ok=True)
logger.info(f"Created: {directory}")
return True
except Exception as e:
logger.error(f"Failed to create configuration structure: {e}")
return False
def collect_configuration(self) -> Dict[str, Any]:
"""Collect configuration from user"""
config = {}
print("\nConfiguration Setup")
print("Please provide the following information:")
# API Keys
print("\nAPI Configuration:")
groq_api_key = getpass.getpass("Enter your Groq API key: ")
config["groq_api_key"] = groq_api_key
# Server Configuration
print("\nServer Configuration:")
config["server"] = {
"host": input("Host (default: 0.0.0.0): ") or "0.0.0.0",
"port": int(input("Port (default: 8000): ") or "8000"),
"debug": input("Debug mode (y/n, default: n): ").lower() == 'y'
}
# Database Configuration
print("\nDatabase Configuration:")
config["database"] = {
"chroma_persist_dir": input("ChromaDB persist directory (default: ./chroma_persist): ") or "./chroma_persist",
"collection_name": input("Collection name (default: research_documents): ") or "research_documents"
}
# AI Model Configuration
print("\nAI Model Configuration:")
config["ai_model"] = {
"model_name": input("Groq model name (default: llama-3.3-70b-versatile): ") or "llama-3.3-70b-versatile",
"temperature": float(input("Temperature (default: 0.7): ") or "0.7"),
"max_tokens": int(input("Max tokens (default: 4096): ") or "4096")
}
# Search Configuration
print("\nSearch Configuration:")
config["search"] = {
"max_results": int(input("Max search results (default: 10): ") or "10"),
"similarity_threshold": float(input("Similarity threshold (default: 0.7): ") or "0.7")
}
# Upload Configuration
print("\nUpload Configuration:")
config["upload"] = {
"max_file_size": int(input("Max file size in MB (default: 50): ") or "50") * 1024 * 1024,
"allowed_extensions": [".pdf", ".txt", ".md", ".docx"]
}
return config
def save_configuration(self, config: Dict[str, Any]):
"""Save configuration to settings file"""
try:
logger.info("Saving configuration...")
# Create settings configuration
settings_config = {
"server": {
"host": config['server']['host'],
"port": config['server']['port'],
"debug": config['server']['debug'],
"reload": False,
"workers": 1,
"log_level": "info"
},
"database": {
"chroma_persist_dir": config['database']['chroma_persist_dir'],
"collection_name": config['database']['collection_name'],
"similarity_threshold": 0.7,
"max_results": config['search']['max_results'],
"embedding_model": "all-MiniLM-L6-v2"
},
"ai_model": {
"model_name": config['ai_model']['model_name'],
"temperature": config['ai_model']['temperature'],
"max_tokens": config['ai_model']['max_tokens'],
"top_p": 0.9,
"frequency_penalty": 0.0,
"presence_penalty": 0.0,
"timeout": 30
},
"upload": {
"max_file_size": config['upload']['max_file_size'],
"allowed_extensions": config['upload']['allowed_extensions'],
"upload_directory": "./uploads",
"temp_directory": "./tmp"
},
"search": {
"max_results": config['search']['max_results'],
"similarity_threshold": config['search']['similarity_threshold'],
"enable_reranking": True,
"chunk_size": 1000,
"chunk_overlap": 200
},
"security": {
"cors_origins": ["*"],
"cors_methods": ["*"],
"cors_headers": ["*"],
"rate_limit_enabled": True,
"rate_limit_requests": 100,
"rate_limit_period": 60
},
"logging": {
"level": "INFO",
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
"file_enabled": True,
"file_path": "./logs/app.log",
"max_file_size": 10485760,
"backup_count": 5,
"console_enabled": True
}
}
# Save to settings.json
settings_file = self.config_dir / "settings.json"
with open(settings_file, 'w') as f:
json.dump(settings_config, f, indent=2)
# Save environment variables
env_content = f"""# ResearchMate Environment Variables
GROQ_API_KEY={config['groq_api_key']}
ENVIRONMENT=production
DEBUG={str(config['server']['debug']).lower()}
HOST={config['server']['host']}
PORT={config['server']['port']}
"""
with open(self.env_file, 'w') as f:
f.write(env_content)
logger.info("Configuration saved successfully")
logger.info(f"Settings file: {settings_file}")
logger.info(f"Environment file: {self.env_file}")
return True
except Exception as e:
logger.error(f"Failed to save configuration: {e}")
return False
def create_startup_script(self):
"""Create startup script"""
try:
logger.info("Creating startup script...")
startup_content = """#!/usr/bin/env python3
# ResearchMate Startup Script
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent))
from scripts.deploy import ResearchMateDeployer
def main():
deployer = ResearchMateDeployer()
if deployer.deploy():
deployer.start_server()
else:
sys.exit(1)
if __name__ == "__main__":
main()
"""
startup_script = self.project_root / "start_researchmate.py"
with open(startup_script, 'w') as f:
f.write(startup_content)
# Make executable on Unix systems
if os.name != 'nt':
os.chmod(startup_script, 0o755)
logger.info("Startup script created")
return True
except Exception as e:
logger.error(f"Failed to create startup script: {e}")
return False
def create_test_files(self):
"""Create test files structure"""
try:
logger.info("Creating test files...")
# Create test directory structure
test_dirs = [
"src/tests",
"src/tests/unit",
"src/tests/integration",
"src/tests/fixtures"
]
for test_dir in test_dirs:
(self.project_root / test_dir).mkdir(parents=True, exist_ok=True)
# Create __init__.py files
for test_dir in test_dirs:
init_file = self.project_root / test_dir / "__init__.py"
init_file.touch()
# Create basic test files
test_files = {
"src/tests/test_basic.py": '''"""Basic tests for ResearchMate"""
import pytest
import sys
from pathlib import Path
# Add project root to path
sys.path.append(str(Path(__file__).parent.parent.parent))
def test_imports():
"""Test that core modules can be imported"""
try:
from src.components import ResearchAssistant
from src.components.config import Config
assert True
except ImportError as e:
pytest.fail(f"Import failed: {e}")
def test_config_loading():
"""Test configuration loading"""
from src.components.config import Config
config = Config()
assert config is not None
''',
"src/tests/conftest.py": '''"""Test configuration"""
import pytest
import tempfile
import shutil
from pathlib import Path
@pytest.fixture
def temp_dir():
"""Create temporary directory for tests"""
temp_dir = Path(tempfile.mkdtemp())
yield temp_dir
shutil.rmtree(temp_dir)
@pytest.fixture
def sample_config():
"""Sample configuration for tests"""
return {
"server": {"host": "127.0.0.1", "port": 8000},
"database": {"chroma_persist_dir": "./test_chroma"},
"ai_model": {"model_name": "llama-3.3-70b-versatile"}
}
''',
"src/tests/unit/test_components.py": '''"""Unit tests for components"""
import pytest
import sys
from pathlib import Path
# Add project root to path
sys.path.append(str(Path(__file__).parent.parent.parent.parent))
def test_research_assistant_init():
"""Test ResearchAssistant initialization"""
# Add your component tests here
assert True
def test_config_validation():
"""Test configuration validation"""
# Add your config tests here
assert True
''',
"src/tests/integration/test_api.py": '''"""Integration tests for API"""
import pytest
import sys
from pathlib import Path
# Add project root to path
sys.path.append(str(Path(__file__).parent.parent.parent.parent))
def test_api_endpoints():
"""Test API endpoints"""
# Add your API tests here
assert True
'''
}
for file_path, content in test_files.items():
full_path = self.project_root / file_path
with open(full_path, 'w') as f:
f.write(content)
logger.info("Test files created")
return True
except Exception as e:
logger.error(f"Failed to create test files: {e}")
return False
def create_development_tools(self):
"""Create development tools and scripts"""
try:
logger.info("Creating development tools...")
# Create development requirements
dev_requirements = """# Development dependencies
pytest==7.4.3
pytest-asyncio==0.21.1
pytest-cov==4.1.0
black==23.11.0
flake8==6.1.0
isort==5.12.0
watchdog==3.0.0
pre-commit==3.5.0
"""
with open(self.project_root / "requirements-dev.txt", 'w') as f:
f.write(dev_requirements)
# Create pre-commit configuration
pre_commit_config = """repos:
- repo: https://github.com/psf/black
rev: 23.11.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
args: [--max-line-length=88]
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--profile", "black"]
"""
with open(self.project_root / ".pre-commit-config.yaml", 'w') as f:
f.write(pre_commit_config)
# Create setup.cfg for tool configuration
setup_cfg = """[flake8]
max-line-length = 88
exclude = .git,__pycache__,venv,build,dist
ignore = E203,W503
[isort]
profile = black
multi_line_output = 3
line_length = 88
[tool:pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts = -v --tb=short
"""
with open(self.project_root / "setup.cfg", 'w') as f:
f.write(setup_cfg)
logger.info("Development tools created")
return True
except Exception as e:
logger.error(f"Failed to create development tools: {e}")
return False
def update_requirements(self):
"""Update requirements.txt with additional development packages"""
try:
logger.info("Updating requirements...")
# Add development packages to main requirements
additional_packages = [
"python-dotenv==1.0.0",
"watchdog==3.0.0"
]
with open(self.project_root / "requirements.txt", 'r') as f:
current_requirements = f.read()
# Add packages if not already present
for package in additional_packages:
if package.split('==')[0] not in current_requirements:
current_requirements += f"\n{package}"
with open(self.project_root / "requirements.txt", 'w') as f:
f.write(current_requirements)
logger.info("Requirements updated")
return True
except Exception as e:
logger.error(f"Failed to update requirements: {e}")
return False
def run_setup(self):
"""Run complete setup process"""
self.print_banner()
steps = [
("Creating configuration structure", self.create_config_structure),
("Updating requirements", self.update_requirements),
("Creating test files", self.create_test_files),
("Creating development tools", self.create_development_tools),
("Creating startup script", self.create_startup_script),
]
for step_name, step_func in steps:
logger.info(f"Running: {step_name}")
if not step_func():
logger.error(f"Failed at step: {step_name}")
return False
# Collect and save configuration
config = self.collect_configuration()
if not self.save_configuration(config):
return False
logger.info("Setup completed successfully!")
logger.info("\nNext steps:")
logger.info("1. Run: python scripts/deploy.py")
logger.info("2. Or run: python start_researchmate.py")
logger.info("3. For development: python scripts/dev_server.py")
return True
def main():
"""Main setup function"""
import argparse
parser = argparse.ArgumentParser(description="ResearchMate Setup System")
parser.add_argument("--skip-config", action="store_true", help="Skip configuration collection")
args = parser.parse_args()
setup = ResearchMateSetup()
if setup.run_setup():
logger.info("Setup completed successfully!")
else:
logger.error("Setup failed!")
sys.exit(1)
if __name__ == "__main__":
main()