ragflow/personal_analyze/02-SERVICE-LAYER
Claude 2f61760051
docs: Add document and knowledgebase service analysis documentation
- Add document_service_analysis.md: comprehensive analysis of document
  lifecycle management including insert, remove, parse, progress tracking
- Add knowledgebase_service_analysis.md: dataset management and access
  control analysis with permission model, parser configuration
2025-11-27 09:54:39 +00:00
..
dialog_service_analysis.md docs: Add detailed backend module analysis documentation 2025-11-26 11:10:54 +00:00
document_service_analysis.md docs: Add document and knowledgebase service analysis documentation 2025-11-27 09:54:39 +00:00
knowledgebase_service_analysis.md docs: Add document and knowledgebase service analysis documentation 2025-11-27 09:54:39 +00:00
llm_service_analysis.md docs: Add detailed backend module analysis documentation 2025-11-26 11:10:54 +00:00
README.md docs: Add detailed backend module analysis documentation 2025-11-26 11:10:54 +00:00
task_service_analysis.md docs: Add detailed backend module analysis documentation 2025-11-26 11:10:54 +00:00

02-SERVICE-LAYER - Business Logic Layer

Tổng Quan

Service Layer là tầng business logic của RAGFlow, xử lý tất cả operations phức tạp và orchestrate các components khác nhau.

Kiến Trúc Service Layer

┌─────────────────────────────────────────────────────────────────────────┐
│                          API LAYER (Blueprints)                          │
└────────────────────────────────┬────────────────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                          SERVICE LAYER                                   │
│                                                                          │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐         │
│  │ DialogService   │  │ DocumentService │  │ KnowledgebaseS. │         │
│  │                 │  │                 │  │                 │         │
│  │ • chat()        │  │ • insert()      │  │ • create()      │         │
│  │ • ask()         │  │ • remove()      │  │ • update()      │         │
│  │ • gen_mindmap() │  │ • get_list()    │  │ • get_by_id()   │         │
│  └────────┬────────┘  └────────┬────────┘  └────────┬────────┘         │
│           │                    │                    │                   │
│  ┌────────┴────────┐  ┌────────┴────────┐  ┌────────┴────────┐         │
│  │ TaskService     │  │ FileService     │  │ LLMService      │         │
│  │                 │  │                 │  │ (LLMBundle)     │         │
│  │ • queue_tasks() │  │ • upload()      │  │                 │         │
│  │ • get_task()    │  │ • download()    │  │ • encode()      │         │
│  │ • update_prog() │  │ • delete()      │  │ • chat()        │         │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘         │
│                                                                          │
└────────────────────────────────┬────────────────────────────────────────┘
                                 │
          ┌──────────────────────┼──────────────────────┐
          │                      │                      │
          ▼                      ▼                      ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│    DATABASE     │    │   VECTOR STORE  │    │     STORAGE     │
│    (MySQL)      │    │ (Elasticsearch) │    │     (MinIO)     │
└─────────────────┘    └─────────────────┘    └─────────────────┘

Cấu Trúc Thư Mục

/api/db/
├── db_models.py              # Peewee ORM models (54KB)
├── db_utils.py               # Database utilities
├── init_data.py              # Initial data seeding
├── runtime_config.py         # Runtime configuration
│
└── services/
    ├── dialog_service.py     # Chat/RAG service (37KB) ⭐
    ├── document_service.py   # Document management (39KB) ⭐
    ├── knowledgebase_service.py  # KB operations (21KB)
    ├── task_service.py       # Task queue (20KB) ⭐
    ├── file_service.py       # File operations (22KB)
    ├── llm_service.py        # LLM abstraction ⭐
    ├── user_service.py       # User management
    ├── conversation_service.py   # Conversation storage
    ├── canvas_service.py     # Canvas/workflow storage
    ├── connector_service.py  # Data source connectors
    ├── api_service.py        # API token management
    ├── search_service.py     # Search operations
    └── common_service.py     # Base service class

Files Trong Module Này

File Mô Tả
dialog_service_analysis.md Core RAG Chat - Retrieval, reranking, generation
document_service_analysis.md Document lifecycle management
task_service_analysis.md Background task queue system
llm_service_analysis.md LLM abstraction và token tracking
knowledgebase_service_analysis.md Knowledge base operations

Core Patterns

1. CommonService Base Class

class CommonService:
    """Base class for all services with common CRUD operations."""

    model = None  # Override in subclass

    @classmethod
    @DB.connection_context()
    def query(cls, cols=None, reverse=None, order_by=None, **kwargs):
        """
        Flexible query builder.

        Args:
            cols: Columns to select
            reverse: Reverse sort order
            order_by: Sort field
            **kwargs: Filter conditions

        Returns:
            List of matching records
        """
        query = cls.model.select(*cols) if cols else cls.model.select()

        for k, v in kwargs.items():
            query = query.where(getattr(cls.model, k) == v)

        if order_by:
            query = query.order_by(
                getattr(cls.model, order_by).desc() if reverse
                else getattr(cls.model, order_by)
            )

        return list(query)

    @classmethod
    @DB.connection_context()
    def get_by_id(cls, id):
        """Get record by primary key."""
        try:
            record = cls.model.get_by_id(id)
            return True, record
        except DoesNotExist:
            return False, None

    @classmethod
    @DB.connection_context()
    def save(cls, **kwargs):
        """Insert new record."""
        return cls.model.create(**kwargs)

    @classmethod
    @DB.connection_context()
    def update_by_id(cls, id, data):
        """Update record by ID."""
        data["update_time"] = int(time.time() * 1000)
        data["update_date"] = datetime.now()
        return cls.model.update(data).where(cls.model.id == id).execute()

