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
+116
View File
@@ -0,0 +1,116 @@
from __future__ import annotations
import argparse
import sys
import urllib.error
from common import ROOT, call_chat_completion, read_json
REGISTRY_INDEX = ROOT / "registry" / "index.json"
DEFAULT_BASE_URL = "http://docker-gpu.cin.su:8000"
PLUGIN_TASKS = {
"text": {"text", "chat", "summarization", "code", "tool-use"},
"translation": {"translation"},
"audio": {"speech-to-text", "speech-translation"},
"video": {"video", "image-understanding", "document-understanding", "visual-question-answering"},
"1c": {"1c", "1c-rag", "bsl-code", "metadata-safety", "1c-query"},
}
DEFAULT_PROMPTS = {
"text": "Кратко объясни, зачем нужен реестр локальных моделей.",
"translation": "Переведи на английский: Проверяем локальную модель перевода.",
"audio": "Составь чек-лист проверки качества распознавания речи.",
"video": "Какие тесты нужны для проверки модели анализа видео?",
"1c": "Какие метаданные 1С нужно запросить перед изменением документа?",
}
STATUS_RANK = {
"production": 0,
"staging": 1,
"candidate": 2,
"draft": 3,
"archived": 9,
}
def model_matches_plugin(model: dict, plugin: str) -> bool:
tasks = set(model.get("task") or [])
return bool(tasks & PLUGIN_TASKS.get(plugin, set()))
def model_score(model: dict, plugin: str) -> tuple[int, int, str]:
tasks = set(model.get("task") or [])
status = str(model.get("status") or "")
score = 0
if plugin == "text":
if tasks & {"text", "chat"}:
score -= 5
if tasks & {"1c", "1c-rag", "bsl-code"}:
score += 6
elif plugin == "1c":
if tasks & PLUGIN_TASKS["1c"]:
score -= 6
else:
if tasks & PLUGIN_TASKS.get(plugin, set()):
score -= 5
return (score, STATUS_RANK.get(status, 8), str(model.get("id") or ""))
def select_model(plugin: str, model_id: str | None) -> dict:
registry = read_json(REGISTRY_INDEX)
models = registry.get("models") or []
candidates = [model for model in models if model_matches_plugin(model, plugin)]
if model_id:
candidates = [model for model in candidates if model.get("id") == model_id]
candidates.sort(key=lambda model: model_score(model, plugin))
if not candidates:
raise ValueError(f"No model found for plugin={plugin!r} model={model_id!r}")
return candidates[0]
def main() -> int:
parser = argparse.ArgumentParser(description="Chat with a registry model through an OpenAI-compatible endpoint.")
parser.add_argument("--plugin", choices=sorted(PLUGIN_TASKS), default="text")
parser.add_argument("--model-id", help="Registry model id. Defaults to the first model for the plugin.")
parser.add_argument("--base-url", default=DEFAULT_BASE_URL)
parser.add_argument("--prompt")
parser.add_argument("--temperature", type=float, default=0.2)
parser.add_argument("--max-tokens", type=int, default=1000)
parser.add_argument("--system", default="Отвечай по-русски, кратко и по делу.")
args = parser.parse_args()
try:
model = select_model(args.plugin, args.model_id)
except ValueError as exc:
print(exc, file=sys.stderr)
return 1
served_model = model.get("served_model_name") or model.get("id")
prompt = args.prompt or DEFAULT_PROMPTS[args.plugin]
messages = [
{"role": "system", "content": args.system},
{"role": "user", "content": prompt},
]
print(f"Plugin: {args.plugin}")
print(f"Model: {model.get('id')} -> {served_model}")
print(f"Endpoint: {args.base_url}")
print("")
try:
answer = call_chat_completion(
base_url=args.base_url,
model=served_model,
messages=messages,
temperature=args.temperature,
max_tokens=args.max_tokens,
)
except (urllib.error.URLError, ValueError) as exc:
print(f"Chat request failed: {exc}", file=sys.stderr)
return 1
print(answer)
return 0
if __name__ == "__main__":
raise SystemExit(main())