// // (MlPredictResultDto/MlServiceStatusDto/MlEvalDto/MlResetResultDto). // Модель per-tenant: пул в ml-service, файл SQLite data/ml/.sqlite // // tenant-id — id тенанта (строка; модель тенанта — в пуле сервиса); // service-token — общий токен сервисов (env DEAL_SERVICE_TOKEN); неверный/ // пустой → UNAUTHENTICATED. // // INVALID_ARGUMENT — невалидный запрос (пустой text и т.п.); // UNAVAILABLE — хранилище модели недоступно (ядро отвечает «не уверен», // // Семантика неготовой модели: Predict НЕ ошибка — модель без опыта отвечает // фиксированным «не уверен»: take=false, label пуст, scores пуст, hits=0, // // Deadlines (клиент ядра): Predict — 5 с; Status/Reset — 10 с; TrainBatch — 30 с // (батч ≤100 примеров, одна транзакция). syntax = "proto3"; package deal.ml.v1; option csharp_namespace = "Deal.Grpc.Ml"; service MlService { // take/label/scores/hits/margin/terms/type осмысленны только при take=true; // scores — до 5 лучших «класс → вес» (round 3), margin — адаптивный порог // (0.9/0.7/0.5/0.35 после 0/60/150/400 примеров), terms — узнанные термины // класса-победителя, type — решение о типе заявки (t:hire/t:order). rpc Predict(PredictRequest) returns (PredictReply); // classes — «label → вес» (round 2, по убыванию); eval — самооценка по окну // последних подтверждённых решений (EVAL_WINDOW). Модель создаётся лениво rpc Status(StatusRequest) returns (StatusReply); // терминов и журнала самооценки + пересоздание файла. Ok=true; мягкая // ошибка — Ok=false + error (ядро чистит свою ml_outbox только при успехе). rpc Reset(ResetRequest) returns (ResetReply); // пакетные вставки терминов; самооценка по действиям пользователя (delta=1, // не t:*) до применения. Ответ — число применённых примеров. rpc TrainBatch(TrainBatchRequest) returns (TrainBatchReply); } message PredictRequest { // Текст сообщения (ядро передаёт уже обрезанный/нормализованный, как string text = 1; } message PredictReply { // True — модель уверена (take) и решение можно использовать без ИИ. bool take = 1; // Класс решения: id колонки канбана (b_…) или "spam"; пуст, если не уверена. optional string label = 2; // Веса классов: «label → вес» (до 5 лучших; пуст у неготовой модели). map scores = 3; // Сколько терминов класса-победителя модель узнала в тексте. int32 hits = 4; // Модель обучена (набрала MIN_TOTAL/MIN_WINNER/MIN_WINNER_SPAM) и может // принимать решения. bool ready = 5; // Порог уверенности решения (адаптивный margin, 2 знака); пуст — нет решения. optional double margin = 6; // Узнанные термины класса-победителя (подсказка структуры карточки, ≤8). repeated string terms = 7; // Решение о типе заявки (hire/order); пуст — модель тип не определила. TypeDecision type = 8; } message TypeDecision { // True — модель уверена в типе. bool take = 1; // Тип: "hire" | "order". string label = 2; // Внутренний класс ML: "t:hire" | "t:order" (не показывается UI). string value = 3; // Запас уверенности (margin, 2 знака). double margin = 4; } message StatusRequest {} message StatusReply { // Модель готова принимать решения. bool ready = 1; // Классы модели: «label → вес» (round 2; пуст, пока нет обучения). map classes = 2; // Всего примеров, на которых модель обучалась (сумма по классам). int32 learned = 3; // Самооценка модели по последним подтверждённым решениям. ModelEval eval = 4; } message ModelEval { // Решений в окне самооценки (последние EVAL_WINDOW). int32 count = 1; // Из них совпавших с действием пользователя. int32 correct = 2; // Доля верных (correct/count, 0..1; 0 при пустом окне). double accuracy = 3; } message ResetRequest {} message ResetReply { // True — модель сброшена (и ядро очищает свою очередь обучения). bool ok = 1; // Текст ошибки при сбое сброса (пуст при успехе) — мягкая ошибка. optional string error = 2; } message TrainBatchRequest { repeated TrainExample items = 1; } // Один обучающий пример (строка ml_outbox ядра: text/label/delta). message TrainExample { // Текст примера (source_msg карточки или title). string text = 1; // Метка: id доски (b_…), "spam" либо тип "t:hire"/"t:order". string label = 2; // Вес сигнала: 1.0 — действие пользователя; −1.0 — снять метку; double delta = 3; } message TrainBatchReply { // Число применённых примеров (= len(items) при успехе). int32 learned = 1; }