2. Transaction Handling

# Atomic operations
with DB.atomic():
    for item in items:
        cls.model.update(data).where(...).execute()

# Connection context for query isolation
@DB.connection_context()
def critical_operation():
    # Automatic connection management
    pass

# Database locking for critical sections
with DB.lock("operation_name", timeout=60):
    # Only one process can execute this
    pass

3. Service-to-Service Communication

# Services call other services
class DialogService:
    @classmethod
    def chat(cls, dialog, messages, **kwargs):
        # Get knowledge bases
        kbs = KnowledgebaseService.get_by_ids(dialog.kb_ids)

        # Get embedding model
        embd_mdl = LLMBundle(tenant_id, LLMType.EMBEDDING, kb.embd_id)

        # Retrieve documents
        kbinfos = retriever.retrieval(query, embd_mdl, ...)

        # Generate response
        for token in chat_mdl.chat_streamly(...):
            yield token

Database Models Overview

Core Models

# User & Multi-tenancy
User          # id, email, password, access_token
Tenant        # id, name, llm_id, embd_id
UserTenant    # user_id, tenant_id, role

# Knowledge Management
Knowledgebase # id, tenant_id, name, embd_id, parser_config
Document      # id, kb_id, name, status, progress, chunk_num
File          # id, tenant_id, name, location, type
File2Document # file_id, document_id

# Chat & Dialog
Dialog        # id, tenant_id, kb_ids, llm_id, prompt_config
Conversation  # id, dialog_id, message (JSON array)

# Task Queue
Task          # id, doc_id, progress, chunk_ids

# API Integration
APIToken      # id, tenant_id, token, dialog_id

JSON Fields Usage

# Parser configuration
Document.parser_config = {
    "chunk_token_num": 512,
    "delimiter": "\n。;!?",
    "layout_recognize": "DeepDOC"
}

# LLM settings
Dialog.llm_setting = {
    "temperature": 0.7,
    "max_tokens": 2048,
    "top_p": 1.0
}

# Prompt configuration
Dialog.prompt_config = {
    "system": "You are a helpful assistant...",
    "prologue": "Hi! How can I help?",
    "quote": True,
    "reasoning": False
}

Key Service Interactions

┌─────────────────────────────────────────────────────────────────────────┐
│                     SERVICE INTERACTION FLOW                             │
└─────────────────────────────────────────────────────────────────────────┘

[Document Upload]
    API
     │
     ├──► FileService.upload_document()
     │       │
     │       ├──► Store file in MinIO
     │       ├──► Create File record
     │       └──► Create Document record
     │
     └──► TaskService.queue_tasks()
             │
             └──► Create Task records
             └──► Push to Redis queue

[Document Processing]
    TaskExecutor (Background)
     │
     ├──► TaskService.get_task()
     ├──► DocumentService.get_by_id()
     ├──► Parse & chunk document
     ├──► LLMBundle.encode() → Generate embeddings
     ├──► Store chunks in Elasticsearch
     ├──► TaskService.update_progress()
     └──► DocumentService.increment_chunk_num()

[Chat/RAG]
    API
     │
     └──► DialogService.chat()
             │
             ├──► KnowledgebaseService.get_by_ids()
             ├──► LLMBundle (embedding) → Query vector
             ├──► retriever.retrieval() → Hybrid search
             ├──► LLMBundle (rerank) → Rerank results
             ├──► LLMBundle (chat) → Generate response
             └──► ConversationService.save()

Performance Patterns

1. Batch Operations

def bulk_create_chunks(chunks: List[dict]):
    """Bulk insert for efficiency."""
    with db.atomic():
        for batch in chunked(chunks, 1000):
            Chunk.insert_many(batch).execute()

2. Connection Pooling

db = PooledMySQLDatabase(
    database,
    max_connections=32,
    stale_timeout=300,
    **connection_params
)

3. Caching Strategies

# Metadata caching for filtering
@cache_result(ttl=600)
def get_meta_by_kbs(kb_ids):
    """Cache metadata index for 10 minutes."""
    return DocumentService.get_meta_by_kbs(kb_ids)

4. Token Tracking

class LLMBundle:
    def encode(self, texts):
        embeddings, tokens = self.mdl.encode(texts)
        # Track token usage
        TenantLLMService.increase_usage(
            self.tenant_id,
            LLMType.EMBEDDING,
            tokens
        )
        return embeddings

Error Handling

class ServiceException(Exception):
    """Base exception for service errors."""
    pass

class DocumentNotFoundError(ServiceException):
    pass

class InsufficientQuotaError(ServiceException):
    pass

# Usage
try:
    result = DocumentService.get_by_id(doc_id)
    if not result[0]:
        raise DocumentNotFoundError(f"Document {doc_id} not found")
except DocumentNotFoundError as e:
    return get_json_result(code=404, message=str(e))
  • /api/db/db_models.py - All database models
  • /rag/llm/*.py - LLM implementations
  • /rag/nlp/search.py - Search/retrieval logic