feat(ai): Phase 1 step 3-6 — LLM adapter + per-field AI suggest endpoint + UI

Approach C upgrade на templates foundation (!233). Admin может попросить AI
предложить новое поле — system prompt force'ит structural JSON Schema
fragment, admin review через accept/edit/reject. Bitemporal draft workflow
unchanged downstream.

## Backend
- `LlmAdapter` — OpenAI-compatible /v1/chat/completions client (Ollama,
  vLLM, OpenAI). Bean conditional на ordinis.ai.enabled=true.
- `AiSchemaService` — system prompt + 3 few-shot examples, JSON output
  parsing (с markdown fence stripping), validation (fieldName snake_case).
  In-memory circuit breaker: 10 fails в 60s → open 5 min.
- `AiSchemaController`:
  - GET /api/v1/ai/info → 200 (enabled) / 404 (disabled). Frontend probe.
  - POST /api/v1/ai/suggest-field → suggestion. Per-IP rate limit 30/min.
- All bean-conditional: ordinis.ai.enabled=false → controllers нет →
  endpoints 404 → frontend hides AI buttons automatically.

## Frontend
- `useAiFeatureAvailable` query — probes /ai/info, cache 5 min
- `useAiSuggestField` mutation — 30s timeout (LLM может быть slow)
- `AiFieldSuggestPanel` component — inline expandable: prompt → preview →
  accept/retry/reject. Error handling per HTTP status (503/429/422/502/404).
- DictionaryEditorDialog: AI toggle visible на schema tab когда
  aiAvailable=true. Accept wraps suggestion в mini-schema → parseSchemaJson
  (reuse existing kind-inference) → push в properties (overwrite если
  duplicate fieldName).
- i18n RU + EN

## Config
- application.yml: ordinis.ai.{enabled,endpoint,model,bearer-token,
  timeout-seconds}
- Helm writer.yaml: ORDINIS_AI_* env vars, optional secretRef для bearer
- values.yaml: ai.{enabled,endpoint,model,timeoutSeconds,bearerTokenSecretRef}
  defaults disabled

Pair с infra MR — values-staging enables AI с vortex.nstart.cloud Ollama
serving qwen2.5:7b.
This commit is contained in:
Zimin A.N.
2026-05-16 13:55:16 +03:00
parent db5d5c19e2
commit e4cd7b9709
10 changed files with 861 additions and 1 deletions
@@ -230,6 +230,18 @@ ordinis:
require-authentication: ${ORDINIS_AUTH_REQUIRED:false}
allow-query-scope: ${ORDINIS_AUTH_ALLOW_QUERY_SCOPE:true}
# AI Schema Assist (Phase 1 step 3-6). Off by default — controllers/services
# bean-conditionally registered, frontend hides AI button when 404.
# Enable per-env через helm values (см. charts/ordinis/values-staging.yaml).
# endpoint: OpenAI-compatible /v1/chat/completions root (без /v1 suffix —
# adapter добавит сам). bearer-token optional (Ollama не требует, OpenAI да).
ai:
enabled: ${ORDINIS_AI_ENABLED:false}
endpoint: ${ORDINIS_AI_ENDPOINT:}
model: ${ORDINIS_AI_MODEL:qwen2.5:7b}
bearer-token: ${ORDINIS_AI_BEARER_TOKEN:}
timeout-seconds: ${ORDINIS_AI_TIMEOUT_SECONDS:15}
# Keycloak Admin REST integration for UserDisplayService Phase 2 — on-demand
# sub→user lookup when JWT capture cache + DB cache both miss. See
# KeycloakAdminUserResolver.java + 0023-user-display-cache.xml migration.