АРЧ АП11 - Включить response guard для capability binding ассистента

This commit is contained in:
2026-04-15 23:47:26 +03:00
parent 1c928a5d68
commit 918feaf06e
7 changed files with 384 additions and 9 deletions
@@ -2,6 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAssistantAddressLaneResponseRuntime = runAssistantAddressLaneResponseRuntime;
const assistantAddressTurnFinalizeRuntimeAdapter_1 = require("./assistantAddressTurnFinalizeRuntimeAdapter");
const assistantCapabilityBindingResponseGuard_1 = require("./assistantCapabilityBindingResponseGuard");
const assistantCapabilityRuntimeBindingAdapter_1 = require("./assistantCapabilityRuntimeBindingAdapter");
const assistantRuntimeContractResolver_1 = require("./assistantRuntimeContractResolver");
const assistantStateTransitionRuntimeAdapter_1 = require("./assistantStateTransitionRuntimeAdapter");
@@ -207,14 +208,23 @@ function runAssistantAddressLaneResponseRuntime(input) {
addressRuntimeMeta: input.llmPreDecomposeMeta,
replyType: normalizeAddressReplyType(input.addressLane.reply_type)
});
const guardedResponse = (0, assistantCapabilityBindingResponseGuard_1.applyAssistantCapabilityBindingResponseGuard)({
assistantReply: safeAddressReply,
replyType: normalizeAddressReplyType(input.addressLane.reply_type),
capabilityBinding: debugWithCapabilityBinding.assistant_capability_binding_v1
});
const debugWithResponseGuard = {
...debugWithCapabilityBinding,
capability_binding_response_guard: guardedResponse.audit
};
const finalization = finalizeAddressTurnSafe({
sessionId: input.sessionId,
userMessage: input.userMessage,
effectiveAddressUserMessage: input.effectiveAddressUserMessage,
assistantReply: safeAddressReply,
replyType: normalizeAddressReplyType(input.addressLane.reply_type),
assistantReply: guardedResponse.assistantReply,
replyType: guardedResponse.replyType,
addressLaneDebug: normalizeAddressLaneDebug(input.addressLane.debug),
debug: debugWithCapabilityBinding,
debug: debugWithResponseGuard,
carryoverMeta: normalizeCarryoverMeta(input.carryoverMeta),
llmPreDecomposeMeta: normalizeLlmPreDecomposeMeta(input.llmPreDecomposeMeta),
appendItem: input.appendItem,
@@ -226,6 +236,6 @@ function runAssistantAddressLaneResponseRuntime(input) {
});
return {
response: finalization.response,
debug: debugWithCapabilityBinding
debug: debugWithResponseGuard
};
}
@@ -0,0 +1,77 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyAssistantCapabilityBindingResponseGuard = applyAssistantCapabilityBindingResponseGuard;
function formatMissingAnchors(anchors) {
if (anchors.length === 0) {
return "нужный объект, период или организацию";
}
return anchors.join(", ");
}
function buildClarificationReply(binding) {
return [
"Нужно уточнение, чтобы не подставить неподтвержденный объект в расчет.",
`Не хватает: ${formatMissingAnchors(binding.missing_anchors)}.`,
"Уточните это, и я продолжу тот же сценарий."
].join("\n");
}
function buildBlockedReply(binding) {
const reasons = binding.violations.length > 0 ? binding.violations.join(", ") : "runtime_binding_blocked";
return [
"Не могу надежно подтвердить ответ в текущем контексте.",
`Проверка сценария остановила ответ: ${reasons}.`,
"Лучше уточнить объект или перезапустить вопрос от корневого запроса, чем выдавать это как подтвержденный факт."
].join("\n");
}
function applyAssistantCapabilityBindingResponseGuard(input) {
const binding = input.capabilityBinding;
const baseAudit = {
schema_version: "assistant_capability_binding_response_guard_v1",
guard_owner: "assistantCapabilityBindingResponseGuard",
applied: false,
action: binding?.binding_action ?? "none",
original_reply_type: input.replyType,
guarded_reply_type: input.replyType,
reason_codes: binding?.reason_codes ?? []
};
if (!binding || binding.binding_action === "allow" || binding.binding_action === "observe_only") {
return {
assistantReply: input.assistantReply,
replyType: input.replyType,
audit: baseAudit
};
}
if (binding.binding_action === "clarify") {
return {
assistantReply: buildClarificationReply(binding),
replyType: "partial_coverage",
audit: {
...baseAudit,
applied: true,
guarded_reply_type: "partial_coverage",
reason_codes: [...baseAudit.reason_codes, "capability_binding_guard_clarification_reply"]
}
};
}
if (binding.binding_action === "block") {
return {
assistantReply: buildBlockedReply(binding),
replyType: "partial_coverage",
audit: {
...baseAudit,
applied: true,
guarded_reply_type: "partial_coverage",
reason_codes: [...baseAudit.reason_codes, "capability_binding_guard_blocked_reply"]
}
};
}
return {
assistantReply: input.assistantReply,
replyType: input.replyType === "factual" ? "partial_coverage" : input.replyType,
audit: {
...baseAudit,
applied: input.replyType === "factual",
guarded_reply_type: input.replyType === "factual" ? "partial_coverage" : input.replyType,
reason_codes: [...baseAudit.reason_codes, "capability_binding_guard_limited_reply_type"]
}
};
}