Stage 3: улучшена логика жизненного цикла и очищены ответы ассистента
This commit is contained in:
+47
-23
@@ -917,10 +917,10 @@ class AssistantDataLayer {
|
||||
result = this.executeRisk(fragmentText, data);
|
||||
}
|
||||
else if (route === "batch_refresh_then_store") {
|
||||
result = this.executeBatch(data);
|
||||
result = this.executeBatch(fragmentText, data);
|
||||
}
|
||||
else if (route === "store_canonical") {
|
||||
result = this.executeCanonical(data);
|
||||
result = this.executeCanonical(fragmentText, data);
|
||||
}
|
||||
else if (route === "live_mcp_drilldown") {
|
||||
result = this.executeDrilldown(fragmentText, data);
|
||||
@@ -1207,7 +1207,9 @@ class AssistantDataLayer {
|
||||
errors: []
|
||||
};
|
||||
}
|
||||
executeRisk(_fragmentText, data) {
|
||||
executeRisk(fragmentText, data) {
|
||||
const semanticProfile = buildSemanticRetrievalProfile(fragmentText);
|
||||
const profileRiskFactors = semanticProfile.anomaly_patterns;
|
||||
const records = [...data.problemCases, ...data.ndsRegisters];
|
||||
const scored = records
|
||||
.map((record) => {
|
||||
@@ -1258,12 +1260,15 @@ class AssistantDataLayer {
|
||||
items: [],
|
||||
summary: {
|
||||
checked_records: records.length,
|
||||
risky_records: 0
|
||||
risky_records: 0,
|
||||
query_subject: semanticProfile.query_subject,
|
||||
semantic_profile: semanticProfile,
|
||||
ranking_basis: semanticProfile.ranking_basis
|
||||
},
|
||||
evidence: [],
|
||||
why_included: [],
|
||||
selection_reason: ["Риск-оценка выполнялась по техническим признакам, но записи выше порога не найдены."],
|
||||
risk_factors: [],
|
||||
risk_factors: profileRiskFactors,
|
||||
business_interpretation: ["По текущему срезу явные риск-признаки не обнаружены."],
|
||||
confidence: "medium",
|
||||
limitations: ["Оценка основана на snapshot-данных и эвристическом risk score."],
|
||||
@@ -1271,6 +1276,13 @@ class AssistantDataLayer {
|
||||
};
|
||||
}
|
||||
const averageScore = items.reduce((acc, item) => acc + item.risk_score, 0) / items.length;
|
||||
const normalizedRiskFactors = uniqueStrings([
|
||||
...profileRiskFactors,
|
||||
"unknown_link_count",
|
||||
"zero_guid_values",
|
||||
"navigation_links",
|
||||
"missing_counterparty_link"
|
||||
]);
|
||||
return {
|
||||
status: "ok",
|
||||
result_type: "list",
|
||||
@@ -1278,7 +1290,10 @@ class AssistantDataLayer {
|
||||
summary: {
|
||||
checked_records: records.length,
|
||||
risky_records: items.length,
|
||||
average_risk_score: Number(averageScore.toFixed(2))
|
||||
average_risk_score: Number(averageScore.toFixed(2)),
|
||||
query_subject: semanticProfile.query_subject,
|
||||
semantic_profile: semanticProfile,
|
||||
ranking_basis: semanticProfile.ranking_basis
|
||||
},
|
||||
evidence: items.slice(0, 10).map((item) => ({
|
||||
source_entity: item.source_entity,
|
||||
@@ -1287,21 +1302,18 @@ class AssistantDataLayer {
|
||||
})),
|
||||
why_included: ["В ответ включены записи с risk_score >= 2."],
|
||||
selection_reason: [
|
||||
"score растет при unknown links, zero GUID, навигационных ссылках и отсутствии явного контрагента."
|
||||
],
|
||||
risk_factors: [
|
||||
"unknown_link_count",
|
||||
"zero_guid_values",
|
||||
"navigation_links",
|
||||
"missing_counterparty_link"
|
||||
"score растет при unknown links, zero GUID, навигационных ссылках и отсутствии явного контрагента.",
|
||||
`Semantic profile subject: ${semanticProfile.query_subject}.`
|
||||
],
|
||||
risk_factors: normalizedRiskFactors,
|
||||
business_interpretation: ["Рти записи требуют первичной бухгалтерской проверки как потенциальные аномалии."],
|
||||
confidence: "high",
|
||||
limitations: ["Риск-факторы определяются эвристикой, а не полным набором бизнес-правил 1С."],
|
||||
errors: []
|
||||
};
|
||||
}
|
||||
executeBatch(data) {
|
||||
executeBatch(fragmentText, data) {
|
||||
const semanticProfile = buildSemanticRetrievalProfile(fragmentText);
|
||||
const source = [...data.problemCases, ...data.keyFields, ...data.docs];
|
||||
const byEntity = new Map();
|
||||
for (const record of source) {
|
||||
@@ -1321,7 +1333,10 @@ class AssistantDataLayer {
|
||||
items,
|
||||
summary: {
|
||||
checked_records: source.length,
|
||||
ranked_entities: items.length
|
||||
ranked_entities: items.length,
|
||||
query_subject: semanticProfile.query_subject,
|
||||
semantic_profile: semanticProfile,
|
||||
ranking_basis: semanticProfile.ranking_basis
|
||||
},
|
||||
evidence: items.slice(0, 5).map((item) => ({
|
||||
entity: item.entity,
|
||||
@@ -1329,17 +1344,20 @@ class AssistantDataLayer {
|
||||
})),
|
||||
why_included: items.length > 0 ? ["Показаны сущности с максимальным количеством записей."] : [],
|
||||
selection_reason: ["Ранжирование выполнено по records_count по убыванию."],
|
||||
risk_factors: ["Высокий объем записей по сущности повышает приоритет проверки."],
|
||||
risk_factors: uniqueStrings(["entity_volume_spike", ...semanticProfile.anomaly_patterns]),
|
||||
business_interpretation: [
|
||||
"Сущности в топе ранга чаще дают наибольший вклад в проблемный объем и требуют приоритетного аудита."
|
||||
"Top entities by volume highlight where lifecycle-focused review should start first."
|
||||
],
|
||||
confidence: "medium",
|
||||
limitations: ["Ранжирование по объему не всегда эквивалентно бизнес-риску."],
|
||||
errors: []
|
||||
};
|
||||
}
|
||||
executeCanonical(data) {
|
||||
const items = data.docs
|
||||
executeCanonical(fragmentText, data) {
|
||||
const semanticProfile = buildSemanticRetrievalProfile(fragmentText);
|
||||
const useVatSource = semanticProfile.domain_scope.includes("vat") || semanticProfile.domain_scope.includes("taxes");
|
||||
const sourceRecords = useVatSource ? [...data.ndsRegisters, ...data.keyFields] : data.docs;
|
||||
const items = sourceRecords
|
||||
.map((record) => {
|
||||
const period = extractDate(record);
|
||||
return {
|
||||
@@ -1360,8 +1378,11 @@ class AssistantDataLayer {
|
||||
result_type: "list",
|
||||
items,
|
||||
summary: {
|
||||
checked_records: data.docs.length,
|
||||
returned_records: items.length
|
||||
checked_records: sourceRecords.length,
|
||||
returned_records: items.length,
|
||||
query_subject: semanticProfile.query_subject,
|
||||
semantic_profile: semanticProfile,
|
||||
ranking_basis: semanticProfile.ranking_basis
|
||||
},
|
||||
evidence: items.slice(0, 6).map((item) => ({
|
||||
source_entity: item.source_entity,
|
||||
@@ -1369,8 +1390,11 @@ class AssistantDataLayer {
|
||||
period: item.period
|
||||
})),
|
||||
why_included: items.length > 0 ? ["Показаны последние по дате записи канонического документного слоя."] : [],
|
||||
selection_reason: ["Отбор по максимальной дате документа в пределах snapshot."],
|
||||
risk_factors: [],
|
||||
selection_reason: [
|
||||
"Отбор по максимальной дате документа в пределах snapshot.",
|
||||
`Semantic profile subject: ${semanticProfile.query_subject}.`
|
||||
],
|
||||
risk_factors: semanticProfile.anomaly_patterns,
|
||||
business_interpretation: ["Слой отражает базовый factual-срез документов для оперативной сверки."],
|
||||
confidence: "high",
|
||||
limitations: ["Рто read-only snapshot, Р° РЅРµ онлайн-состояние 1РЎ."],
|
||||
|
||||
Reference in New Issue
Block a user