16 KiB
Architecture Overview - Odoo LLM Integration
This document provides a comprehensive technical overview of the Odoo LLM Integration architecture, covering the consolidated module structure, core concepts, and development patterns.
Architecture Overview
The Odoo LLM Integration provides a modular framework for integrating Large Language Models into Odoo. The architecture follows a consolidated design with clear separation of concerns, enabling seamless interaction with various AI providers while building sophisticated AI-powered applications.
Core Module Architecture
The system is built around five core modules that form the foundation for all LLM operations:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ llm (Base) │ │ llm_assistant │ │ llm_generate │
│ Foundation │◄───┤ Intelligence │◄───┤ Generation │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
▲ ▲ ▲
│ │ │
┌─────────────────┐ ┌─────────────────┐ │
│ llm_tool │ │ llm_store │ │
│ Actions │ │ Storage │ │
│ │ │ │ │
└─────────────────┘ └─────────────────┘ │
▲ ▲ │
│ │ │
└───────────────────────┴───────────────────────┘
Core Module Responsibilities
llm- Foundation infrastructure and provider abstractionllm_assistant- Intelligence layer with prompt managementllm_generate- Unified content generation APIllm_tool- Function calling and Odoo integrationllm_store- Vector storage and similarity search
Enhanced Mail Message System
Message Extensions
The base llm module extends Odoo's core messaging system with AI-specific capabilities:
# Extended mail.message fields
llm_role = fields.Selection([
('user', 'User'),
('assistant', 'Assistant'),
('tool', 'Tool'),
('system', 'System')
], compute='_compute_llm_role', store=True, index=True)
body_json = fields.Json() # Structured data for tool messages
Message Subtypes
Integrated message subtypes for AI interactions:
llm.mt_user: User messages in AI conversationsllm.mt_assistant: AI-generated responsesllm.mt_tool: Tool execution results and datallm.mt_system: System prompts and configuration messages
Performance Optimization
The llm_role field provides 10x faster message queries by:
- Eliminating expensive subtype lookups with indexed field access
- Enabling efficient conversation history processing
- Simplifying frontend filtering and display logic
- Optimizing database operations for large datasets
Core Models & Concepts
1. LLM.Thread (llm_thread/models/llm_thread.py)
Purpose: Central conversation management and data bridge
class LLMThread(models.Model):
_name = "llm.thread"
_description = "LLM Chat Thread"
_inherit = ["mail.thread"]
Core Function: Serves as the primary link between Odoo business data and AI conversations:
- Storage Backend: Persistent storage for all LLM conversations
- Data Bridge: Links any Odoo record to AI conversation threads
- Conversation Context: Maintains state, configuration, and history
- Multi-Threading: Multiple concurrent conversations per business record
Key Relationships:
Odoo Record (sale.order, project.task, etc.)
↓ (1:many relationship)
LLM Thread(s) - Multiple AI conversations per record
↓ (inherits from mail.thread)
Mail Messages - Conversation history with AI enhancements
PostgreSQL Advisory Locking:
- Prevents concurrent generation conflicts
- Ensures message consistency during streaming
- Database-level coordination for multi-user scenarios
2. LLM.Assistant (llm_assistant/models/llm_assistant.py)
Purpose: Intelligent configuration orchestrator
class LLMAssistant(models.Model):
_name = "llm.assistant"
_description = "LLM Assistant"
_inherit = ["mail.thread"]
Core Function: Provides the intelligence layer that configures HOW to connect Odoo data to AI models:
Configuration Domains:
- Model Selection: AI provider and model specification
- Instruction Templates: System prompts and conversation templates
- Data Mapping: Odoo record transformation to LLM inputs
- Tool Orchestration: Available tools and usage patterns
- Context Management: History trimming and optimization
- Generation Parameters: Content generation configuration
Consolidated Prompt Management:
The assistant module now includes integrated prompt template functionality (previously llm_prompt):
# Integrated prompt fields
prompt_id = fields.Many2one('llm.prompt')
default_values = fields.Json() # Default template arguments
Assistant Types:
- Chat Assistants: Conversational AI with specific personas
- Generation Assistants: Content creation workflows
- Analysis Assistants: Data analysis and insights
- Training Assistants: Model fine-tuning workflows
3. LLM.Provider (llm/models/llm_provider.py)
Purpose: AI service provider abstraction
class LLMProvider(models.Model):
_name = "llm.provider"
_inherit = ["mail.thread"]
_description = "LLM Provider"
Provider Integration Pattern:
def _dispatch(self, method, *args, **kwargs):
"""Dynamic method dispatch to service implementations"""
service_method = f"{self.service}_{method}"
return getattr(self, service_method)(*args, **kwargs)
Supported Providers:
- OpenAI (
llm_openai): GPT models, DALL-E, embeddings - Anthropic (
llm_anthropic): Claude models with tool calling - Ollama (
llm_ollama): Local model deployment - Mistral (
llm_mistral): Mistral AI models - LiteLLM (
llm_litellm): Multi-provider proxy - Replicate (
llm_replicate): Model marketplace access - FAL.ai (
llm_fal_ai): Fast inference API
4. LLM.Tool (llm_tool/models/llm_tool.py)
Purpose: Function calling and Odoo integration
class LLMTool(models.Model):
_name = "llm.tool"
_description = "LLM Tool"
_inherit = ["mail.thread"]
Enhanced Tool System:
- Structured Data Storage: Tool results in
body_jsonformat - MCP Integration: Model Context Protocol compatibility
- Security Framework: User consent and permission system
- Error Handling: Comprehensive error propagation and logging
Tool Message Format:
# New structured format
thread.message_post(
body_json={
"tool_call_id": "call_123",
"function": "search_records",
"arguments": {"model": "sale.order", "domain": [...]},
"result": {"records": [...], "count": 5}
},
llm_role="tool"
)
5. LLM.Store (llm_store/models/llm_store.py)
Purpose: Vector storage abstraction
class LLMStore(models.Model):
_name = "llm.store"
_inherit = ["mail.thread"]
_description = "LLM Vector Store"
Vector Store Implementations:
- ChromaDB (
llm_chroma): HTTP client integration - pgvector (
llm_pgvector): PostgreSQL extension - Qdrant (
llm_qdrant): Qdrant vector database
RAG Integration:
# Vector similarity search
results = store.search_vectors(
collection='knowledge_base',
query_vector=embedding,
limit=5,
filter_metadata={"domain": "sales"}
)
Unified Generation System
Generation API
The llm_generate module provides a unified interface for all content generation:
# Unified generation method
response = thread.generate_response(
user_input="Create a sales report",
generation_type="text", # or "image", "audio", etc.
use_queue=True # Optional background processing
)
Dynamic Form Generation
Automatic form generation based on model schemas:
def get_input_schema(self):
"""Generate form schema for model inputs"""
# Priority order:
# 1. Assistant's prompt schema
# 2. Thread's direct prompt schema
# 3. Model's default schema
Race Condition Fixes
Comprehensive fixes for async loading issues:
- Loading State Management: Proper async handling in UI components
- Schema Synchronization: Automatic prompt argument detection
- Form Stability: Prevention of empty forms during loading
- Context Handling: Improved state management during updates
Knowledge Management System
Consolidated llm_knowledge Module
The llm_knowledge module consolidates functionality from the former llm_resource module:
Consolidated Features:
- Resource Management: Document processing and storage (
llm.resource) - RAG Capabilities: Retrieval-Augmented Generation
- Vector Integration: Embedding and similarity search
- Processing Pipeline: Retrieve → Parse → Chunk → Embed → Index
Processing States:
draft → retrieved → parsed → chunked → ready
API Compatibility: All existing methods preserved:
# Complete processing pipeline
resource.process_resource() # Full pipeline
resource.retrieve() # Get content from source
resource.parse() # Convert to markdown
resource.chunk() # Split into segments
resource.embed() # Generate embeddings
Message System Architecture
Enhanced Message Creation
# Role-based message posting
def message_post(self, body=None, llm_role=None, body_json=None, **kwargs):
"""Enhanced message posting with AI-specific fields"""
# Automatic role computation from subtype
if not llm_role and message_type:
llm_role = self._compute_role_from_subtype(message_type)
# Structured data handling
if body_json:
kwargs['body_json'] = body_json
return super().message_post(body=body, **kwargs)
Streaming Message Updates
Real-time message creation during AI generation:
def message_post_from_stream(self, stream, llm_role, **kwargs):
"""Create and update message from streaming response"""
# Create placeholder message
message = self.message_post(body="", llm_role=llm_role, **kwargs)
# Update content as stream progresses
for chunk in stream:
message.body += chunk
# Real-time UI updates via bus notifications
Provider Integration Patterns
Service Registration
@api.model
def _get_available_services(self):
return super()._get_available_services() + [
('openai', 'OpenAI'),
('anthropic', 'Anthropic'),
('ollama', 'Ollama'),
# Additional providers...
]
Method Implementation Pattern
def openai_chat(self, messages, model=None, stream=False, **kwargs):
"""OpenAI-specific chat implementation"""
def anthropic_chat(self, messages, model=None, stream=False, **kwargs):
"""Anthropic-specific chat implementation"""
Model Context Protocol (MCP) Integration
MCP Server Configuration
class LLMMCPServer(models.Model):
_name = "llm.mcp.server"
_description = "MCP Server Configuration"
name = fields.Char(required=True)
command = fields.Char(required=True) # Server start command
args = fields.Text() # Command arguments
env_vars = fields.Json() # Environment variables
Tool Exposure via MCP
def get_tool_definition(self):
"""Returns MCP-compatible tool definition"""
return {
"name": self.name,
"description": self.description,
"inputSchema": json.loads(self.input_schema or '{}')
}
Frontend Architecture
JavaScript Component Structure
Core Components:
- LLMChatContainer: Main chat interface controller
- LLMChatComposer: Message input and generation forms
- LLMChatThreadHeader: Provider/model/assistant selection
- LLMMediaForm: Dynamic form generation with schema handling
Real-time Features
- Streaming Generation: Live message updates during AI response
- Tool Execution: Visual feedback for function calls
- Context Switching: Dynamic provider/model/assistant changes
- Form Generation: Automatic UI generation from model schemas
Security & Access Control
Role-Based Security
User Groups:
- LLM User (
llm.group_llm_user): Basic access to AI features - LLM Manager (
llm.group_llm_manager): Full administrative access
Tool Security Framework
# Tool consent system
requires_user_consent = fields.Boolean(default=False)
destructive_hint = fields.Boolean(default=False)
read_only_hint = fields.Boolean(default=True)
Record Rules
- Company-based access control for providers
- User-specific thread access restrictions
- Administrative override capabilities
Performance Optimizations
Database Improvements
- Indexed Role Field: 10x faster message queries
- Reduced Subtype Lookups: Direct field access instead of joins
- PostgreSQL Locking: Concurrent operation safety
- Optimized Vector Queries: Efficient similarity search
Frontend Optimizations
- Loading State Management: Prevents UI flashing during async operations
- Schema Caching: Reduced API calls for form generation
- Streaming Updates: Real-time UI updates without full refreshes
- Component Reuse: Efficient component lifecycle management
Development Patterns
Adding New Providers
- Create Provider Module: Inherit from
llm.provider - Implement Service Methods: Follow naming convention
{service}_{method} - Register Service: Add to
_get_available_services() - Add Configuration: Provider-specific settings and UI
Creating Custom Tools
- Inherit Tool Model: Extend
llm.tool - Implement Execute Method:
{implementation}_execute() - Define Schema: Method signature or JSON schema
- Register Implementation: Add to available implementations
Extending Message Handling
- Override Message Post: Custom
message_post()in thread model - Handle Custom Roles: Process custom
llm_rolevalues - Process Structured Data: Handle
body_jsoncontent - Implement Email Patterns: Custom
email_fromlogic
Migration & Compatibility
Module Consolidations
Completed Consolidations:
llm_resource→llm_knowledge(resource management + RAG)llm_prompt→llm_assistant(prompt templates + assistants)llm_mail_message_subtypes→llm(message subtypes)
Migration Scripts: Automatic migration preserves all data:
- Message subtype conversion
- Tool data format migration
- Module dependency updates
- Configuration preservation
Backward Compatibility
- API Compatibility: All existing methods continue to work
- Data Preservation: Zero data loss during consolidations
- Configuration Migration: Settings automatically transferred
- Progressive Enhancement: New features don't break existing workflows
This architecture provides a robust, scalable foundation for building sophisticated AI-powered applications within Odoo, with clear patterns for extension and a strong emphasis on performance, security, and maintainability.