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:
@@ -852,6 +852,34 @@ export const schemaTemplateDetailQuery = (id: string) =>
|
||||
},
|
||||
staleTime: 5 * 60_000,
|
||||
})
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// AI feature detection — probe endpoint
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Probe AI Schema Assist availability. Backend регистрирует /ai/suggest-field
|
||||
* conditionally на ordinis.ai.enabled — если выключено, OPTIONS возвращает 404.
|
||||
*
|
||||
* <p>Used UI чтобы decide показывать ли «AI suggest» button. Cache 5 min —
|
||||
* feature flag меняется только при helm upgrade.
|
||||
*/
|
||||
export const aiFeatureAvailableQuery = queryOptions({
|
||||
queryKey: ['ai-feature-available'] as const,
|
||||
queryFn: async (): Promise<boolean> => {
|
||||
try {
|
||||
const { data } = await apiClient.get<{ enabled: boolean }>('/ai/info')
|
||||
return Boolean(data?.enabled)
|
||||
} catch {
|
||||
// 404 (AI disabled) или network error → hide button (graceful default).
|
||||
return false
|
||||
}
|
||||
},
|
||||
staleTime: 5 * 60_000,
|
||||
retry: false,
|
||||
})
|
||||
|
||||
export const useAiFeatureAvailable = () => useQuery(aiFeatureAvailableQuery)
|
||||
export const useRecordRaw = (
|
||||
dictionaryName: string,
|
||||
businessKey: string | undefined,
|
||||
|
||||
Reference in New Issue
Block a user