AI generated first iteration
This commit is contained in:
117
app/llm/client.py
Normal file
117
app/llm/client.py
Normal file
@@ -0,0 +1,117 @@
|
||||
"""LLM client abstraction for pluggable LLM providers."""
|
||||
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from app.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LLMClient:
|
||||
"""
|
||||
Abstraction layer for LLM providers.
|
||||
|
||||
Supports: OpenAI, Ollama, LM Studio, or offline/mock mode.
|
||||
Can be extended to support other providers.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: Optional[str] = None,
|
||||
api_key: Optional[str] = None,
|
||||
base_url: Optional[str] = None,
|
||||
model: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Initialize LLM client.
|
||||
|
||||
Args:
|
||||
provider: "openai", "ollama", "lm_studio", or None for mock
|
||||
api_key: API key for provider
|
||||
base_url: Base URL for API (for ollama/lm_studio)
|
||||
model: Model identifier
|
||||
"""
|
||||
self.provider = provider or settings.LLM_PROVIDER
|
||||
self.api_key = api_key or settings.LLM_API_KEY
|
||||
self.base_url = base_url or settings.LLM_BASE_URL
|
||||
self.model = model or settings.LLM_MODEL
|
||||
|
||||
logger.info(f"LLMClient initialized with provider: {self.provider}")
|
||||
|
||||
async def generate(self, prompt: str, max_tokens: int = 200) -> str:
|
||||
"""
|
||||
Generate text from a prompt.
|
||||
|
||||
Args:
|
||||
prompt: Input prompt
|
||||
max_tokens: Maximum tokens to generate
|
||||
|
||||
Returns:
|
||||
Generated text
|
||||
|
||||
TODO: Implement OpenAI API integration
|
||||
TODO: Implement Ollama API integration
|
||||
TODO: Implement LM Studio API integration
|
||||
"""
|
||||
if self.provider == "openai":
|
||||
return await self._generate_openai(prompt, max_tokens)
|
||||
elif self.provider == "ollama":
|
||||
return await self._generate_ollama(prompt, max_tokens)
|
||||
elif self.provider == "lm_studio":
|
||||
return await self._generate_lm_studio(prompt, max_tokens)
|
||||
else:
|
||||
return self._generate_mock(prompt)
|
||||
|
||||
async def _generate_openai(self, prompt: str, max_tokens: int) -> str:
|
||||
"""
|
||||
Generate using OpenAI API.
|
||||
|
||||
TODO: Implement using openai library
|
||||
- Create client with api_key
|
||||
- Call ChatCompletion
|
||||
- Handle errors and retries
|
||||
"""
|
||||
logger.warning("OpenAI provider not yet implemented (stub)")
|
||||
return self._generate_mock(prompt)
|
||||
|
||||
async def _generate_ollama(self, prompt: str, max_tokens: int) -> str:
|
||||
"""
|
||||
Generate using Ollama local API.
|
||||
|
||||
TODO: Implement using httpx or requests
|
||||
- POST to base_url/api/generate
|
||||
- Stream response and accumulate
|
||||
- Handle model pulling if needed
|
||||
"""
|
||||
logger.warning("Ollama provider not yet implemented (stub)")
|
||||
return self._generate_mock(prompt)
|
||||
|
||||
async def _generate_lm_studio(self, prompt: str, max_tokens: int) -> str:
|
||||
"""
|
||||
Generate using LM Studio local API.
|
||||
|
||||
TODO: Implement OpenAI-compatible API calls
|
||||
- POST to base_url/v1/chat/completions
|
||||
- Use same logic as OpenAI but with local endpoint
|
||||
"""
|
||||
logger.warning("LM Studio provider not yet implemented (stub)")
|
||||
return self._generate_mock(prompt)
|
||||
|
||||
def _generate_mock(self, prompt: str) -> str:
|
||||
"""
|
||||
Generate deterministic mock response (no API needed).
|
||||
|
||||
Used when no provider is configured or for testing.
|
||||
"""
|
||||
logger.debug(f"Mock generation for prompt: {prompt[:50]}...")
|
||||
|
||||
# Simple deterministic responses for testing
|
||||
if "hello" in prompt.lower():
|
||||
return "Greetings, traveler! Welcome to The Sanctum."
|
||||
elif "help" in prompt.lower():
|
||||
return "I am here to guide your discourse through the streams."
|
||||
elif "topic" in prompt.lower():
|
||||
return "The archives speak of many topics worthy of discussion."
|
||||
else:
|
||||
return "An interesting observation. Tell me more."
|
||||
Reference in New Issue
Block a user