Entities¶
src.entities
¶
src.entities.Conversation
¶
SQLAlchemy entity for conversation sessions with LLM generation parameters.
Represents a chat session with a specific LLM, storing messages, generation settings, and conversation metadata. Enforces parameter validation via SQLAlchemy validators.
Relationships
- messages: One-to-many with Message (cascade delete).
- llm: Many-to-one with Llm (which model is used).
Example
from src.entities.Conversation import Conversation
conv = Conversation( llm_id=42, name="Python Programming Help", temperature=0.7, top_p=0.9, max_tokens=2048 )
Conversation
¶
Bases: Base
SQLAlchemy model for conversation sessions with generation parameter validation.
Stores chat sessions with LLM-specific generation settings. Each conversation maintains its own temperature, top_p, and max_tokens parameters. Messages are stored separately with cascade delete.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (auto-increment). |
|
llm_id |
Foreign key to Llm, NULLABLE (server-side SET NULL on model delete). A conversation survives the deletion of its model and can be switched to another one (#225). |
|
created_at |
Conversation creation timestamp (server-stamped). |
|
updated_at |
Last modification timestamp (server-stamped, auto-updated). |
|
temperature |
Sampling temperature (0.0-2.0, validated). |
|
top_p |
Nucleus sampling threshold (0.0-1.0, validated). |
|
max_tokens |
Maximum tokens to generate (1-32768, validated). |
|
custom_prompt |
Optional additional system instructions. |
|
name |
Conversation title (default "New Conversation"). |
|
web_search_enabled |
Per-conversation web-search toggle. |
|
reasoning_effort |
How much the model may deliberate (validated). |
|
compaction_threshold |
Share of the working window, in percent, at which the conversation compacts (50-90 step 5, validated). |
|
messages |
Relationship to Message entities (ordered by id = insertion order). |
|
llm |
Relationship to Llm entity (which model). |
|
message_count |
int
|
Hybrid property returning number of messages. |
last_message_time |
Optional[datetime]
|
Hybrid property returning last message timestamp. |
Example
conv = Conversation(llm_id=42, name="Debug Session", temperature=0.3, max_tokens=4096) print(conv.message_count) # 0 (messages are added via MessageRepository)
__repr__()
¶
last_message_time()
¶
Get timestamp of most recent message.
Returns:
| Type | Description |
|---|---|
Optional[datetime]
|
Last message timestamp, or conversation created_at if no messages. |
Source code in backend/src/entities/Conversation.py
message_count()
¶
Get total number of messages in this conversation.
Returns:
| Type | Description |
|---|---|
int
|
Message count (user + assistant messages). |
validate_compaction_threshold(key, compaction_threshold)
¶
Validate the compaction threshold is a whole percent on the scale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Column name ("compaction_threshold"). |
required |
compaction_threshold
|
int
|
Percentage to validate. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Validated percentage. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If it is not an int in COMPACTION_THRESHOLDS (50-90, step 5); a bool, a float or a string is rejected. |
Source code in backend/src/entities/Conversation.py
validate_max_tokens(key, max_tokens)
¶
Validate max_tokens parameter is within allowed range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Column name ("max_tokens"). |
required |
max_tokens
|
int
|
Max_tokens value to validate. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Validated max_tokens value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If max_tokens not in range [1, 32768]. |
Source code in backend/src/entities/Conversation.py
validate_reasoning_effort(key, reasoning_effort)
¶
Validate the reasoning effort is one of the five levels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Column name ("reasoning_effort"). |
required |
reasoning_effort
|
str
|
Level to validate. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Validated level. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the level is not in REASONING_EFFORT_LEVELS. |
Source code in backend/src/entities/Conversation.py
validate_temperature(key, temperature)
¶
Validate temperature parameter is within allowed range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Column name ("temperature"). |
required |
temperature
|
float
|
Temperature value to validate. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Validated temperature value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If temperature not in range [0.0, 2.0]. |
Source code in backend/src/entities/Conversation.py
validate_top_p(key, top_p)
¶
Validate top_p parameter is within allowed range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Column name ("top_p"). |
required |
top_p
|
float
|
Top_p value to validate. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Validated top_p value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If top_p not in range [0.0, 1.0]. |
Source code in backend/src/entities/Conversation.py
src.entities.DownloadJob
¶
SQLAlchemy entity for LLM download job tracking with progress and ETA.
Represents a background download task for fetching and quantizing LLMs from HuggingFace. Tracks progress, timing, file paths, and error states.
Example
from src.entities.DownloadJob import DownloadJobModel
job = DownloadJobModel( remote_model_id="meta-llama/Llama-3-8B-Instruct", remote_model_link="https://huggingface.co/meta-llama/Llama-3-8B-Instruct", local_model_id=42, status="pending" )
DownloadJobModel
¶
Bases: Base
SQLAlchemy model for LLM download jobs with progress tracking and file paths.
Tracks the lifecycle of downloading and quantizing an LLM from HuggingFace, including progress percentage, ETA, temp/final file paths, and error messages.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (auto-increment). |
|
remote_model_id |
HuggingFace repo ID (e.g., "meta-llama/Llama-3-8B-Instruct"). |
|
local_model_id |
Database ID of temp Llm entry created during download. |
|
remote_model_link |
HuggingFace URL or API endpoint. |
|
temp_local_model_link |
Temp directory for full-precision download. |
|
final_local_model_link |
Final directory for quantized model. |
|
status |
Job state - "pending", "running", "completed", "failed", "cancelled". |
|
error_message |
Exception message if status="failed". |
|
created_at |
Job creation timestamp (server default). |
|
updated_at |
Last status update timestamp (auto-updated). |
|
total_bytes |
Total download size in bytes. |
|
progress |
Download progress percentage (0.0-100.0). |
|
total_time_elapsed |
Seconds elapsed since job start. |
|
time_left |
Estimated seconds remaining. |
Constraints
- status must be one of: pending, running, completed, failed, cancelled.
- progress must be between 0.0 and 100.0.
- total_bytes, total_time_elapsed, time_left must be non-negative.
- remote_model_id and remote_model_link must not be empty.
Example
job = DownloadJobModel(remote_model_id="Qwen/Qwen2.5-7B-Instruct", status="pending") job.progress = 50.0 job.time_left = 120.5
validate_non_negative(key, value)
¶
Ensure numeric fields are non-negative.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated (one of: total_bytes, total_time_elapsed, time_left). |
required | |
value
|
Proposed numeric value. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
The validated non-negative value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is negative. |
Source code in backend/src/entities/DownloadJob.py
validate_not_empty(key, value)
¶
Ensure required string fields are not empty.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated (one of: remote_model_id, remote_model_link). |
required | |
value
|
Proposed string value. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
The validated stripped string value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is empty or whitespace-only. |
Source code in backend/src/entities/DownloadJob.py
validate_progress(key, value)
¶
Ensure progress is between 0.0 and 100.0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated ('progress'). |
required | |
value
|
Proposed float value for download progress percentage. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
The validated progress value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If progress is outside 0.0-100.0 range. |
Source code in backend/src/entities/DownloadJob.py
validate_status(key, value)
¶
Ensure status is one of the allowed values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated ('status'). |
required | |
value
|
Proposed string value for job status. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
The validated status value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If status is not in allowed list. |
Source code in backend/src/entities/DownloadJob.py
src.entities.KBJob
¶
SQLAlchemy entity for Knowledge Base creation/update job tracking.
Tracks background ingestion tasks (extract → chunk → embed → index) during KB assistant creation or update. Monitors status and error messages.
Example
from src.entities.KBJob import KBJobModel
job = KBJobModel( base_model_id=42, new_model_id=108, kb_id=15, status="pending" )
KBJobModel
¶
Bases: Base
SQLAlchemy model for Knowledge Base creation/update job tracking.
The id columns are real foreign keys with ON DELETE SET NULL: a job is an audit record of its state machine and must survive the deletion of the entities it produced (cleanup of a failed creation deletes the specialized LLM and the KB — the failed job remains, refs nulled by the server).
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (auto-increment). |
|
base_model_id |
Base LLM used as foundation (nulled if deleted). |
|
new_model_id |
Specialized LLM created for this KB; equals base_model_id for update jobs (nulled if deleted). |
|
kb_id |
KnowledgeBase being created/updated (nulled if deleted). |
|
status |
Job state - "pending", "running", "completed", "failed". |
|
error_message |
Exception message if status="failed". |
|
created_at |
Job creation timestamp (server-stamped). |
|
updated_at |
Last status update timestamp (server-stamped). |
Example
job = KBJobModel(base_model_id=42, new_model_id=108, kb_id=15, status="running")
src.entities.KnowledgeBase
¶
SQLAlchemy entity for Knowledge Base registry.
A KnowledgeBase is the business-level container for a RAG corpus: it owns the
ingested source files (documents → KnowledgeDocument rows) and the
specialized assistant built on top of it (llm, one-to-one). The chunks +
embeddings themselves live in the pgvector-managed rag.kb_chunks table
(langchain-postgres), filtered by kb_id at retrieval time.
Relationships
- documents: One-to-many with KnowledgeDocument (server-side CASCADE).
- llm: One-to-one with Llm (specialized assistant using this KB).
KnowledgeBase
¶
Bases: Base
Registry row for one Knowledge Base.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (auto-increment). |
|
created_at |
Server-stamped creation timestamp. |
|
documents |
Ingested source files (KnowledgeDocument rows). |
|
llm |
Specialized Llm entity attached to this KB (one-to-one). |
src.entities.KnowledgeDocument
¶
SQLAlchemy entity for documents ingested into a Knowledge Base.
One row per source file dropped into a KB. Replaces the FAISS-era
KnowledgeBase.file_names_list JSON blob: documents are first-class rows
with a content hash (dedup), a size, and a per-file ingestion status. The
actual text chunks + embeddings live in the pgvector-managed rag.kb_chunks
table (langchain-postgres), keyed back here through a document_id metadata
column.
Statuses
active: extracted, chunked, and indexed — retrievable.empty: extracted but produced zero indexable chunks (blank/whitespace file or a parser that yielded no text); nothing searchable was added.failed: ingestion raised; error surfaced via the KB job.pending_vision: image or scanned PDF accepted but not yet readable (OCR/VLM tiers land in a later release); zero chunks indexed.
KnowledgeDocument
¶
Bases: Base
A single source file tracked inside a Knowledge Base.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (auto-increment). |
|
kb_id |
Owning KnowledgeBase (server-side ON DELETE CASCADE). |
|
name |
Original file name (display + extension routing). |
|
content_hash_sha256 |
SHA-256 of the file bytes; UNIQUE per KB (dedup). |
|
size_bytes |
File size at ingestion time. |
|
status |
Per-file ingestion state (see module docstring). |
|
created_at |
Server-stamped ingestion timestamp. |
validate_status(key, value)
¶
Ensure status is one of the allowed ingestion states.
Source code in backend/src/entities/KnowledgeDocument.py
src.entities.Llm
¶
SQLAlchemy entity for LLM model catalog and metadata.
This entity represents the complete lifecycle of an LLM model in Erudi: - Remote models: Browsable from HuggingFace (local=0). - Downloading: Temporary placeholder during download (local=2). - Local models: Downloaded and ready for inference (local=1). - KB-attached: Specialized assistants with Knowledge Base (is_attached_to_kb=True).
Relationships
- kb: One-to-one with KnowledgeBase (if is_attached_to_kb=True).
Example
from src.entities.Llm import Llm
Create remote model entry¶
llm = Llm( name="Llama-3-8B-Instruct", local=0, link="meta-llama/Meta-Llama-3-8B-Instruct", type="llama", param_size=8.0, quantized=False )
Llm
¶
Bases: Base
SQLAlchemy model for LLM catalog entries with download state and KB attachment.
Represents a single LLM model in the database, tracking its download status, metadata, and optional Knowledge Base attachment. Models can be remote (browsable), downloading (temporary), or local (ready for inference).
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (auto-increment). |
|
name |
Human-readable model name (e.g., "Llama-3-8B-Instruct"). |
|
local |
Download state - 0=remote (HuggingFace), 1=local (ready), 2=downloading. |
|
link |
HuggingFace repo ID (if remote) or local filesystem path (if local). |
|
type |
Model family (e.g., "llama", "qwen", "mistral", "gemma"). |
|
description |
Optional user annotation or HuggingFace description. |
|
model_metadata |
JSON string with additional metadata (vocab size, context length). |
|
quantized |
Boolean - False=not quantized (full precision), True=pre-quantized (MLX/GGUF format). |
|
param_size |
Model size in billions of parameters (2, 4, 8, 16, 70, etc.), or None when the size could not be measured (#201). |
|
is_attached_to_kb |
Boolean - False=standalone model, True=specialized KB assistant. |
|
kb_id |
Foreign key to KnowledgeBase (if is_attached_to_kb=True). |
|
kb |
Relationship to KnowledgeBase entity (one-to-one). |
Constraints
- local must be 0 (remote), 1 (local), or 2 (downloading).
- param_size must be positive when known (None allowed for unknown).
- name must not be empty.
Example
llm = Llm(name="Qwen2.5-7B", local=1, link="backend/data/models/42", type="qwen", param_size=7.0) db.add(llm) db.commit()
validate_artifact_size_bytes(key, value)
¶
A known artifact size is a positive byte count; None means unknown.
Zero or negative is never a measurement (an empty directory walk, a listing without sizes) and must not masquerade as one -- callers store None in that case so the UI keeps its estimate.
Source code in backend/src/entities/Llm.py
validate_local(key, value)
¶
Ensure local is 0 (remote), 1 (ready), or 2 (downloading).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated ('local'). |
required | |
value
|
Proposed integer value for download state. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
The validated local state value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not 0, 1, or 2. |
Source code in backend/src/entities/Llm.py
validate_name(key, value)
¶
Ensure name is not empty.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated ('name'). |
required | |
value
|
Proposed value for the name field. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
Stripped name value if valid. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If name is empty or whitespace-only. |
Source code in backend/src/entities/Llm.py
validate_param_size(key, value)
¶
Ensure a known param_size is positive; allow None for unknown (#201).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated ('param_size'). |
required | |
value
|
Proposed float value for parameter size in billions, or None when the size could not be measured. |
required |
Returns:
| Type | Description |
|---|---|
|
Optional[float]: The validated parameter size, or None. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a non-null param_size is zero or negative. |
Source code in backend/src/entities/Llm.py
validate_type(key, value)
¶
Ensure type is not empty.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated ('type'). |
required | |
value
|
Proposed string value for model family type. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
Stripped type value if valid. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If type is empty or whitespace-only. |
Source code in backend/src/entities/Llm.py
src.entities.Message
¶
SQLAlchemy entity for individual messages within conversations.
Represents a single user or assistant message with metadata for starring and
timestamp tracking. Messages belong to a Conversation; insertion order is the
primary key (PostgreSQL's now() is frozen per transaction, so timestamps
can collide within one request — never order by them).
Relationships
- conversation: Many-to-one with Conversation (parent session).
Example
from src.entities.Message import Message
msg = Message( conversation_id=42, sender="user", content="What is quantum computing?", starred=False )
Message
¶
Bases: Base
SQLAlchemy model for conversation messages with starring support.
Stores individual messages within conversations, tracking sender, content, server-stamped timestamp, and starred status (for memory injection).
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (auto-increment) — also the insertion order. |
|
conversation_id |
Foreign key to Conversation (server-side CASCADE). |
|
sender |
Message sender - "user" or "llm" (validated). |
|
content |
Message text content (non-empty, no length cap). |
|
timestamp |
Message creation timestamp (server-stamped). |
|
starred |
True if user starred for importance (used in memory injection). |
|
trace |
Optional JSON list of the assistant turn's non-answer stream
events (thinking / tool_call / tool_result, and the compaction
|
|
conversation |
Relationship to Conversation entity. |
Example
msg = Message(conversation_id=42, sender="user", content="Hello!") print(msg.starred) # False (starring is done via MessageRepository)
__repr__()
¶
String representation of the message.
validate_content(key, content)
¶
Validate content is non-empty.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Column name ("content"). |
required |
content
|
str
|
Content value to validate. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Validated content value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If content is empty or whitespace-only. |
Source code in backend/src/entities/Message.py
validate_sender(key, sender)
¶
Validate sender is either 'user' or 'llm'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Column name ("sender"). |
required |
sender
|
str
|
Sender value to validate. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Validated sender value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If sender not in ['user', 'llm']. |
Source code in backend/src/entities/Message.py
src.entities.StartupVariables
¶
SQLAlchemy entity for application startup state tracking.
Stores persistent UI state flags across app restarts, such as whether the welcome popup has been shown, and model seeding state to avoid unnecessary API calls.
Example
from src.entities.StartupVariables import StartupVariables from datetime import datetime
vars = StartupVariables( welcome_popup_has_already_displayed=True, models_seeded=True, last_seeded_at=datetime.now() )
StartupVariables
¶
Bases: Base
SQLAlchemy model for application startup state persistence.
Stores UI state flags and model seeding state that persist across app restarts. Singleton entity (only one row in table).
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (singleton - only one row). |
|
welcome_popup_has_already_displayed |
Boolean - True if welcome popup shown to user. |
|
models_seeded |
Boolean - True if base/derived models have been seeded. |
|
last_seeded_at |
DateTime - Timestamp of last successful model seeding. |
|
offline_mode |
Boolean - True if last startup detected no internet connection. |
Constraints
- welcome_popup_has_already_displayed must be Boolean (enforced by validator).
- models_seeded must be Boolean (enforced by validator).
- offline_mode must be Boolean (enforced by validator).
Example
vars = db.query(StartupVariables).first() if not vars.welcome_popup_has_already_displayed: ... show_welcome_popup() ... vars.welcome_popup_has_already_displayed = True ... db.commit()
Check if models need reseeding (every 3 days)¶
from datetime import datetime, timedelta if not vars.models_seeded or (datetime.now() - vars.last_seeded_at) > timedelta(days=3): ... await seed_models() ... vars.models_seeded = True ... vars.last_seeded_at = datetime.now() ... db.commit()
validate_boolean_flags(key, value)
¶
Ensure boolean flags are actually Boolean type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated. |
required | |
value
|
Proposed Boolean value. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
The validated Boolean value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not a Boolean. |
Example
vars.models_seeded = True # Valid vars.models_seeded = "yes" # Raises ValueError
Source code in backend/src/entities/StartupVariables.py
src.entities.HardwareProfile
¶
SQLAlchemy entity for backend-agnostic hardware profile.
Stores comprehensive hardware specifications and performance scores for all backends (MLX, CUDA, CPU). Uses discriminated fields with backend_type to determine which fields are populated. All backend-specific fields are nullable.
Architecture
- Common fields: Populated for all backends (CPU, memory, scores)
- MLX-specific: chip_model, mlx_gpu_cores, mps_available, neural_engine_tops
- CUDA-specific: cuda_cores, cuda_version, compute_capability, vram_*
- CPU-only: Minimal fields (no GPU/accelerator)
Example
from src.entities.HardwareProfile import HardwareProfile
MLX backend¶
hw_mlx = HardwareProfile( backend_type="mlx", cpu_model="Apple M3 Max", total_memory_gb=128.0, mlx_chip_model="M3 Max", mlx_gpu_cores=40, mps_available=True, unified_memory=True )
CUDA backend¶
hw_cuda = HardwareProfile( backend_type="cuda", cpu_model="Intel Xeon", total_memory_gb=64.0, cuda_cores=10752, cuda_version="12.1", vram_total_gb=24.0 )
HardwareProfile
¶
Bases: Base
SQLAlchemy model for backend-agnostic hardware profile (singleton).
Comprehensive hardware specifications supporting MLX (Apple Silicon), CUDA (NVIDIA), and CPU backends. Backend-specific fields are nullable and populated based on backend_type discriminator.
Table Design
- Singleton pattern: Only one row in database (id=1)
- backend_type determines which optional fields are populated
- Frontend checks backend_type to render appropriate UI
Common Attributes (All Backends): id: Primary key (singleton, always 1). backend_type: Backend discriminator ("mlx", "cuda", "cpu"). cpu_model: CPU model string. total_memory_gb: Total system memory in GB. available_memory_gb: Currently available memory in GB. disk_total_gb: Total disk space in GB. disk_available_gb: Available disk space in GB. global_inference_score: Inference performance score (0-100). global_inference_label: Inference label (Poor/Medium/Good/Very Good). cpu_score: CPU-specific score (0-100). memory_score: Memory-specific score (0-100). system_platform: OS platform (Darwin/Linux/Windows).
Common Accelerator Attributes (MLX & CUDA): gpu_name: Accelerator name (Apple GPU / NVIDIA GPU model). estimated_tflops: Estimated peak TFLOPS (FP32). memory_bandwidth_gbs: Memory bandwidth in GB/s. architecture: Architecture identifier (3nm/5nm for MLX, Ampere/Ada for CUDA). gpu_score: GPU/accelerator performance score (0-100).
MLX-Specific Attributes (Apple Silicon): mlx_chip_model: Apple chip model (M1/M2/M3/M4 + variant). mlx_gpu_cores: Number of GPU cores (8-76). mps_available: Metal Performance Shaders availability. neural_engine_tops: Neural Engine performance (TOPS). unified_memory: Unified memory architecture flag.
CUDA-Specific Attributes (NVIDIA): cuda_cores: Number of CUDA cores. cuda_version: CUDA runtime version (e.g., "12.1"). compute_capability: Compute capability (e.g., "8.6"). vram_total_gb: Total dedicated VRAM in GB. vram_available_gb: Available VRAM in GB.
Performance Tracking
cpu_performance_units: CPU performance metric (computed). performance_breakdown: Detailed JSON with component scores. created_at: Profile creation timestamp. updated_at: Last update timestamp.
Constraints
- backend_type must be "mlx", "cuda", or "cpu"
- Singleton enforced at application level (id=1)
Example
MLX profile¶
hw = HardwareProfile( ... backend_type="mlx", ... cpu_model="Apple M3 Max", ... mlx_chip_model="M3 Max", ... mlx_gpu_cores=40, ... unified_memory=True ... ) db.add(hw) db.commit()
src.entities.UserSettings
¶
SQLAlchemy entity for global user settings.
Singleton table (one row) holding app-wide user preferences, mirroring the
StartupVariables singleton pattern. First occupant: the global web-search
toggle (issue #310) — the DEFAULT for new conversations. Each conversation
copies this value at creation and owns its flag afterwards; changing the
global setting never retro-affects existing conversations. It also carries the
interface language, the automatic-update preference, the inference
backend the app runs models on, and the other defaults new conversations copy
(reasoning effort, compaction threshold).
Example
from src.entities.UserSettings import UserSettings
settings = UserSettings(web_search_enabled=False)
UserSettings
¶
Bases: Base
SQLAlchemy model for the user-settings singleton.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
Primary key (singleton - only one row). |
|
web_search_enabled |
Boolean - global default for the web_search agent tool (#310). False by default: a web search egresses the user's query, so the local-first product keeps it strictly opt-in. |
|
language |
Interface language code (#385), one of SUPPORTED_LANGUAGES. "en" by default; the frontend derives the first value from the OS locale and persists it here so it survives restarts. |
|
auto_update_enabled |
Boolean - whether the Electron main process may check for, download and install a new version on its own. True by default, so an install that never touches the setting behaves as it always has; turning it off stops the update traffic entirely. |
|
inference_backend |
One of INFERENCE_BACKENDS. "auto" by default, so hardware detection decides; "cpu" makes the app run models on the CPU build even when an NVIDIA GPU is present. Read once per boot, after the migrations, so the choice needs an app restart to apply. |
|
default_reasoning_effort |
One of REASONING_EFFORT_LEVELS, the GLOBAL default new conversations copy at creation. "medium" by default: the level at which a model that reasons naturally behaves exactly as it did before the setting existed. Arena panels, which have no conversation row, read this value on every turn. |
|
default_compaction_threshold |
One of COMPACTION_THRESHOLDS (50-90, step 5), the GLOBAL share of the working window, in percent, at which new conversations compact; each copies it at creation. 80 by default, the value every row that predates the column holds. Arena panels never compact, so nothing else reads it. |
Constraints
- web_search_enabled must be a Boolean (enforced by validator).
- auto_update_enabled must be a Boolean (enforced by validator).
- language must be one of SUPPORTED_LANGUAGES (enforced by validator).
- inference_backend must be one of INFERENCE_BACKENDS (validator).
- default_reasoning_effort must be one of REASONING_EFFORT_LEVELS.
- default_compaction_threshold must be one of COMPACTION_THRESHOLDS.
validate_boolean_flags(key, value)
¶
Ensure boolean flags are actually Boolean type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Column name being validated. |
required | |
value
|
Proposed Boolean value. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
The validated Boolean value. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not a Boolean. |
Source code in backend/src/entities/UserSettings.py
validate_default_compaction_threshold(key, value)
¶
Ensure the global compaction threshold is a whole percent on the scale.
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not an int in COMPACTION_THRESHOLDS (a bool, a float or a string is rejected). |
Source code in backend/src/entities/UserSettings.py
validate_default_reasoning_effort(key, value)
¶
Ensure the global reasoning effort is one of the five levels.
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not in REASONING_EFFORT_LEVELS. |
Source code in backend/src/entities/UserSettings.py
validate_inference_backend(key, value)
¶
Ensure the inference backend is one of the supported values.
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not in INFERENCE_BACKENDS. |
Source code in backend/src/entities/UserSettings.py
validate_language(key, value)
¶
Ensure the language is one of the supported interface languages.
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is not in SUPPORTED_LANGUAGES. |