ARCH: ранжировать metadata surface objects только для честного tie-break

This commit is contained in:
2026-04-23 10:34:56 +03:00
parent 3a89cca6bb
commit c2392f6420
3 changed files with 299 additions and 17 deletions
@@ -159,6 +159,7 @@ export interface AssistantMcpDiscoveryDerivedMetadataSurface {
recommended_next_primitive: "query_documents" | "query_movements" | "drilldown_related_objects" | null;
ambiguity_detected: boolean;
ambiguity_entity_sets: string[];
surface_object_ranking_applied?: boolean;
available_fields: string[];
known_limitations: string[];
inference_basis: "confirmed_1c_metadata_surface_rows";
@@ -688,6 +689,11 @@ function metadataTypesForPlanner(planner: AssistantMcpDiscoveryPlannerContract):
return ["Документ", "РегистрНакопления", "РегистрСведений", "Справочник"];
}
function metadataScopeRankingAllowedForPlanner(planner: AssistantMcpDiscoveryPlannerContract): boolean {
const action = String(planner.discovery_plan.turn_meaning_ref?.asked_action_family ?? "").toLowerCase().trim();
return action === "inspect_surface";
}
interface ValueFlowPilotProfile {
scope: Extract<
AssistantMcpDiscoveryPilotScope,
@@ -1310,20 +1316,86 @@ function metadataSurfaceFamilyScores(
return scores;
}
function normalizeMetadataObjectRankingToken(value: string): string {
return String(value ?? "")
.toLowerCase()
.replace(/[^\p{L}\p{N}]+/gu, "");
}
function metadataScopeRankingTokens(metadataScope: string | null): string[] {
const scope = String(metadataScope ?? "").trim();
if (!scope) {
return [];
}
const condensed = normalizeMetadataObjectRankingToken(scope);
const result: string[] = [];
if (condensed.length >= 2) {
pushUnique(result, condensed);
}
for (const token of scope.toLowerCase().split(/[^\p{L}\p{N}]+/gu)) {
const normalized = normalizeMetadataObjectRankingToken(token);
if (normalized.length >= 2) {
pushUnique(result, normalized);
}
}
return result;
}
function metadataObjectRelevanceScore(metadataScope: string | null, objectName: string): number {
const objectToken = normalizeMetadataObjectRankingToken(objectName);
if (!objectToken) {
return 1;
}
let score = 1;
for (const token of metadataScopeRankingTokens(metadataScope)) {
if (objectToken.includes(token)) {
score += token.length >= 6 ? 4 : 3;
}
}
return score;
}
function metadataWeightedSurfaceFamilyScores(
matchedObjects: string[],
metadataScope: string | null
): AssistantMcpDiscoveryDerivedMetadataSurface["surface_family_scores"] {
const scores = emptyMetadataSurfaceFamilyScores();
for (const objectName of matchedObjects) {
const entitySet = inferMetadataEntitySetFromObjectName(objectName);
const routeFamily = entitySet ? metadataRouteFamilyForEntitySetRelaxed(entitySet) : null;
if (routeFamily) {
scores[routeFamily] += metadataObjectRelevanceScore(metadataScope, objectName);
}
}
return scores;
}
function sortMetadataObjectsByRelevance(matchedObjects: string[], metadataScope: string | null): string[] {
return [...matchedObjects].sort((left, right) => {
const scoreDelta = metadataObjectRelevanceScore(metadataScope, right) - metadataObjectRelevanceScore(metadataScope, left);
if (scoreDelta !== 0) {
return scoreDelta;
}
return left.localeCompare(right, "ru");
});
}
function metadataObjectsForRouteFamily(
routeFamily: "document_evidence" | "movement_evidence" | "catalog_drilldown" | null,
matchedObjects: string[]
matchedObjects: string[],
metadataScope: string | null
): string[] {
if (!routeFamily) {
return [];
}
return matchedObjects.filter((objectName) => {
const filtered = matchedObjects.filter((objectName) => {
const entitySet = inferMetadataEntitySetFromObjectName(objectName);
return entitySet ? metadataRouteFamilyForEntitySetRelaxed(entitySet) === routeFamily : false;
});
return sortMetadataObjectsByRelevance(filtered, metadataScope);
}
function selectMetadataRouteFamilyFromSurfaceScores(
function selectDominantMetadataRouteFamilyFromScores(
scores: AssistantMcpDiscoveryDerivedMetadataSurface["surface_family_scores"]
): "document_evidence" | "movement_evidence" | "catalog_drilldown" | null {
const ranked = (Object.entries(scores) as Array<
@@ -1345,10 +1417,54 @@ function selectMetadataRouteFamilyFromSurfaceScores(
return clearlyDominant ? top[0] : null;
}
function selectMetadataRouteFamilyFromSurfaceScores(input: {
matchedObjects: string[];
metadataScope: string | null;
countScores: AssistantMcpDiscoveryDerivedMetadataSurface["surface_family_scores"];
allowScopeRanking: boolean;
}): {
routeFamily: "document_evidence" | "movement_evidence" | "catalog_drilldown" | null;
rankingApplied: boolean;
} {
const countDominant = selectDominantMetadataRouteFamilyFromScores(input.countScores);
if (countDominant) {
return {
routeFamily: countDominant,
rankingApplied: false
};
}
if (!input.allowScopeRanking) {
return {
routeFamily: null,
rankingApplied: false
};
}
const rankedCounts = (Object.entries(input.countScores) as Array<
["document_evidence" | "movement_evidence" | "catalog_drilldown", number]
>)
.filter(([, score]) => score > 0)
.sort((left, right) => right[1] - left[1]);
const topCount = rankedCounts[0]?.[1] ?? 0;
const secondCount = rankedCounts[1]?.[1] ?? 0;
if (topCount <= 0 || topCount !== secondCount) {
return {
routeFamily: null,
rankingApplied: false
};
}
const weightedScores = metadataWeightedSurfaceFamilyScores(input.matchedObjects, input.metadataScope);
const weightedDominant = selectDominantMetadataRouteFamilyFromScores(weightedScores);
return {
routeFamily: weightedDominant,
rankingApplied: Boolean(weightedDominant)
};
}
function deriveMetadataSurface(
result: AddressMcpMetadataRowsResult | null,
metadataScope: string | null,
requestedMetaTypes: string[]
requestedMetaTypes: string[],
allowScopeRanking: boolean
): AssistantMcpDiscoveryDerivedMetadataSurface | null {
if (!result || result.error || result.rows.length <= 0) {
return null;
@@ -1370,8 +1486,16 @@ function deriveMetadataSurface(
const selectedEntitySetRouteFamily = grounding.selectedEntitySet
? metadataRouteFamilyForEntitySetRelaxed(grounding.selectedEntitySet)
: null;
const scoredRouteFamily =
selectedEntitySetRouteFamily === null ? selectMetadataRouteFamilyFromSurfaceScores(surfaceFamilyScores) : null;
const scoredRouteSelection =
selectedEntitySetRouteFamily === null
? selectMetadataRouteFamilyFromSurfaceScores({
matchedObjects,
metadataScope,
countScores: surfaceFamilyScores,
allowScopeRanking
})
: { routeFamily: null, rankingApplied: false };
const scoredRouteFamily = scoredRouteSelection.routeFamily;
const downstreamRouteFamily = selectedEntitySetRouteFamily ?? scoredRouteFamily;
const routeFamilySelectionBasis = selectedEntitySetRouteFamily
? "selected_entity_set"
@@ -1380,8 +1504,8 @@ function deriveMetadataSurface(
: null;
const selectedSurfaceObjects =
grounding.selectedEntitySet !== null
? metadataObjectsForEntitySet(grounding.selectedEntitySet, matchedObjects)
: metadataObjectsForRouteFamily(downstreamRouteFamily, matchedObjects);
? sortMetadataObjectsByRelevance(metadataObjectsForEntitySet(grounding.selectedEntitySet, matchedObjects), metadataScope)
: metadataObjectsForRouteFamily(downstreamRouteFamily, matchedObjects, metadataScope);
const knownLimitations: string[] = [];
const ambiguityRemainsUnresolved = grounding.ambiguityDetected && !downstreamRouteFamily;
if (ambiguityRemainsUnresolved && grounding.ambiguityEntitySets.length > 0) {
@@ -1408,6 +1532,7 @@ function deriveMetadataSurface(
recommended_next_primitive: metadataNextPrimitiveForRouteFamily(downstreamRouteFamily),
ambiguity_detected: ambiguityRemainsUnresolved,
ambiguity_entity_sets: ambiguityRemainsUnresolved ? grounding.ambiguityEntitySets : [],
surface_object_ranking_applied: scoredRouteSelection.rankingApplied,
available_fields: metadataAvailableFields(result.rows),
known_limitations: knownLimitations,
inference_basis: "confirmed_1c_metadata_surface_rows"
@@ -2422,12 +2547,20 @@ export async function executeAssistantMcpDiscoveryPilot(
}
const sourceRowsSummary = metadataResult ? summarizeMetadataRows(metadataResult) : null;
const derivedMetadataSurface = deriveMetadataSurface(metadataResult, metadataScope, requestedMetaTypes);
const derivedMetadataSurface = deriveMetadataSurface(
metadataResult,
metadataScope,
requestedMetaTypes,
metadataScopeRankingAllowedForPlanner(planner)
);
if (derivedMetadataSurface) {
pushReason(reasonCodes, "pilot_derived_metadata_surface_from_confirmed_rows");
if (derivedMetadataSurface.route_family_selection_basis === "dominant_surface_objects") {
pushReason(reasonCodes, "pilot_selected_metadata_route_family_from_dominant_surface_objects");
}
if (derivedMetadataSurface.surface_object_ranking_applied) {
pushReason(reasonCodes, "pilot_selected_metadata_route_family_from_surface_object_ranking");
}
}
const evidence = resolveAssistantMcpDiscoveryEvidence({
plan: planner.discovery_plan,