⚙️ Process System

Процессы — это шаблоны для выполнения LLM-задач. Хранятся в БД, управляются через контракты, запускаются через process_runner.

Что такое Процесс

Процесс — это DB-сущность, которая описывает:

📝 Prompt Template

Шаблон для рендеринга user prompt

🎯 Model Selection

Default model + min_rank

📊 Context Sources

RAG, personal data, chat history

🔄 Fallback Chain

Timeout, memory errors, model fallback

🔄 Execution Flow

От input_text до ответа

1. Load Process
get_process_by_code()
2. Build Context
RAG / personal / history
3. Select Agent
agent_selection.py
4. Render Prompt
Template + variables
5. Pick Model
best available + rank
6. LLM Call
Ollama / GLM

💻 Код: execute_process_for_runtime

# bot/app/services/process_runner.py
async def execute_process_for_runtime(
    runtime, *,
    process_code: str,
    input_text: str,
    user_db_id: Optional[int],
    chat_db_id: Optional[int],
    rag_context: Optional[str] = None,
    run_id: Optional[str] = None,
    model_tier: Optional[str] = None,  # "free" | "paid"
) -> ProcessExecutionResult:

    # 1. Определяем лимиты по tier
    if model_tier == "paid":
        max_tokens = 4096  # paid tier
    else:
        max_tokens = 512   # free tier

    # 2. Загружаем процесс из DB
    process = await runtime.db.get_process_by_code(process_code)

    # 3. Строим контекст (RAG, personal data, history)
    if not rag_context:
        if process.metadata.get("rag"):
            rag_context = await build_rag_context(query=input_text)
        if process.metadata.get("personal_data"):
            docs = await db.list_table_documents(user_id=user_db_id)
            rag_context += format_personal_docs(docs)

    # 4. Выбираем агента (если есть)
    agent_sel = await select_agent(db, process_code=process_code)
    if agent_sel:
        system_prompt = agent_sel["assembled_system_prompt"]

    # 5. Рендерим prompt
    rendered_prompt = render_process_prompt(
        process_code=process_code,
        prompt_template=process["prompt_template"],
        input_text=input_text,
        rag_context=rag_context,
    )

    # 6. Выбираем модель
    process_model = process.get("default_model") or "phi4-mini"
    best_available = runtime._pick_best_chat_model(
        models, preferred=process_model, min_rank=min_rank
    )

    # 7. LLM call с timeout
    response = await asyncio.wait_for(
        runtime.chat_llm(
            model=best_available,
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": rendered_prompt},
            ],
            options={"num_predict": max_tokens, "temperature": 0.2},
        ),
        timeout=90.0,
    )

    # 8. Логируем LLM call
    await db.log_llm_call(
        scope=f"process:{process_code}",
        model=best_available,
        latency_ms=...,
    )

    return ProcessExecutionResult(
        text=response["message"]["content"],
        model=best_available,
        raw=response,
        degraded=False,
    )

📚 Context Sources

RAGVector Search

Semantic search по embeddings из document_chunks.

metadata.rag = true включает
max_distance = 0.45 фильтр
snippet_max_chars = 700
PERSONALUser Data

Данные из table_document пользователя.

metadata.personal_data = true
• Формат: [type] key: value (date)
• Limit: 20 docs default
HISTORYChat Context

Последние сообщения из чата (default fallback).

• Используется если нет RAG/personal
context_messages = 10
message_max_chars = 200

🔄 Fallback Chain

Что происходит при ошибках:

TIMEOUT

Пробует lighter модели с меньшим num_predict

Если все fail — возвращает degraded ответ из template

OOM

Memory error — переключается на модели с меньшим VRAM

Уменьшает num_predict, decay factor = 0.85

404 MODEL

Модель не найдена — выбирает лучшую доступную

Может понизить min_rank если нужно

🎯 Model Selection

Model Rank

phi4-minirank 1
llama3.2:3brank 2
llama3.1:8brank 3
glm-4.5-airrank 5 (cloud)

Short Input Fast-track

Если len(input_text) < 80:

fast_model_for_short_inputs = "phi4-mini"

Экономит ресурсы для простых запросов

🗄️ DB Schema

processes

id (serial)
code (text, unique)
name (text)
description (text)
prompt_template (text)
default_model (text)
metadata (jsonb)
├ rag: bool
├ personal_data: bool
├ num_predict: int
status (text) # draft/active/archived
created_by → users.id

process_runs

id (uuid)
process_id → processes.id
requested_by → users.id
chat_id → chats.id
input_text (text)
input_payload (jsonb)
status (text)
├ queued, running, waiting_user
├ succeeded, degraded, failed
output_text (text)
model_used (text)
latency_ms (int)
created_at, finished_at

📊 Status Flow

queuedrunningwaiting_usersucceeded
degradedfailedcancelled

💡 Примеры процессов

BUILTINdirect_chat

Обычный диалог с ботом. Без RAG, без special context.

model: phi4-mini | tokens: 512
RAGtravel_research

Поиск информации о поездках. RAG-enabled, ищет в document_chunks.

model: llama3.2:3b | tokens: 1024 | rag: true
PERSONALpersonal_assistant

Персональный помощник с доступом к user data из table_document.

model: phi4-mini | tokens: 512 | personal_data: true

🔧 Troubleshooting

"Process not found"

Проверьте processes.code в DB и status = 'active'.

Degraded response

Смотрите llm_calls table, проверьте timeout и memory errors.

Медленный RAG

Проверьте document_chunks size и embeddings. Уменьшите limit или max_distance.

🔗 Связанные страницы