Initial SQL-only 1C adapter baseline

This commit is contained in:
2026-07-22 03:03:47 +03:00
commit e2503b77e7
545 changed files with 184711 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
# Core
Общее ядро LLM-платформы.
`core` отвечает за переиспользуемые возможности:
- реестр моделей;
- инференс;
- обучение и дообучение;
- eval-тесты;
- GPU deployment;
- хранение;
- мониторинг.
Прикладная логика задач должна находиться в `plugins`.
+1
View File
@@ -0,0 +1 @@
"""Shared core platform modules."""
+45
View File
@@ -0,0 +1,45 @@
# Core Deploy
Общие правила развертывания.
GPU workload target: `docker-gpu.cin.su`.
Infrastructure/lightweight proxy target: `docker.cin.su`.
В репозитории храним только воспроизводимую конфигурацию и документацию. Секреты, токены и пароли не коммитим.
Локальные модели и RAG-артефакты проверяются отдельно перед переносом или
Docker-запуском: `docs/runbooks/artifact-portability.md`.
Локальная консоль управления запускается командой:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/run_management_console.ps1
```
Runbook: `docs/runbooks/management-console.md`.
1C MCP proxy:
```text
docs/runbooks/adapter-1c-mcp.md
core/deploy/docker/adapter-1c-mcp/compose.yaml
```
1C REST adapter on GPU host:
```text
core/deploy/docker-gpu/adapter-1c/compose.yaml
```
1C agent service (подпроект):
```text
core/deploy/docker/1c-agent/compose.yaml
docs/runbooks/1c-agent.md
```
The current container is read-first and route-index backed. It serves
`http://docker-gpu.cin.su:8011`, keeps the route index in the
`adapter-1c_adapter-1c-data` Docker volume, and is used by
`adapter-1c-mcp` through `ONEC_ADAPTER_URL`.
+7
View File
@@ -0,0 +1,7 @@
# Docker GPU Deployment
Целевой хост для GPU-развертываний: `docker-gpu.cin.su`.
Здесь будут находиться compose-файлы, env-шаблоны и инструкции для запуска GPU-сервисов.
Секреты должны передаваться через окружение, секрет-хранилище или настройки хоста, но не через git.
@@ -0,0 +1,11 @@
ADAPTER_1C_IMAGE=adapter-1c-rest:latest
ADAPTER_1C_CONTAINER_NAME=adapter-1c-rest
ADAPTER_1C_HOST_PORT=8011
# Live SQL connections. Keep real credentials outside git.
# Example:
# ONEC_SQL_BASES_JSON={"upo_test":{"server":"sql-host","database":"upo_test","user":"configured_login","password_env":"ONEC_SQL_PASSWORD_UPO_TEST"}}
# ONEC_SQL_PASSWORD_UPO_TEST=put-this-only-in-a-real-non-committed-env-file
ONEC_SQL_BASES_JSON=
# Optional path inside the container to a JSON file with the same shape as ONEC_SQL_BASES_JSON.
ONEC_SQL_BASES_JSON_FILE=/data/onec-sql-bases.json
@@ -0,0 +1,32 @@
name: adapter-1c
services:
adapter-1c-rest:
build:
context: ../../../../plugins/1c
dockerfile: connector/Dockerfile
image: ${ADAPTER_1C_IMAGE:-adapter-1c-rest:latest}
container_name: ${ADAPTER_1C_CONTAINER_NAME:-adapter-1c-rest}
restart: unless-stopped
ports:
- "${ADAPTER_1C_HOST_PORT:-8011}:8011"
volumes:
- adapter-1c-data:/data
environment:
ONEC_ADAPTER_HOST: 0.0.0.0
ONEC_ADAPTER_PORT: 8011
ONEC_ADAPTER_SERVICE_TOKEN: ${ONEC_ADAPTER_SERVICE_TOKEN:-}
ONEC_ADAPTER_ALLOW_UNAUTHENTICATED_ADMIN: ${ONEC_ADAPTER_ALLOW_UNAUTHENTICATED_ADMIN:-true}
ONEC_SQL_BASES_JSON: ${ONEC_SQL_BASES_JSON:-}
ONEC_SQL_BASES_JSON_FILE: ${ONEC_SQL_BASES_JSON_FILE:-/data/onec-sql-bases.json}
ONEC_INFOBASE_USER_ADMIN_BASES_JSON: ${ONEC_INFOBASE_USER_ADMIN_BASES_JSON:-}
ONEC_INFOBASE_USER_ADMIN_BASES_JSON_FILE: ${ONEC_INFOBASE_USER_ADMIN_BASES_JSON_FILE:-/data/onec-infobase-user-admin.json}
ONEC_INFOBASE_USER_ADMIN_TOKEN_UPO_TEST: ${ONEC_INFOBASE_USER_ADMIN_TOKEN_UPO_TEST:-}
ONEC_INFOBASE_USER_ADMIN_ALLOW_UNAUTHENTICATED: ${ONEC_INFOBASE_USER_ADMIN_ALLOW_UNAUTHENTICATED:-false}
ONEC_REPOSITORY_RUNNER_TOKEN: ${ONEC_REPOSITORY_RUNNER_TOKEN:-}
ONEC_ADAPTER_ENABLE_EXTERNAL_1C: ${ONEC_ADAPTER_ENABLE_EXTERNAL_1C:-false}
ONEC_REPOSITORY_REQUEST_TTL_SECONDS: ${ONEC_REPOSITORY_REQUEST_TTL_SECONDS:-86400}
ONEC_REPOSITORY_CONFIRMATION_TTL_SECONDS: ${ONEC_REPOSITORY_CONFIRMATION_TTL_SECONDS:-7200}
volumes:
adapter-1c-data:
@@ -0,0 +1,17 @@
# Copy to .env on the deployment host and adjust values there.
# Do not commit real tokens, private paths, or credentials.
LLAMA_CONTAINER_NAME=llm-llama-devstral-1c
LLAMA_IMAGE=ghcr.io/ggml-org/llama.cpp:server-cuda
LLAMA_HOST_PORT=8080
LLAMA_MODEL_PATH=/models/gguf/1c/devstral-small-2-24b-instruct-2512-q4_k_m/mistralai_Devstral-Small-2-24B-Instruct-2512-Q4_K_M.gguf
LLAMA_SERVED_MODEL_NAME=devstral-1c-q4
LLAMA_CTX_SIZE=32768
LLAMA_GPU_LAYERS=999
LLAMA_THREADS=8
LLAMA_PARALLEL=1
LLAMA_FIT=off
LLAMA_REASONING=off
LLAMA_REASONING_FORMAT=none
LLAMA_CHAT_TEMPLATE=mistral-v7-tekken
HOST_MODELS_DIR=/models
@@ -0,0 +1,43 @@
services:
llama-cpp:
image: ${LLAMA_IMAGE:-ghcr.io/ggml-org/llama.cpp:server-cuda}
container_name: ${LLAMA_CONTAINER_NAME:-llm-llama-devstral-1c}
restart: unless-stopped
ports:
- "${LLAMA_HOST_PORT:-8080}:8080"
volumes:
- ${HOST_MODELS_DIR:-/models}:/models
command:
- --host
- 0.0.0.0
- --port
- "8080"
- --model
- ${LLAMA_MODEL_PATH}
- --alias
- ${LLAMA_SERVED_MODEL_NAME:-devstral-1c-q4}
- --ctx-size
- ${LLAMA_CTX_SIZE:-32768}
- --n-gpu-layers
- ${LLAMA_GPU_LAYERS:-999}
- --threads
- ${LLAMA_THREADS:-8}
- --parallel
- ${LLAMA_PARALLEL:-1}
- --fit
- ${LLAMA_FIT:-off}
- --reasoning
- ${LLAMA_REASONING:-off}
- --reasoning-format
- ${LLAMA_REASONING_FORMAT:-none}
- --chat-template
- ${LLAMA_CHAT_TEMPLATE:-mistral-v7-tekken}
- --skip-chat-parsing
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities:
- gpu
@@ -0,0 +1,19 @@
# Qwen3-Coder Q6 GPU llama.cpp settings for docker-gpu.cin.su.
# This model is too large to keep online together with SDXL/vLLM on a 24 GiB RTX 4090.
LLAMA_CONTAINER_NAME=llm-llama-qwen3-coder-q6-test
LLAMA_IMAGE=ghcr.io/ggml-org/llama.cpp:server-cuda
LLAMA_HOST_PORT=8081
LLAMA_MODEL_PATH=/models/gguf/1c/qwen3-coder-30b-a3b-instruct-q6_k/Qwen3-Coder-30B-A3B-Instruct-Q6_K.gguf
LLAMA_SERVED_MODEL_NAME=qwen3-coder-1c-q6
LLAMA_CTX_SIZE=8192
LLAMA_GPU_LAYERS=auto
LLAMA_THREADS=12
LLAMA_PARALLEL=1
LLAMA_FIT=on
LLAMA_REASONING=auto
LLAMA_REASONING_FORMAT=none
LLAMA_CHAT_TEMPLATE=chatml
# Optional future LoRA path after converting the trained adapter to GGUF for llama.cpp:
# LLAMA_LORA_PATH=/models/adapters/1c/qwen3-coder-30b-a3b-1c-lora-v1.gguf
HOST_MODELS_DIR=Z:/LLM/models
@@ -0,0 +1,24 @@
services:
model-chat-ui:
image: ${MODEL_CHAT_IMAGE:-vllm/vllm-openai:v0.10.2}
container_name: ${MODEL_CHAT_CONTAINER_NAME:-llm-model-chat-ui}
restart: unless-stopped
ports:
- "${MODEL_CHAT_HOST_PORT:-8765}:8765"
volumes:
- ${HOST_APP_DIR:-Z:/LLM/model-chat-app}:/app
- ${HOST_MODELS_DIR:-Z:/LLM/models}:/models:ro
- ${HOST_REPORTS_DIR:-Z:/LLM/reports}:/reports
environment:
MODEL_CHAT_REPORT_ROOT: /reports
working_dir: /app
entrypoint:
- python3
command:
- scripts/model_chat_server.py
- --host
- 0.0.0.0
- --port
- "8765"
- --static-dir
- /app
@@ -0,0 +1,25 @@
services:
train-1c-lora:
image: ${TRAINING_IMAGE:-pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime}
container_name: llm-train-1c-lora
working_dir: /workspace
shm_size: 16gb
volumes:
- ${HOST_WORKSPACE_DIR:-/workspace/LLM}:/workspace
- ${HOST_MODELS_DIR:-/models}:/models
command:
- bash
- -lc
- |
pip install -r requirements-training.txt &&
python scripts/preflight_1c_training.py --config ${TRAINING_CONFIG:-/workspace/plugins/1c/training/configs/qwen3-coder-30b-a3b-lora.yaml} &&
if [ "${PREFLIGHT_ONLY:-0}" = "1" ]; then exit 0; fi &&
python scripts/train_1c_lora.py --config ${TRAINING_CONFIG:-/workspace/plugins/1c/training/configs/qwen3-coder-30b-a3b-lora.yaml}
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities:
- gpu
@@ -0,0 +1,4 @@
TRAINING_IMAGE=pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime
HOST_WORKSPACE_DIR=Z:/LLM/model-chat-app
HOST_MODELS_DIR=Z:/LLM/models
TRAINING_CONFIG=/workspace/plugins/1c/training/configs/qwen3-coder-30b-a3b-lora.yaml
@@ -0,0 +1,38 @@
name: llm-transformers-audio
services:
audio-api:
image: ${TRANSFORMERS_IMAGE:-vllm/vllm-openai:v0.10.2}
container_name: ${TRANSFORMERS_CONTAINER_NAME:-llm-transformers-audio}
restart: unless-stopped
ipc: host
ports:
- "${TRANSFORMERS_HOST_PORT:-8020}:8020"
environment:
HF_HOME: /root/.cache/huggingface
MODEL_PATH: ${MODEL_PATH:-/models/audio/whisper-large-v3-turbo}
SERVED_MODEL_NAME: ${SERVED_MODEL_NAME:-whisper-large-v3-turbo}
PORT: "8020"
LOAD_ON_START: ${LOAD_ON_START:-0}
volumes:
- ${HOST_APP_DIR:-Z:/LLM/model-chat-app}:/app
- ${HOST_MODELS_DIR:-Z:/LLM/models}:/models
- ${HOST_HF_CACHE_DIR:-Z:/LLM/models/cache/huggingface}:/root/.cache/huggingface
working_dir: /app
entrypoint: python3
command:
- scripts/transformers_plugin_server.py
- --plugin
- audio
- --host
- 0.0.0.0
- --port
- "8020"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities:
- gpu
@@ -0,0 +1,9 @@
HOST_APP_DIR=Z:/LLM/model-chat-app
HOST_MODELS_DIR=Z:/LLM/models
HOST_HF_CACHE_DIR=Z:/LLM/models/cache/huggingface
TRANSFORMERS_IMAGE=vllm/vllm-openai:v0.10.2
TRANSFORMERS_CONTAINER_NAME=llm-transformers-audio
TRANSFORMERS_HOST_PORT=8020
MODEL_PATH=/models/audio/whisper-large-v3-turbo
SERVED_MODEL_NAME=whisper-large-v3-turbo
LOAD_ON_START=0
@@ -0,0 +1,10 @@
FROM vllm/vllm-openai:v0.10.2
RUN python3 -m pip install --no-cache-dir \
"diffusers>=0.35.0" \
"transformers>=4.51.0" \
"accelerate>=1.0.0" \
safetensors \
pillow
WORKDIR /app
@@ -0,0 +1,42 @@
name: llm-transformers-image
services:
image-api:
image: ${TRANSFORMERS_IMAGE:-llm-transformers-image:latest}
build:
context: ../../../../
dockerfile: core/deploy/docker-gpu/transformers/image.Dockerfile
container_name: ${TRANSFORMERS_CONTAINER_NAME:-llm-transformers-image}
restart: unless-stopped
ipc: host
ports:
- "${TRANSFORMERS_HOST_PORT:-8040}:8040"
environment:
HF_HOME: /root/.cache/huggingface
MODEL_PATH: ${MODEL_PATH:-/models/image/sdxl-base-1.0}
EDIT_MODEL_PATH: ${EDIT_MODEL_PATH:-/models/image/sdxl-inpainting-1.0}
SERVED_MODEL_NAME: ${SERVED_MODEL_NAME:-sdxl-image}
PORT: "8040"
LOAD_ON_START: ${LOAD_ON_START:-1}
BACKGROUND_LOAD_ON_START: ${BACKGROUND_LOAD_ON_START:-1}
volumes:
- ${HOST_APP_DIR:-Z:/LLM/model-chat-app}:/app
- ${HOST_MODELS_DIR:-Z:/LLM/models}:/models
- ${HOST_HF_CACHE_DIR:-Z:/LLM/models/cache/huggingface}:/root/.cache/huggingface
working_dir: /app
entrypoint: /bin/sh
command:
- -lc
- >
exec python3 scripts/transformers_plugin_server.py
--plugin image
--host 0.0.0.0
--port 8040
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities:
- gpu
@@ -0,0 +1,11 @@
HOST_APP_DIR=Z:/LLM/model-chat-app
HOST_MODELS_DIR=Z:/LLM/models
HOST_HF_CACHE_DIR=Z:/LLM/models/cache/huggingface
TRANSFORMERS_IMAGE=llm-transformers-image:latest
TRANSFORMERS_CONTAINER_NAME=llm-transformers-image
TRANSFORMERS_HOST_PORT=8040
MODEL_PATH=/models/image/sdxl-base-1.0
EDIT_MODEL_PATH=/models/image/sdxl-inpainting-1.0
SERVED_MODEL_NAME=sdxl-image
LOAD_ON_START=1
BACKGROUND_LOAD_ON_START=1
@@ -0,0 +1,11 @@
HOST_APP_DIR=Z:/LLM/model-chat-app
HOST_MODELS_DIR=Z:/LLM/models
HOST_HF_CACHE_DIR=Z:/LLM/models/cache/huggingface
TRANSFORMERS_IMAGE=llm-transformers-image:latest
TRANSFORMERS_CONTAINER_NAME=llm-transformers-image
TRANSFORMERS_HOST_PORT=8040
MODEL_PATH=/models/image/qwen-image-edit
EDIT_MODEL_PATH=/models/image/qwen-image-edit
SERVED_MODEL_NAME=qwen-image-edit
LOAD_ON_START=0
BACKGROUND_LOAD_ON_START=0
@@ -0,0 +1,38 @@
name: llm-transformers-translation
services:
translation-api:
image: ${TRANSFORMERS_IMAGE:-vllm/vllm-openai:v0.10.2}
container_name: ${TRANSFORMERS_CONTAINER_NAME:-llm-transformers-translation}
restart: unless-stopped
ipc: host
ports:
- "${TRANSFORMERS_HOST_PORT:-8010}:8010"
environment:
HF_HOME: /root/.cache/huggingface
MODEL_PATH: ${MODEL_PATH:-/models/translation/lmt-60-4b}
SERVED_MODEL_NAME: ${SERVED_MODEL_NAME:-lmt-60-4b}
PORT: "8010"
LOAD_ON_START: ${LOAD_ON_START:-0}
volumes:
- ${HOST_APP_DIR:-Z:/LLM/model-chat-app}:/app
- ${HOST_MODELS_DIR:-Z:/LLM/models}:/models
- ${HOST_HF_CACHE_DIR:-Z:/LLM/models/cache/huggingface}:/root/.cache/huggingface
working_dir: /app
entrypoint: python3
command:
- scripts/transformers_plugin_server.py
- --plugin
- translation
- --host
- 0.0.0.0
- --port
- "8010"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities:
- gpu
@@ -0,0 +1,9 @@
HOST_APP_DIR=Z:/LLM/model-chat-app
HOST_MODELS_DIR=Z:/LLM/models
HOST_HF_CACHE_DIR=Z:/LLM/models/cache/huggingface
TRANSFORMERS_IMAGE=vllm/vllm-openai:v0.10.2
TRANSFORMERS_CONTAINER_NAME=llm-transformers-translation
TRANSFORMERS_HOST_PORT=8010
MODEL_PATH=/models/translation/lmt-60-4b
SERVED_MODEL_NAME=lmt-60-4b
LOAD_ON_START=0
@@ -0,0 +1,38 @@
name: llm-transformers-video
services:
video-api:
image: ${TRANSFORMERS_IMAGE:-vllm/vllm-openai:v0.10.2}
container_name: ${TRANSFORMERS_CONTAINER_NAME:-llm-transformers-video}
restart: unless-stopped
ipc: host
ports:
- "${TRANSFORMERS_HOST_PORT:-8030}:8030"
environment:
HF_HOME: /root/.cache/huggingface
MODEL_PATH: ${MODEL_PATH:-/models/video/qwen2.5-vl-7b-instruct}
SERVED_MODEL_NAME: ${SERVED_MODEL_NAME:-qwen2.5-vl-7b-instruct}
PORT: "8030"
LOAD_ON_START: ${LOAD_ON_START:-0}
volumes:
- ${HOST_APP_DIR:-Z:/LLM/model-chat-app}:/app
- ${HOST_MODELS_DIR:-Z:/LLM/models}:/models
- ${HOST_HF_CACHE_DIR:-Z:/LLM/models/cache/huggingface}:/root/.cache/huggingface
working_dir: /app
entrypoint: python3
command:
- scripts/transformers_plugin_server.py
- --plugin
- video
- --host
- 0.0.0.0
- --port
- "8030"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities:
- gpu
@@ -0,0 +1,9 @@
HOST_APP_DIR=Z:/LLM/model-chat-app
HOST_MODELS_DIR=Z:/LLM/models
HOST_HF_CACHE_DIR=Z:/LLM/models/cache/huggingface
TRANSFORMERS_IMAGE=vllm/vllm-openai:v0.10.2
TRANSFORMERS_CONTAINER_NAME=llm-transformers-video
TRANSFORMERS_HOST_PORT=8030
MODEL_PATH=/models/video/qwen2.5-vl-7b-instruct
SERVED_MODEL_NAME=qwen2.5-vl-7b-instruct
LOAD_ON_START=0
+20
View File
@@ -0,0 +1,20 @@
# Copy to .env on the deployment host and adjust values there.
# Do not commit real tokens, private paths, or credentials.
VLLM_CONTAINER_NAME=llm-vllm-text
VLLM_IMAGE=vllm/vllm-openai:latest
VLLM_MODEL_ID=Qwen/Qwen3-4B-Instruct-2507
VLLM_SERVED_MODEL_NAME=qwen3-4b-instruct
VLLM_LORA_MODULES=qwen3-4b-1c=/models/adapters/1c/qwen3-4b-1c-lora-v1
VLLM_MAX_LORAS=1
VLLM_HOST_PORT=8000
VLLM_GPU_MEMORY_UTILIZATION=0.90
VLLM_MAX_MODEL_LEN=32768
VLLM_DTYPE=auto
# Local model/cache paths on docker-gpu.cin.su.
HOST_MODELS_DIR=/models
HOST_HF_CACHE_DIR=/models/cache/huggingface
# Set on the host only if the model source requires it.
HF_TOKEN=
+42
View File
@@ -0,0 +1,42 @@
services:
vllm:
image: ${VLLM_IMAGE:-vllm/vllm-openai:latest}
container_name: ${VLLM_CONTAINER_NAME:-llm-vllm-text}
restart: unless-stopped
ipc: host
ports:
- "${VLLM_HOST_PORT:-8000}:8000"
environment:
HF_HOME: /root/.cache/huggingface
HUGGING_FACE_HUB_TOKEN: ${HF_TOKEN:-}
volumes:
- ${HOST_MODELS_DIR:-/models}:/models
- ${HOST_HF_CACHE_DIR:-/models/cache/huggingface}:/root/.cache/huggingface
command:
- --model
- ${VLLM_MODEL_ID:-Qwen/Qwen3-4B-Instruct-2507}
- --served-model-name
- ${VLLM_SERVED_MODEL_NAME:-qwen3-4b-instruct}
- --enable-lora
- --max-loras
- ${VLLM_MAX_LORAS:-1}
- --lora-modules
- ${VLLM_LORA_MODULES:-qwen3-4b-1c=/models/adapters/1c/qwen3-4b-1c-lora-v1}
- --host
- 0.0.0.0
- --port
- "8000"
- --gpu-memory-utilization
- ${VLLM_GPU_MEMORY_UTILIZATION:-0.90}
- --max-model-len
- ${VLLM_MAX_MODEL_LEN:-32768}
- --dtype
- ${VLLM_DTYPE:-auto}
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities:
- gpu
@@ -0,0 +1,24 @@
ONEC_AGENT_IMAGE=onec-agent:latest
ONEC_AGENT_CONTAINER_NAME=onec-agent
ONEC_AGENT_HOST_PORT=8090
ONEC_AGENT_DEFAULT_BASE_URL=http://docker-gpu.cin.su:8000
ONEC_AGENT_DEFAULT_MODEL=qwen3-4b-instruct-2507
ONEC_ADAPTER_URL=http://docker-gpu.cin.su:8011
# Для интеграции с несколькими ИИ провайдерскими конечными точками
# Формат JSON:
# {
# "default": {
# "type": "openai-compatible",
# "base_url": "http://docker-gpu.cin.su:8000",
# "model": "qwen3-4b-instruct-2507"
# },
# "openrouter": {
# "type": "openai-compatible",
# "base_url": "https://openrouter.ai/api/v1",
# "model": "some-openai-compatible-id",
# "api_key_env": "OPENROUTER_API_KEY"
# }
# }
ONEC_AGENT_PROVIDERS=
OPENROUTER_API_KEY=
+26
View File
@@ -0,0 +1,26 @@
name: onec-agent
services:
onec-agent:
build:
context: ../../../../
dockerfile: plugins/1c/agent/Dockerfile
image: ${ONEC_AGENT_IMAGE:-onec-agent:latest}
container_name: ${ONEC_AGENT_CONTAINER_NAME:-onec-agent}
restart: unless-stopped
ports:
- "${ONEC_AGENT_HOST_PORT:-8090}:8090"
volumes:
- onec-agent-data:/app/data
environment:
ONEC_AGENT_HOST: 0.0.0.0
ONEC_AGENT_PORT: 8090
ONEC_AGENT_DB_PATH: /app/data/onec-agent.db
ONEC_AGENT_DEFAULT_BASE_URL: ${ONEC_AGENT_DEFAULT_BASE_URL:-http://docker-gpu.cin.su:8000}
ONEC_AGENT_DEFAULT_MODEL: ${ONEC_AGENT_DEFAULT_MODEL:-qwen3-4b-instruct-2507}
ONEC_ADAPTER_URL: ${ONEC_ADAPTER_URL:-http://docker-gpu.cin.su:8011}
ONEC_ADAPTER_TOKEN: ${ONEC_ADAPTER_TOKEN:-}
ONEC_AGENT_PROVIDERS: ${ONEC_AGENT_PROVIDERS:-}
volumes:
onec-agent-data:
@@ -0,0 +1,11 @@
ADAPTER_1C_MCP_IMAGE=adapter-1c-mcp:latest
ADAPTER_1C_MCP_CONTAINER_NAME=adapter-1c-mcp
ADAPTER_1C_MCP_HOST_PORT=8021
# REST 1C adapter endpoint. The MCP proxy forwards onec_request(method,payload)
# to this service. Change it when the real adapter container is deployed.
ONEC_ADAPTER_URL=http://docker-gpu.cin.su:8011
ONEC_ADAPTER_TIMEOUT_SECONDS=120
# Optional bearer token for the REST adapter. Do not commit real secrets.
ONEC_ADAPTER_TOKEN=
@@ -0,0 +1,17 @@
name: adapter-1c-mcp
services:
adapter-1c-mcp:
build:
context: ../../../../plugins/1c/mcp
dockerfile: Dockerfile
image: ${ADAPTER_1C_MCP_IMAGE:-adapter-1c-mcp:latest}
container_name: ${ADAPTER_1C_MCP_CONTAINER_NAME:-adapter-1c-mcp}
restart: unless-stopped
ports:
- "${ADAPTER_1C_MCP_HOST_PORT:-8021}:8021"
environment:
PORT: "8021"
ONEC_ADAPTER_URL: ${ONEC_ADAPTER_URL:-http://docker-gpu.cin.su:8011}
ONEC_ADAPTER_TOKEN: ${ONEC_ADAPTER_TOKEN:-}
ONEC_ADAPTER_TIMEOUT_SECONDS: ${ONEC_ADAPTER_TIMEOUT_SECONDS:-240}
+12
View File
@@ -0,0 +1,12 @@
# Core Evals
Общие правила оценки качества моделей.
Eval-наборы должны позволять сравнить:
- базовую модель;
- модель с RAG;
- модель с адаптером;
- разные версии адаптеров.
Для каждого плагина могут быть собственные eval-наборы.
+12
View File
@@ -0,0 +1,12 @@
# Core Inference
Общий слой инференса.
Цель: дать единый интерфейс для запуска моделей разных типов.
Планируемые режимы:
- OpenAI-compatible API для текстовых моделей;
- batch inference;
- локальный inference для eval-тестов;
- подключение LoRA/adapters поверх базовых моделей.
+10
View File
@@ -0,0 +1,10 @@
# Core Monitoring
Мониторинг должен покрывать:
- использование GPU и VRAM;
- время ответа;
- ошибки инференса;
- количество запросов;
- версии используемых моделей;
- результаты eval-прогонов.
+14
View File
@@ -0,0 +1,14 @@
"""Shared observability helpers for services and plugins."""
from .redaction import sanitize_for_logging
from .store import JsonlAuditStore, resolve_audit_root
from .trace import next_trace_id, resolve_request_id, resolve_trace_id
__all__ = [
"JsonlAuditStore",
"next_trace_id",
"resolve_audit_root",
"resolve_request_id",
"resolve_trace_id",
"sanitize_for_logging",
]
+48
View File
@@ -0,0 +1,48 @@
from __future__ import annotations
import re
from typing import Any
REDACTED = "[REDACTED]"
SENSITIVE_KEY_PARTS = (
"authorization",
"api_key",
"apikey",
"access_token",
"refresh_token",
"token",
"password",
"secret",
"cookie",
"set-cookie",
)
BEARER_RE = re.compile(r"(?i)\bBearer\s+[A-Za-z0-9._~+/=-]+")
def _looks_sensitive_key(key: str) -> bool:
lowered = key.strip().lower()
return any(part in lowered for part in SENSITIVE_KEY_PARTS)
def _sanitize_string(value: str) -> str:
return BEARER_RE.sub("Bearer " + REDACTED, value)
def sanitize_for_logging(value: Any) -> Any:
if isinstance(value, dict):
cleaned: dict[str, Any] = {}
for key, item in value.items():
key_text = str(key)
if _looks_sensitive_key(key_text):
cleaned[key_text] = REDACTED
else:
cleaned[key_text] = sanitize_for_logging(item)
return cleaned
if isinstance(value, list):
return [sanitize_for_logging(item) for item in value]
if isinstance(value, tuple):
return [sanitize_for_logging(item) for item in value]
if isinstance(value, str):
return _sanitize_string(value)
return value
+47
View File
@@ -0,0 +1,47 @@
from __future__ import annotations
import json
import threading
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
def utc_now_iso() -> str:
return datetime.now(timezone.utc).isoformat()
def resolve_audit_root(root: Path, *, service: str, env_var: str | None = None) -> Path:
import os
configured = os.environ.get(env_var or "", "").strip() if env_var else ""
if configured:
return Path(configured)
return root / "reports" / "observability" / service
class JsonlAuditStore:
def __init__(self, root: Path, *, service: str) -> None:
self.root = root
self.service = service
self.root.mkdir(parents=True, exist_ok=True)
self._lock = threading.Lock()
def _path_for(self, event_type: str) -> Path:
stamp = datetime.now(timezone.utc).strftime("%Y%m%d")
return self.root / event_type / f"{stamp}.jsonl"
def write_event(self, event_type: str, payload: dict[str, Any]) -> dict[str, Any]:
record = {
"event_type": event_type,
"service": self.service,
"logged_at": utc_now_iso(),
**payload,
}
path = self._path_for(event_type)
path.parent.mkdir(parents=True, exist_ok=True)
line = json.dumps(record, ensure_ascii=False, separators=(",", ":")) + "\n"
with self._lock:
with path.open("a", encoding="utf-8") as handle:
handle.write(line)
return record
+26
View File
@@ -0,0 +1,26 @@
from __future__ import annotations
import uuid
from typing import Mapping
def next_trace_id() -> str:
return uuid.uuid4().hex
def _header_value(headers: Mapping[str, str], *names: str) -> str:
for name in names:
value = headers.get(name)
if value:
return str(value).strip()
return ""
def resolve_trace_id(headers: Mapping[str, str]) -> str:
trace_id = _header_value(headers, "x-trace-id", "X-Trace-Id", "x-request-id", "X-Request-Id")
return trace_id or next_trace_id()
def resolve_request_id(headers: Mapping[str, str], *, fallback_trace_id: str) -> str:
request_id = _header_value(headers, "x-request-id", "X-Request-Id")
return request_id or fallback_trace_id
+10
View File
@@ -0,0 +1,10 @@
# Core Registry
Общий слой работы с реестром моделей.
Планируемые функции:
- проверка `model-card.yaml`;
- поиск моделей по задаче, языку и требованиям VRAM;
- учет базовых моделей и адаптеров;
- контроль статусов `draft`, `staging`, `production`, `archived`.
+24
View File
@@ -0,0 +1,24 @@
# Core Storage
Правила хранения моделей, датасетов и артефактов.
Рекомендуемая внешняя структура:
```text
/models
/base
/adapters
/embeddings
/audio
/video
/translation
/datasets
/raw
/prepared
/evals
/artifacts
```
В git храним только метаданные и инструкции.
+7
View File
@@ -0,0 +1,7 @@
# Core Training
Общие пайплайны подготовки данных и дообучения.
Основной подход для доменных моделей: adapter-based fine-tuning, например LoRA/QLoRA.
Полное дообучение базовых моделей не используем как первый вариант из-за стоимости, сложности хранения и риска ухудшения общего качества.