haiku.rag/haiku_rag_slim/haiku/rag/config/models.py
2026-02-24 09:55:40 +02:00

213 lines
6.1 KiB
Python

from pathlib import Path
from typing import Literal
from pydantic import BaseModel, Field
from haiku.rag.utils import get_default_data_dir
class ModelConfig(BaseModel):
"""Configuration for a language model.
Attributes:
provider: Model provider (ollama, openai, anthropic, etc.)
name: Model name/identifier
base_url: Optional base URL for OpenAI-compatible servers (vLLM, LM Studio, etc.)
enable_thinking: Control reasoning behavior (true/false/None for default)
temperature: Sampling temperature (0.0 to 1.0+)
max_tokens: Maximum tokens to generate
"""
provider: str = "ollama"
name: str = "gpt-oss"
base_url: str | None = None
enable_thinking: bool | None = None
temperature: float | None = None
max_tokens: int | None = None
class EmbeddingModelConfig(BaseModel):
"""Configuration for an embedding model.
Attributes:
provider: Model provider (ollama, openai, voyageai, cohere, sentence-transformers)
name: Model name/identifier
vector_dim: Vector dimensions produced by the model
base_url: Optional base URL for OpenAI-compatible servers (vLLM, LM Studio, etc.)
"""
provider: str = "ollama"
name: str = "qwen3-embedding:4b"
vector_dim: int = 2560
base_url: str | None = None
class StorageConfig(BaseModel):
data_dir: Path = Field(default_factory=get_default_data_dir)
auto_vacuum: bool = True
vacuum_retention_seconds: int = 86400
class MonitorConfig(BaseModel):
directories: list[Path] = []
ignore_patterns: list[str] = []
include_patterns: list[str] = []
delete_orphans: bool = False
class LanceDBConfig(BaseModel):
uri: str = ""
api_key: str = ""
region: str = ""
class EmbeddingsConfig(BaseModel):
model: EmbeddingModelConfig = Field(default_factory=EmbeddingModelConfig)
class RerankingConfig(BaseModel):
model: ModelConfig | None = None
class QAConfig(BaseModel):
model: ModelConfig = Field(
default_factory=lambda: ModelConfig(
provider="ollama",
name="gpt-oss",
enable_thinking=False,
)
)
max_iterations: int = 2
max_concurrency: int = 1
class ResearchConfig(BaseModel):
model: ModelConfig = Field(
default_factory=lambda: ModelConfig(
provider="ollama",
name="gpt-oss",
enable_thinking=False,
)
)
max_iterations: int = 3
max_concurrency: int = 1
class RLMConfig(BaseModel):
model: ModelConfig = Field(
default_factory=lambda: ModelConfig(
provider="ollama",
name="gpt-oss",
enable_thinking=False,
)
)
code_timeout: float = 60.0
max_output_chars: int = 50_000
class PictureDescriptionConfig(BaseModel):
"""Configuration for VLM-based picture description."""
enabled: bool = False
model: ModelConfig = Field(
default_factory=lambda: ModelConfig(
provider="ollama",
name="ministral-3",
)
)
timeout: int = 90
max_tokens: int = 200
class ConversionOptions(BaseModel):
"""Options for document conversion."""
# OCR options
do_ocr: bool = True
force_ocr: bool = False
ocr_engine: Literal[
"auto", "easyocr", "ocrmac", "rapidocr", "tesserocr", "tesseract"
] = "auto"
ocr_lang: list[str] = []
# Table options
do_table_structure: bool = True
table_mode: Literal["fast", "accurate"] = "accurate"
table_cell_matching: bool = True
# Image options
images_scale: float = 2.0
generate_page_images: bool = True
generate_picture_images: bool = False
# VLM picture description
picture_description: PictureDescriptionConfig = Field(
default_factory=PictureDescriptionConfig
)
class ProcessingConfig(BaseModel):
chunk_size: int = 256
converter: str = "docling-local"
chunker: str = "docling-local"
chunker_type: str = "hybrid"
chunking_tokenizer: str = "Qwen/Qwen3-Embedding-0.6B"
chunking_merge_peers: bool = True
chunking_use_markdown_tables: bool = False
conversion_options: ConversionOptions = Field(default_factory=ConversionOptions)
class SearchConfig(BaseModel):
limit: int = 5
context_radius: int = 0
max_context_items: int = 10
max_context_chars: int = 10000
vector_index_metric: Literal["cosine", "l2", "dot"] = "cosine"
vector_refine_factor: int = 30
class OllamaConfig(BaseModel):
base_url: str = Field(
default_factory=lambda: __import__("os").environ.get(
"OLLAMA_BASE_URL", "http://localhost:11434"
)
)
class DoclingServeConfig(BaseModel):
base_url: str = "http://localhost:5001"
api_key: str = ""
class ProvidersConfig(BaseModel):
ollama: OllamaConfig = Field(default_factory=OllamaConfig)
docling_serve: DoclingServeConfig = Field(default_factory=DoclingServeConfig)
class PromptsConfig(BaseModel):
domain_preamble: str = ""
qa: str | None = None
synthesis: str | None = None
picture_description: str = (
"Describe this image for a blind user. "
"State the image type (screenshot, chart, photo, etc.), "
"what it depicts, any visible text, and key visual details. "
"Be concise and accurate."
)
class AppConfig(BaseModel):
environment: str = "production"
storage: StorageConfig = Field(default_factory=StorageConfig)
monitor: MonitorConfig = Field(default_factory=MonitorConfig)
lancedb: LanceDBConfig = Field(default_factory=LanceDBConfig)
embeddings: EmbeddingsConfig = Field(default_factory=EmbeddingsConfig)
reranking: RerankingConfig = Field(default_factory=RerankingConfig)
qa: QAConfig = Field(default_factory=QAConfig)
research: ResearchConfig = Field(default_factory=ResearchConfig)
rlm: RLMConfig = Field(default_factory=RLMConfig)
processing: ProcessingConfig = Field(default_factory=ProcessingConfig)
search: SearchConfig = Field(default_factory=SearchConfig)
providers: ProvidersConfig = Field(default_factory=ProvidersConfig)
prompts: PromptsConfig = Field(default_factory=PromptsConfig)