diff --git a/config/settings.yaml b/config/settings.yaml index a703c42..9c1b018 100644 --- a/config/settings.yaml +++ b/config/settings.yaml @@ -2,9 +2,10 @@ # LLM Settings llm: + provider: deepseek # Supported values: openai, deepseek temperature: 0.5 max_tokens: 4096 - model: deepseek-r1 + model: deepseek-r1 # Model name specific to the provider # ArXiv Client Settings arxiv: diff --git a/requirements.txt b/requirements.txt index 762bbb7..e0422ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,14 @@ -langchain==0.2.1 +langchain==0.3.17 +langchain-community>=0.0.10 +openai>=1.0.0 arxiv==2.1.0 -unstructured==0.12.2 -deepseek-ai==1.0.0 +unstructured==0.16.17 +deepseek==1.0.0 faiss-cpu==1.8.0 sqlalchemy==2.0.30 python-dotenv==1.0.0 pyyaml==6.0.1 -pypdf==4.2.0 +pypdf==5.2.0 redis==5.0.3 -chromadb==0.5.0 +chromadb==0.6.3 requests>=2.31.0 \ No newline at end of file diff --git a/src/analysis/analysis_engine.py b/src/analysis/analysis_engine.py index 4ce84b5..5345554 100644 --- a/src/analysis/analysis_engine.py +++ b/src/analysis/analysis_engine.py @@ -1,9 +1,8 @@ from langchain.schema import Document from langchain.chains.summarize import load_summarize_chain -from langchain_community.llms import OpenAI from typing import List, Dict import yaml -import os +from .llm_provider import create_llm_provider class TechnicalConceptExtractor: def __init__(self, llm): @@ -31,15 +30,17 @@ class PaperAnalyzer: def __init__(self, config_path: str = "config/settings.yaml"): with open(config_path) as f: self.config = yaml.safe_load(f) - - self.llm = OpenAI( - temperature=0.5, # More conservative temperature for academic analysis - model_name="deepseek-r1", - api_key=os.getenv("DEEPSEEK_API_KEY"), - base_url="https://api.deepseek.com/v1", - max_tokens=4096 # Increased token limit for complex papers + + # Create LLM provider based on configuration + llm_config = self.config.get("llm", {}) + provider_type = llm_config.get("provider", "openai") + self.llm = create_llm_provider(provider_type, llm_config).get_llm() + + # Initialize analysis components + self.summary_chain = load_summarize_chain( + self.llm, + chain_type=self.config.get("analysis", {}).get("summary_chain_type", "map_reduce") ) - self.summary_chain = load_summarize_chain(self.llm, chain_type="map_reduce") self.concept_extractor = TechnicalConceptExtractor(self.llm) self.insight_aggregator = InsightAggregator(self.llm) diff --git a/src/analysis/llm_provider.py b/src/analysis/llm_provider.py new file mode 100644 index 0000000..0c4c253 --- /dev/null +++ b/src/analysis/llm_provider.py @@ -0,0 +1,50 @@ +from abc import ABC, abstractmethod +from typing import Dict, Optional +from langchain.base_language import BaseLanguageModel +from langchain_community.llms import OpenAI +import os + +class LLMProvider(ABC): + """Abstract base class for LLM providers""" + @abstractmethod + def get_llm(self) -> BaseLanguageModel: + """Return configured LLM instance""" + pass + +class OpenAIProvider(LLMProvider): + def __init__(self, config: Dict): + self.config = config + + def get_llm(self) -> BaseLanguageModel: + return OpenAI( + temperature=self.config.get("temperature", 0.5), + model_name=self.config.get("model", "gpt-3.5-turbo"), + api_key=os.getenv("OPENAI_API_KEY"), + max_tokens=self.config.get("max_tokens", 2048) + ) + +class DeepseekProvider(LLMProvider): + def __init__(self, config: Dict): + self.config = config + + def get_llm(self) -> BaseLanguageModel: + return OpenAI( + temperature=self.config.get("temperature", 0.5), + model_name=self.config.get("model", "deepseek-r1"), + api_key=os.getenv("DEEPSEEK_API_KEY"), + base_url="https://api.deepseek.com/v1", + max_tokens=self.config.get("max_tokens", 4096) + ) + +def create_llm_provider(provider_type: str, config: Dict) -> LLMProvider: + """Factory function to create LLM provider instances""" + providers = { + "openai": OpenAIProvider, + "deepseek": DeepseekProvider + } + + provider_class = providers.get(provider_type.lower()) + if not provider_class: + raise ValueError(f"Unsupported LLM provider: {provider_type}") + + return provider_class(config) \ No newline at end of file