АРЧ ЮИ - остановка прогона через гуй
This commit is contained in:
@@ -25,6 +25,7 @@ export interface RunAssistantLivingChatLlmRuntimeInput {
|
||||
apiKey?: unknown;
|
||||
model?: unknown;
|
||||
baseUrl?: unknown;
|
||||
abortSignal?: AbortSignal;
|
||||
temperature?: number;
|
||||
maxOutputTokens?: number;
|
||||
};
|
||||
@@ -35,6 +36,7 @@ export interface RunAssistantLivingChatLlmRuntimeInput {
|
||||
apiKey: string;
|
||||
model: string;
|
||||
baseUrl: unknown;
|
||||
abortSignal?: AbortSignal;
|
||||
temperature: number;
|
||||
maxOutputTokens: number;
|
||||
},
|
||||
@@ -104,6 +106,7 @@ export async function runAssistantLivingChatLlmRuntime(
|
||||
apiKey: String(input.payload.apiKey ?? input.defaultApiKey ?? ""),
|
||||
model: String(input.payload.model ?? input.defaultModel),
|
||||
baseUrl: input.payload.baseUrl ?? input.defaultBaseUrl,
|
||||
abortSignal: input.payload.abortSignal,
|
||||
temperature,
|
||||
maxOutputTokens
|
||||
},
|
||||
|
||||
@@ -144,6 +144,10 @@ function hasPriorAssistantTurn(items: unknown[]): boolean {
|
||||
return items.some((item) => item && typeof item === "object" && (item as { role?: string }).role === "assistant");
|
||||
}
|
||||
|
||||
function buildDeterministicSmalltalkLeadReply(): string {
|
||||
return "\u041f\u0440\u0438\u0432\u0435\u0442! \u0412\u0441\u0451 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.";
|
||||
}
|
||||
|
||||
function findLastAddressDebug(items: unknown[]): Record<string, unknown> | null {
|
||||
if (!Array.isArray(items)) {
|
||||
return null;
|
||||
@@ -392,9 +396,11 @@ export async function runAssistantLivingChatRuntime(
|
||||
}
|
||||
const proactiveOffer = input.buildAssistantProactiveOrganizationOfferReply(proactiveScopeProbe);
|
||||
if (proactiveOffer) {
|
||||
chatText = [chatText, proactiveOffer].filter((part) => String(part ?? "").trim().length > 0).join(" ");
|
||||
chatText = [buildDeterministicSmalltalkLeadReply(), proactiveOffer]
|
||||
.filter((part) => String(part ?? "").trim().length > 0)
|
||||
.join(" ");
|
||||
livingChatProactiveScopeOfferApplied = true;
|
||||
livingChatSource = "llm_chat_with_proactive_scope_offer";
|
||||
livingChatSource = "deterministic_smalltalk_with_proactive_scope_offer";
|
||||
if (!dataScopeProbe) {
|
||||
dataScopeProbe = proactiveScopeProbe;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ export function createAssistantLivingModePolicy(deps: AssistantLivingModePolicyD
|
||||
}
|
||||
|
||||
function hasDataRetrievalRequestSignal(text) {
|
||||
const lower = compactWhitespace(String(text ?? "").toLowerCase());
|
||||
const lower = compactWhitespace(repairAddressMojibake(String(text ?? "")).toLowerCase());
|
||||
if (!lower) {
|
||||
return false;
|
||||
}
|
||||
@@ -319,20 +319,33 @@ export function createAssistantLivingModePolicy(deps: AssistantLivingModePolicyD
|
||||
}
|
||||
|
||||
function hasLivingChatSignal(text) {
|
||||
const lower = compactWhitespace(String(text ?? "").toLowerCase());
|
||||
if (!lower) {
|
||||
const rawLower = compactWhitespace(String(text ?? "").toLowerCase());
|
||||
const repairedLower = compactWhitespace(repairAddressMojibake(String(text ?? "")).toLowerCase());
|
||||
const variants = [rawLower, repairedLower].filter((value, index, items) => value.length > 0 && items.indexOf(value) === index);
|
||||
if (variants.length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (/^(?:а\s+)?(?:тут|здесь|там|сюда|туда)[\s!?.,:;\-]*$/iu.test(lower)) {
|
||||
const hasDirectionalReply = variants.some((value) => /^(?:\u0430\s+)?(?:\u0442\u0443\u0442|\u0437\u0434\u0435\u0441\u044c|\u0442\u0430\u043c|\u0441\u044e\u0434\u0430|\u0442\u0443\u0434\u0430)[\s!?.,:;\-]*$/iu.test(value));
|
||||
if (hasDirectionalReply) {
|
||||
return true;
|
||||
}
|
||||
if (/^(ага|угу|ок|окей|ясно|понял|поняла|принято|спасибо|благодарю|супер|класс|норм|го|давай|погнали|привет|хай|йо|yo|че\s+там|ч[её]\s+как|че\s+как|hello|hi|thanks?)$/i.test(lower)) {
|
||||
const hasShortGreeting = variants.some((value) => /^(?:\u0430\u0433\u0430|\u0443\u0433\u0443|\u043e\u043a|\u043e\u043a\u0435\u0439|\u044f\u0441\u043d\u043e|\u043f\u043e\u043d\u044f\u043b(?:\u0430)?|\u043f\u0440\u0438\u043d\u044f\u0442\u043e|\u0441\u043f\u0430\u0441\u0438\u0431\u043e|\u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044e|\u0441\u0443\u043f\u0435\u0440|\u043a\u043b\u0430\u0441\u0441|\u043d\u043e\u0440\u043c|\u0433\u043e|\u0434\u0430\u0432\u0430\u0439|\u043f\u043e\u0433\u043d\u0430\u043b\u0438|\u043f\u0440\u0438\u0432\u0435\u0442(?:\u0438\u043a)?|\u0445\u0430\u0439|\u0439\u043e|yo|\u0447[её]\s+\u0442\u0430\u043c|\u0447[её]\s+\u043a\u0430\u043a|hello|hi|thanks?)$/iu.test(value));
|
||||
if (hasShortGreeting) {
|
||||
return true;
|
||||
}
|
||||
if (/(как дела|как ты|что нового|расскажи о себе|чем можешь помочь|давай поговорим|поговорим|обсудим|посоветуй|что думаешь)/i.test(lower)) {
|
||||
const hasGreetingWithFollowup = variants.some((value) => /(?:^|[\s,.!?;:()\-])(?:\u043f\u0440\u0438\u0432\u0435\u0442\p{L}*|\u0445\u0430\u0439|\u0439\u043e|hello|hi|yo)(?=$|[\s,.!?;:()\-]).*(?:^|[\s,.!?;:()\-])(?:\u043a\u0430\u043a|\u0434\u0435\u043b\u0430|\u0442\u0430\u043c|\u0447[её])(?=$|[\s,.!?;:()\-])/iu.test(value));
|
||||
if (hasGreetingWithFollowup) {
|
||||
return true;
|
||||
}
|
||||
return hasSmallTalkSignal(lower);
|
||||
const hasColloquialFollowup = variants.some((value) => /(?:^|[\s,.!?;:()\-])(?:\u0447[её]\s+\u043a\u0430\u043a|\u0447[её]\s+\u0442\u0430\u043c|\u043a\u0430\u043a\s+\u0442\u0430\u043c(?:\s+\u0434\u0435\u043b\u0430)?)(?=$|[\s,.!?;:()\-])/iu.test(value));
|
||||
if (hasColloquialFollowup) {
|
||||
return true;
|
||||
}
|
||||
const hasOpenSmalltalkPrompt = variants.some((value) => /(?:\u043a\u0430\u043a\s+\u0434\u0435\u043b\u0430|\u043a\u0430\u043a\s+\u0442\u044b|\u0447\u0442\u043e\s+\u043d\u043e\u0432\u043e\u0433\u043e|\u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0438\s+\u043e\s+\u0441\u0435\u0431\u0435|\u0447\u0435\u043c\s+\u043c\u043e\u0436\u0435\u0448\u044c\s+\u043f\u043e\u043c\u043e\u0447\u044c|\u0434\u0430\u0432\u0430\u0439\s+\u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c|\u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c|\u043e\u0431\u0441\u0443\u0434\u0438\u043c|\u043f\u043e\u0441\u043e\u0432\u0435\u0442\u0443\u0439|\u0447\u0442\u043e\s+\u0434\u0443\u043c\u0430\u0435\u0448\u044c)/iu.test(value));
|
||||
if (hasOpenSmalltalkPrompt) {
|
||||
return true;
|
||||
}
|
||||
return variants.some((value) => hasSmallTalkSignal(value));
|
||||
}
|
||||
|
||||
function resolveLivingAssistantModeDecision(input) {
|
||||
|
||||
@@ -3290,6 +3290,7 @@ async function runAddressLlmPreDecompose(normalizerService, payload, userMessage
|
||||
apiKey: payload?.apiKey,
|
||||
model: payload?.model,
|
||||
baseUrl: payload?.baseUrl,
|
||||
abortSignal: payload?.abortSignal,
|
||||
temperature: 0,
|
||||
maxOutputTokens: payload?.maxOutputTokens,
|
||||
promptVersion: "normalizer_v2_0_2",
|
||||
|
||||
@@ -54,6 +54,12 @@ import { AssistantSessionStore } from "./assistantSessionStore";
|
||||
import { NormalizerService } from "./normalizerService";
|
||||
import { ensureDir, writeJsonFile } from "../utils/files";
|
||||
|
||||
function throwIfAborted(signal?: AbortSignal): void {
|
||||
if (signal?.aborted) {
|
||||
throw new Error("EVAL_RUN_ABORTED");
|
||||
}
|
||||
}
|
||||
|
||||
interface EvalCaseFile {
|
||||
case_id: string;
|
||||
raw_question: string;
|
||||
@@ -1925,6 +1931,7 @@ export class EvalService {
|
||||
compareWithReportFile?: string;
|
||||
analysisDate?: string;
|
||||
runId?: string;
|
||||
abortSignal?: AbortSignal;
|
||||
}): Promise<Record<string, unknown>> {
|
||||
if (!FEATURE_ASSISTANT_ACCOUNTANT_EVAL_V1) {
|
||||
throw new ApiError(
|
||||
@@ -1943,6 +1950,7 @@ export class EvalService {
|
||||
let requestsTotal = 0;
|
||||
|
||||
for (const suiteCase of suiteCases) {
|
||||
throwIfAborted(payload.abortSignal);
|
||||
const sessionId = `${runId}-${suiteCase.case_id}`;
|
||||
const turnResponses: AssistantMessageResponsePayload[] = [];
|
||||
const notes: string[] = [];
|
||||
@@ -1950,11 +1958,13 @@ export class EvalService {
|
||||
|
||||
try {
|
||||
for (const turn of suiteCase.turns) {
|
||||
throwIfAborted(payload.abortSignal);
|
||||
const response = (await assistantService.handleMessage({
|
||||
session_id: sessionId,
|
||||
user_message: turn.user_message,
|
||||
message: turn.user_message,
|
||||
mode: "assistant",
|
||||
abortSignal: payload.abortSignal,
|
||||
llmProvider: payload.normalizeConfig.llmProvider,
|
||||
apiKey: payload.normalizeConfig.apiKey,
|
||||
model: payload.normalizeConfig.model,
|
||||
@@ -1979,9 +1989,13 @@ export class EvalService {
|
||||
})) as AssistantMessageResponsePayload;
|
||||
turnResponses.push(response);
|
||||
requestsTotal += 1;
|
||||
throwIfAborted(payload.abortSignal);
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
if (errorMessage === "EVAL_RUN_ABORTED") {
|
||||
throw error;
|
||||
}
|
||||
diagnostics.push({
|
||||
suite_case: suiteCase,
|
||||
session_id: sessionId,
|
||||
@@ -2634,6 +2648,7 @@ export class EvalService {
|
||||
compareWithReportFile?: string;
|
||||
analysisDate?: string;
|
||||
runId?: string;
|
||||
abortSignal?: AbortSignal;
|
||||
}): Promise<Record<string, unknown>> {
|
||||
const mode = payload.mode ?? "standard";
|
||||
const evalTarget = payload.evalTarget ?? "normalizer";
|
||||
@@ -2648,7 +2663,8 @@ export class EvalService {
|
||||
caseSetFile: payload.caseSetFile,
|
||||
compareWithReportFile: payload.compareWithReportFile,
|
||||
analysisDate: analysisDate ?? undefined,
|
||||
runId: payload.runId
|
||||
runId: payload.runId,
|
||||
abortSignal: payload.abortSignal
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1608,6 +1608,7 @@ export class NormalizerService {
|
||||
apiKey: String(apiKey ?? ""),
|
||||
model,
|
||||
baseUrl,
|
||||
abortSignal: payload.abortSignal,
|
||||
temperature,
|
||||
maxOutputTokens
|
||||
},
|
||||
@@ -1656,6 +1657,7 @@ export class NormalizerService {
|
||||
apiKey: String(payload.apiKey ?? process.env.OPENAI_API_KEY ?? ""),
|
||||
model,
|
||||
baseUrl,
|
||||
abortSignal: payload.abortSignal,
|
||||
temperature,
|
||||
maxOutputTokens: retryMaxOutputTokens
|
||||
},
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface OpenAIRequestConfig {
|
||||
apiKey: string;
|
||||
model: string;
|
||||
baseUrl?: string;
|
||||
abortSignal?: AbortSignal;
|
||||
temperature?: number;
|
||||
maxOutputTokens?: number;
|
||||
}
|
||||
@@ -491,7 +492,8 @@ export class OpenAIResponsesClient {
|
||||
response = await fetch(url, {
|
||||
method,
|
||||
headers,
|
||||
body: method === "POST" ? JSON.stringify(payload ?? {}) : undefined
|
||||
body: method === "POST" ? JSON.stringify(payload ?? {}) : undefined,
|
||||
signal: config.abortSignal
|
||||
});
|
||||
} catch (error) {
|
||||
lastNetworkError = error;
|
||||
|
||||
Reference in New Issue
Block a user