@tencentcloud/sdk-mcp 1.7.8 → 1.7.9-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/knowledge/chunker.js +1 -0
- package/knowledge/frontmatter-meta.js +23 -0
- package/knowledge/path-meta.js +56 -0
- package/knowledge/search/filter-pool.js +9 -1
- package/knowledge/search/rank-profile.js +25 -0
- package/knowledge/search/requires-framework.js +4 -1
- package/knowledge/search/search-core.js +56 -1
- package/knowledge/search/search-pass.js +126 -5
- package/package.json +1 -1
- package/resource/index/manifest.json +1 -1
- package/resource/index/vectors/index.json +2 -2
- package/resource/integration/callkit/preset/android/integration.md +0 -2
- package/resource/integration/callkit/preset/ios/integration.md +0 -2
- package/resource/integration/livekit/preset/live/android/prepare-integration.md +0 -4
- package/resource/integration/livekit/preset/live/ios/prepare-integration.md +0 -4
- package/resource/knowledge/callkit/best-practice/android/video-chat-dating.md +0 -2
- package/resource/knowledge/callkit/core-sdk/android/answer-call.md +0 -2
- package/resource/knowledge/callkit/core-sdk/android/make-call.md +0 -2
- package/resource/knowledge/callkit/core-sdk/flutter/answer-call.md +0 -4
- package/resource/knowledge/callkit/core-sdk/flutter/make-call.md +0 -2
- package/resource/knowledge/callkit/core-sdk/flutter/offline-push.md +0 -2
- package/resource/knowledge/callkit/core-sdk/ios/answer-call.md +0 -2
- package/resource/knowledge/callkit/core-sdk/ios/make-call.md +0 -4
- package/resource/knowledge/callkit/core-sdk/ios/offline-push.md +0 -2
- package/resource/knowledge/callkit/core-sdk/uni-app/answer-call.md +0 -2
- package/resource/knowledge/callkit/core-sdk/uni-app/make-call.md +0 -2
- package/resource/knowledge/callkit/faq/ios.md +0 -2
- package/resource/knowledge/callkit/faq/uniapp-app.md +0 -2
- package/resource/knowledge/callkit/preset/miniprogram/integration.md +0 -2
- package/resource/knowledge/callkit/preset/miniprogram/uniapp-integration.md +0 -2
- package/resource/knowledge/iot/app/activate-service.md +95 -0
- package/resource/knowledge/iot/app/demo/android.md +93 -0
- package/resource/knowledge/iot/app/demo/ios.md +87 -0
- package/resource/knowledge/iot/app/demo/miniprogram.md +79 -0
- package/resource/knowledge/iot/app/device-binding.md +378 -0
- package/resource/knowledge/iot/app/device-sharing.md +414 -0
- package/resource/knowledge/iot/app/family-management.md +762 -0
- package/resource/knowledge/iot/app/integration/android.md +328 -0
- package/resource/knowledge/iot/app/integration/harmonyos.md +326 -0
- package/resource/knowledge/iot/app/integration/ios.md +351 -0
- package/resource/knowledge/iot/app/integration/miniprogram.md +268 -0
- package/resource/knowledge/iot/app/monitor-playback.md +557 -0
- package/resource/knowledge/iot/app/remote-control.md +139 -0
- package/resource/knowledge/iot/app/video-call.md +559 -0
- package/resource/knowledge/iot/app/wechat-call/device-call-miniprogram.md +204 -0
- package/resource/knowledge/iot/app/wechat-call/miniprogram-call-device.md +193 -0
- package/resource/knowledge/iot/client-api/app/android/txiotcallsession.md +189 -0
- package/resource/knowledge/iot/client-api/app/android/txiotcloudstorage.md +77 -0
- package/resource/knowledge/iot/client-api/app/android/txiotdevicemanager.md +175 -0
- package/resource/knowledge/iot/client-api/app/android/txiotengine.md +172 -0
- package/resource/knowledge/iot/client-api/app/android/txiotenginedef.md +163 -0
- package/resource/knowledge/iot/client-api/app/android/txiotfamilymanager.md +146 -0
- package/resource/knowledge/iot/client-api/app/android/txiotmonitorsession.md +246 -0
- package/resource/knowledge/iot/client-api/app/harmonyos/txiotcallsession.md +191 -0
- package/resource/knowledge/iot/client-api/app/harmonyos/txiotcloudstorage.md +77 -0
- package/resource/knowledge/iot/client-api/app/harmonyos/txiotdevicemanager.md +183 -0
- package/resource/knowledge/iot/client-api/app/harmonyos/txiotengine.md +186 -0
- package/resource/knowledge/iot/client-api/app/harmonyos/txiotenginedef.md +164 -0
- package/resource/knowledge/iot/client-api/app/harmonyos/txiotfamilymanager.md +150 -0
- package/resource/knowledge/iot/client-api/app/harmonyos/txiotmonitorsession.md +252 -0
- package/resource/knowledge/iot/client-api/app/ios/txiotcallsession.md +199 -0
- package/resource/knowledge/iot/client-api/app/ios/txiotcloudstorage.md +76 -0
- package/resource/knowledge/iot/client-api/app/ios/txiotdevicemanager.md +173 -0
- package/resource/knowledge/iot/client-api/app/ios/txiotengine.md +173 -0
- package/resource/knowledge/iot/client-api/app/ios/txiotenginedef.md +171 -0
- package/resource/knowledge/iot/client-api/app/ios/txiotfamilymanager.md +146 -0
- package/resource/knowledge/iot/client-api/app/ios/txiotmonitorsession.md +250 -0
- package/resource/knowledge/iot/client-api/app/miniprogram/txiotcallsession.md +180 -0
- package/resource/knowledge/iot/client-api/app/miniprogram/txiotcloudstorage.md +76 -0
- package/resource/knowledge/iot/client-api/app/miniprogram/txiotdevicemanager.md +281 -0
- package/resource/knowledge/iot/client-api/app/miniprogram/txiotengine.md +183 -0
- package/resource/knowledge/iot/client-api/app/miniprogram/txiotenginedef.md +152 -0
- package/resource/knowledge/iot/client-api/app/miniprogram/txiotfamilymanager.md +179 -0
- package/resource/knowledge/iot/client-api/app/miniprogram/txiotmonitorsession.md +226 -0
- package/resource/knowledge/iot/client-api/device/android-smart-device.md +813 -0
- package/resource/knowledge/iot/client-api/device/linux-rtos-device.md +2027 -0
- package/resource/knowledge/iot/device/activate-service.md +167 -0
- package/resource/knowledge/iot/device/ai-voice-chat/advanced-features/custom-agent.md +171 -0
- package/resource/knowledge/iot/device/ai-voice-chat/advanced-features/smart-device-control.md +721 -0
- package/resource/knowledge/iot/device/ai-voice-chat/integration-guide/android-smart-device.md +247 -0
- package/resource/knowledge/iot/device/ai-voice-chat/integration-guide/linux-rtos-device.md +368 -0
- package/resource/knowledge/iot/device/ai-voice-chat/overview.md +84 -0
- package/resource/knowledge/iot/device/cloud-storage.md +696 -0
- package/resource/knowledge/iot/device/data-model.md +972 -0
- package/resource/knowledge/iot/device/demo/android-smart-device.md +97 -0
- package/resource/knowledge/iot/device/demo/linux-rtos-device.md +106 -0
- package/resource/knowledge/iot/device/device-ota-upgrade.md +237 -0
- package/resource/knowledge/iot/device/dynamic-registration/android-smart-device.md +275 -0
- package/resource/knowledge/iot/device/dynamic-registration/linux-rtos-device.md +297 -0
- package/resource/knowledge/iot/device/login-and-register/android-smart-device.md +131 -0
- package/resource/knowledge/iot/device/login-and-register/linux-rtos-device.md +291 -0
- package/resource/knowledge/iot/device/monitor-pushing/android-smart-device.md +237 -0
- package/resource/knowledge/iot/device/monitor-pushing/linux-rtos-device.md +493 -0
- package/resource/knowledge/iot/device/video-call/android-smart-device.md +299 -0
- package/resource/knowledge/iot/device/video-call/linux-rtos-device.md +465 -0
- package/resource/knowledge/iot/device/wechat-call/android-smart-device.md +534 -0
- package/resource/knowledge/iot/device/wechat-call/linux-rtos-device.md +681 -0
- package/resource/knowledge/iot/kids-watch/overview.md +28 -0
- package/resource/knowledge/iot/security-camera/activate-service.md +74 -0
- package/resource/knowledge/iot/security-camera/monitor-playback/app-integration.md +302 -0
- package/resource/knowledge/iot/security-camera/monitor-playback/device-integration/android.md +237 -0
- package/resource/knowledge/iot/security-camera/monitor-playback/device-integration/linux-rtos.md +493 -0
- package/resource/knowledge/iot/security-camera/overview.md +31 -0
- package/resource/knowledge/iot/security-camera/ptz-control.md +153 -0
- package/resource/knowledge/iot/security-camera/recording-and-snapshot.md +182 -0
- package/resource/knowledge/iot/security-camera/voice-intercom.md +174 -0
- package/resource/knowledge/iot/smart-vision/serviceoverview.md +114 -0
- package/resource/knowledge/iot/voice-recorder/app-demo.md +99 -0
- package/resource/knowledge/iot/voice-recorder/device-demo.md +189 -0
- package/resource/knowledge/iot/voice-recorder/overview.md +64 -0
- package/resource/knowledge/livekit/core-sdk/features/android/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/android/gift.md +0 -4
- package/resource/knowledge/livekit/core-sdk/features/android/live-list.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/audio-effect.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/gift.md +0 -4
- package/resource/knowledge/livekit/core-sdk/features/ios/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/gift.md +0 -4
- package/resource/knowledge/livekit/core-sdk/features/ios/live-list.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/uni-app/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/uni-app/gift.md +0 -4
- package/resource/knowledge/livekit/core-sdk/live/android/co-guest-interaction.md +0 -4
- package/resource/knowledge/livekit/core-sdk/live/android/host-interaction.md +0 -10
- package/resource/knowledge/livekit/core-sdk/live/android/integration.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/flutter/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/flutter/host-interaction.md +0 -10
- package/resource/knowledge/livekit/core-sdk/live/flutter/integration.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/ios/co-guest-interaction.md +0 -4
- package/resource/knowledge/livekit/core-sdk/live/ios/host-interaction.md +0 -10
- package/resource/knowledge/livekit/core-sdk/live/ios/integration.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/uni-app/co-guest-interaction.md +0 -4
- package/resource/knowledge/livekit/core-sdk/live/uni-app/host-interaction.md +0 -4
- package/resource/knowledge/livekit/core-sdk/live/uni-app/integration.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/android/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/android/host-interaction.md +0 -4
- package/resource/knowledge/livekit/core-sdk/voice/android/integration.md +0 -4
- package/resource/knowledge/livekit/core-sdk/voice/flutter/integration.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/ios/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/ios/host-interaction.md +0 -4
- package/resource/knowledge/livekit/core-sdk/voice/ios/integration.md +0 -4
- package/resource/knowledge/livekit/core-sdk/voice/uni-app/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/uni-app/integration.md +0 -2
- package/resource/knowledge/livekit/faq/error-code.md +0 -2
- package/resource/knowledge/push/config/donut.md +0 -2
- package/resource/knowledge/push/integration/android.md +0 -5
- package/resource/knowledge/push/integration/donut.md +0 -3
- package/resource/knowledge/push/integration/flutter.md +0 -3
- package/resource/knowledge/push/integration/harmonyos.md +0 -3
- package/resource/knowledge/push/integration/ios.md +0 -3
- package/resource/knowledge/push/integration/react-native.md +0 -5
- package/resource/knowledge/push/integration/uni-app.md +0 -3
- package/resource/knowledge/push/integration/unity.md +0 -3
- package/resource/knowledge/push/integration/unreal-engine.md +0 -3
- package/resource/knowledge/roomkit/core-sdk/android/call-user-to-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/android/room-participant-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/android/room-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/android/schedule-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/flutter/call-user-to-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/flutter/room-participant-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/flutter/room-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/flutter/schedule-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/ios/call-user-to-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/ios/room-participant-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/ios/room-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/ios/schedule-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/vue/room-view.md +0 -3
- package/resource/knowledge/rtcengine/web/how_to_run_web_sdk_demo.md +0 -2
- package/resource/knowledge/rtcengine/web/plugin/24-advanced-network-quality.md +0 -2
- package/tools/common/finalize_answer.js +1 -1
- package/tools/common/search_trtc_knowledge.js +2 -2
- package/tools/definitions/search_trtc_knowledge_def.js +3 -2
- package/utils/preflight-route.js +11 -2
package/knowledge/chunker.js
CHANGED
|
@@ -130,6 +130,7 @@ function buildChunk(meta, source, title, body, id, char_start, char_end, extra)
|
|
|
130
130
|
doc_kind: meta.doc_kind,
|
|
131
131
|
capability_status: meta.capability_status,
|
|
132
132
|
retrievable_scope: meta.retrievable_scope,
|
|
133
|
+
feature_domain: meta.feature_domain,
|
|
133
134
|
meta_source: meta.meta_source,
|
|
134
135
|
meta_override_fields: meta.meta_override_fields,
|
|
135
136
|
title,
|
|
@@ -52,6 +52,24 @@ function normalizeRetrievableScope(value) {
|
|
|
52
52
|
return 'always';
|
|
53
53
|
return normalizeStringArray(value);
|
|
54
54
|
}
|
|
55
|
+
function normalizeFeatureDomain(value) {
|
|
56
|
+
const allowed = [
|
|
57
|
+
'app',
|
|
58
|
+
'app_demo',
|
|
59
|
+
'app_integration',
|
|
60
|
+
'device',
|
|
61
|
+
'device_demo',
|
|
62
|
+
'device_integration',
|
|
63
|
+
'security-camera',
|
|
64
|
+
'smart-vision',
|
|
65
|
+
'kids-watch',
|
|
66
|
+
'voice-recorder',
|
|
67
|
+
'client_api',
|
|
68
|
+
];
|
|
69
|
+
return allowed.includes(value)
|
|
70
|
+
? value
|
|
71
|
+
: undefined;
|
|
72
|
+
}
|
|
55
73
|
function parseFrontmatterObject(input) {
|
|
56
74
|
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
57
75
|
return {};
|
|
@@ -135,6 +153,11 @@ export function resolveFrontmatterMeta(rawMarkdown) {
|
|
|
135
153
|
frontmatterMeta.retrievable_scope = retrievableScope;
|
|
136
154
|
overrideFields.push('retrievable_scope');
|
|
137
155
|
}
|
|
156
|
+
const featureDomain = normalizeFeatureDomain(fm.feature_domain);
|
|
157
|
+
if (featureDomain) {
|
|
158
|
+
frontmatterMeta.feature_domain = featureDomain;
|
|
159
|
+
overrideFields.push('feature_domain');
|
|
160
|
+
}
|
|
138
161
|
return {
|
|
139
162
|
content,
|
|
140
163
|
contentOffset,
|
package/knowledge/path-meta.js
CHANGED
|
@@ -55,6 +55,23 @@ function inferShareScope(fileName) {
|
|
|
55
55
|
}
|
|
56
56
|
return 'always';
|
|
57
57
|
}
|
|
58
|
+
function inferIotFramework(normalizedPath) {
|
|
59
|
+
const pathLower = normalizedPath.toLowerCase();
|
|
60
|
+
if (pathLower.includes('miniprogram'))
|
|
61
|
+
return ['minprogram'];
|
|
62
|
+
if (pathLower.includes('react-native') || /\/(rn)\//.test(pathLower))
|
|
63
|
+
return ['rn'];
|
|
64
|
+
if (pathLower.includes('android'))
|
|
65
|
+
return ['android'];
|
|
66
|
+
if (pathLower.includes('ios'))
|
|
67
|
+
return ['ios'];
|
|
68
|
+
if (pathLower.includes('harmonyos'))
|
|
69
|
+
return ['harmonyos'];
|
|
70
|
+
if (pathLower.includes('linux-rtos') || pathLower.includes('/linux') || pathLower.includes('rtos')) {
|
|
71
|
+
return ['linux'];
|
|
72
|
+
}
|
|
73
|
+
return ['*'];
|
|
74
|
+
}
|
|
58
75
|
export function inferPathMeta(relativeSource) {
|
|
59
76
|
const normalized = relativeSource.replace(/\\/g, '/');
|
|
60
77
|
const parts = normalized.split('/');
|
|
@@ -69,6 +86,7 @@ export function inferPathMeta(relativeSource) {
|
|
|
69
86
|
let doc_kind;
|
|
70
87
|
let capability_status;
|
|
71
88
|
let retrievable_scope;
|
|
89
|
+
let feature_domain;
|
|
72
90
|
if (normalized.startsWith('knowledge/share/')) {
|
|
73
91
|
// 通配语料(跨产品共享)显式建模,不再依赖默认兜底路径。
|
|
74
92
|
product = '*';
|
|
@@ -76,6 +94,43 @@ export function inferPathMeta(relativeSource) {
|
|
|
76
94
|
types.push('faq', 'product');
|
|
77
95
|
retrievable_scope = inferShareScope(fileName);
|
|
78
96
|
}
|
|
97
|
+
else if (normalized.startsWith('knowledge/iot/')) {
|
|
98
|
+
product = 'iot';
|
|
99
|
+
framework = inferIotFramework(normalized);
|
|
100
|
+
const top = parts[2] ?? '';
|
|
101
|
+
const topIsFeature = ['app', 'device', 'security-camera', 'smart-vision', 'kids-watch', 'voice-recorder'].includes(top);
|
|
102
|
+
const topIsApi = top === 'client-api';
|
|
103
|
+
if (topIsFeature) {
|
|
104
|
+
types.push('feature');
|
|
105
|
+
}
|
|
106
|
+
else if (topIsApi) {
|
|
107
|
+
types.push('api');
|
|
108
|
+
}
|
|
109
|
+
if (topIsFeature || topIsApi) {
|
|
110
|
+
if (top === 'app') {
|
|
111
|
+
if (parts[3] === 'demo')
|
|
112
|
+
feature_domain = 'app_demo';
|
|
113
|
+
else if (parts[3] === 'integration')
|
|
114
|
+
feature_domain = 'app_integration';
|
|
115
|
+
else
|
|
116
|
+
feature_domain = 'app';
|
|
117
|
+
}
|
|
118
|
+
else if (top === 'device') {
|
|
119
|
+
if (parts[3] === 'demo')
|
|
120
|
+
feature_domain = 'device_demo';
|
|
121
|
+
else if (parts[3] === 'integration')
|
|
122
|
+
feature_domain = 'device_integration';
|
|
123
|
+
else
|
|
124
|
+
feature_domain = 'device';
|
|
125
|
+
}
|
|
126
|
+
else if (top === 'client-api') {
|
|
127
|
+
feature_domain = 'client_api';
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
feature_domain = top;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
79
134
|
else if (normalized.startsWith('knowledge/chat/') || normalized.startsWith('integration/chat/')) {
|
|
80
135
|
product = 'chat';
|
|
81
136
|
if (parts.includes('preset') && parts.length >= 4) {
|
|
@@ -386,6 +441,7 @@ export function inferPathMeta(relativeSource) {
|
|
|
386
441
|
doc_kind,
|
|
387
442
|
capability_status,
|
|
388
443
|
retrievable_scope,
|
|
444
|
+
feature_domain,
|
|
389
445
|
meta_source: 'path',
|
|
390
446
|
meta_override_fields: [],
|
|
391
447
|
};
|
|
@@ -6,7 +6,12 @@ import { hasExplicitFrameworkMatch, hasFrameworkFallbackMatch } from './framewor
|
|
|
6
6
|
* path-meta.ts 已通过 normalizeFrameworkDir 把目录名归一到标准 framework,
|
|
7
7
|
* 所有产品的 framework 均已对齐枚举值,无需额外别名扩展。
|
|
8
8
|
*/
|
|
9
|
-
const FRAMEWORK_SEARCH_ALIASES = {
|
|
9
|
+
const FRAMEWORK_SEARCH_ALIASES = {
|
|
10
|
+
miniprogram: ['miniprogram', 'minprogram'],
|
|
11
|
+
minprogram: ['minprogram', 'miniprogram'],
|
|
12
|
+
'react-native': ['react-native', 'rn'],
|
|
13
|
+
rn: ['rn', 'react-native'],
|
|
14
|
+
};
|
|
10
15
|
function expandFrameworks(frameworks, _products) {
|
|
11
16
|
if (!frameworks?.length)
|
|
12
17
|
return undefined;
|
|
@@ -166,6 +171,9 @@ export function isSoftAllowed(chunk, norm) {
|
|
|
166
171
|
if (norm.scenario && chunk.scenario && chunk.scenario !== norm.scenario) {
|
|
167
172
|
return false;
|
|
168
173
|
}
|
|
174
|
+
// IoT 端别过滤改为“召回保留 + 排序分层”:
|
|
175
|
+
// Phase2 中 exact/common/conflict 的优先级由 applyRankMultipliers 处理,
|
|
176
|
+
// 这里不做硬过滤,避免因标注偏差误杀有效候选。
|
|
169
177
|
// best-practice 文档对 types 过滤免疫:内容不依赖 types 分类,应始终进 pool 靠 BM25 自然排名。
|
|
170
178
|
// 典型场景:Agent 传 types=['api'] 时,types=['faq'] 的 best-practice 不应被过滤掉。
|
|
171
179
|
if (norm.types?.length && !norm.types.some((t) => chunk.types.includes(t))) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const DEFAULT_PROFILE = {
|
|
2
|
+
name: 'default',
|
|
3
|
+
maxPerSource: 3,
|
|
4
|
+
rerankTopK: 20,
|
|
5
|
+
lowConfidenceRerankTopK: 0,
|
|
6
|
+
lowConfidenceTopScoreThreshold: 0,
|
|
7
|
+
lowConfidenceGapRatioThreshold: 0,
|
|
8
|
+
titleExactMultiplier: 1.03,
|
|
9
|
+
titleTokenBoost: 0.05,
|
|
10
|
+
};
|
|
11
|
+
const IOT_PROFILE = {
|
|
12
|
+
name: 'iot',
|
|
13
|
+
maxPerSource: 2,
|
|
14
|
+
rerankTopK: 24,
|
|
15
|
+
lowConfidenceRerankTopK: 10,
|
|
16
|
+
lowConfidenceTopScoreThreshold: 28,
|
|
17
|
+
lowConfidenceGapRatioThreshold: 1.08,
|
|
18
|
+
titleExactMultiplier: 1.15,
|
|
19
|
+
titleTokenBoost: 0.15,
|
|
20
|
+
};
|
|
21
|
+
export function resolveRankProfile(params) {
|
|
22
|
+
if (params.product?.includes('iot'))
|
|
23
|
+
return IOT_PROFILE;
|
|
24
|
+
return DEFAULT_PROFILE;
|
|
25
|
+
}
|
|
@@ -8,7 +8,7 @@ const PLATFORM_TYPES = new Set([
|
|
|
8
8
|
'integration',
|
|
9
9
|
]);
|
|
10
10
|
const CROSS_PLATFORM_TYPES = new Set(['server_api', 'webhook', 'product']);
|
|
11
|
-
const CROSS_PLATFORM_PROMPT = /计费|套餐|价格|UserSig\s*原理|签发流程|控制台|服务端\s*REST|云\s*API|Webhook|回调|callback|server\s*callback
|
|
11
|
+
const CROSS_PLATFORM_PROMPT = /计费|套餐|价格|UserSig\s*原理|签发流程|控制台|服务端\s*REST|云\s*API|Webhook|回调|callback|server\s*callback|物联网开发平台|安防摄像头|智能视觉服务|儿童手表|录音卡/i;
|
|
12
12
|
const PLATFORM_PROMPT = /API|组件|怎么用|怎么开|怎么设置|怎么配置|虚拟背景|屏幕分享|enterRoom|SDK|插件|集成步骤|客户端|Feature|主题定制|连麦|上麦/i;
|
|
13
13
|
/**
|
|
14
14
|
* push 必须问平台的强信号:仅当 prompt 明确提到具体「平台」(android/ios/flutter/...)时才拦询问。
|
|
@@ -60,6 +60,9 @@ export function requiresFramework(norm) {
|
|
|
60
60
|
return false;
|
|
61
61
|
return false;
|
|
62
62
|
}
|
|
63
|
+
// iot:产品级/能力线/API 问法第一阶段允许跨平台检索,不做 framework 前置拦截
|
|
64
|
+
if (hasProduct(norm, 'iot'))
|
|
65
|
+
return false;
|
|
63
66
|
// native_trtc_sdk:所有平台相关咨询都依赖具体客户端(android/ios/c++),必须先问
|
|
64
67
|
if (hasProduct(norm, 'native_trtc_sdk'))
|
|
65
68
|
return true;
|
|
@@ -51,6 +51,7 @@ export function postProcess(ranked, chunksById, limit, opts) {
|
|
|
51
51
|
}
|
|
52
52
|
const sourceCount = {};
|
|
53
53
|
const urlMappingSourceCount = {};
|
|
54
|
+
const maxPerSource = Math.max(1, opts?.maxPerSource ?? 3);
|
|
54
55
|
/** 已入选的 push config/android/{vendor} 文件,用于抑制其他厂商噪声 */
|
|
55
56
|
let selectedVendorFile = null;
|
|
56
57
|
const fragments = [];
|
|
@@ -70,7 +71,7 @@ export function postProcess(ranked, chunksById, limit, opts) {
|
|
|
70
71
|
}
|
|
71
72
|
else {
|
|
72
73
|
const count = sourceCount[chunk.source] ?? 0;
|
|
73
|
-
if (count >=
|
|
74
|
+
if (count >= maxPerSource)
|
|
74
75
|
continue;
|
|
75
76
|
sourceCount[chunk.source] = count + 1;
|
|
76
77
|
}
|
|
@@ -384,7 +385,29 @@ export function hasNativeClientFramework(frameworks) {
|
|
|
384
385
|
return false;
|
|
385
386
|
return frameworks.some((fw) => ['android', 'ios', 'flutter', 'c++'].includes(fw));
|
|
386
387
|
}
|
|
388
|
+
function normalizeCompactText(input) {
|
|
389
|
+
return input.toLowerCase().replace(/[\s\-_]+/g, '');
|
|
390
|
+
}
|
|
391
|
+
function hasExactTitleMatch(prompt, title) {
|
|
392
|
+
if (!prompt || !title)
|
|
393
|
+
return false;
|
|
394
|
+
const p = normalizeCompactText(prompt);
|
|
395
|
+
const t = normalizeCompactText(title);
|
|
396
|
+
if (!p || !t)
|
|
397
|
+
return false;
|
|
398
|
+
return (t.length >= 3 && p.includes(t)) || (p.length >= 3 && t.includes(p));
|
|
399
|
+
}
|
|
400
|
+
function tokenizePromptForTitle(prompt) {
|
|
401
|
+
return [...new Set(prompt
|
|
402
|
+
.toLowerCase()
|
|
403
|
+
.split(/[^a-z0-9\u4e00-\u9fff]+/)
|
|
404
|
+
.map((s) => s.trim())
|
|
405
|
+
.filter((s) => s.length >= 2))];
|
|
406
|
+
}
|
|
387
407
|
export function applyRankMultipliers(ranked, chunksById, opts) {
|
|
408
|
+
const prompt = opts.prompt ?? '';
|
|
409
|
+
const promptTokens = tokenizePromptForTitle(prompt);
|
|
410
|
+
const isIotProfile = opts.rank_profile === 'iot';
|
|
388
411
|
const adjusted = ranked.map((item) => {
|
|
389
412
|
const chunk = chunksById.get(item.id);
|
|
390
413
|
if (!chunk)
|
|
@@ -402,6 +425,38 @@ export function applyRankMultipliers(ranked, chunksById, opts) {
|
|
|
402
425
|
multiplier *= 0.2;
|
|
403
426
|
}
|
|
404
427
|
}
|
|
428
|
+
// Phase1: title/h2 与 query 精确短语命中增强
|
|
429
|
+
if (prompt && hasExactTitleMatch(prompt, chunk.title)) {
|
|
430
|
+
multiplier *= isIotProfile ? 1.15 : 1.03;
|
|
431
|
+
}
|
|
432
|
+
if (promptTokens.length > 0) {
|
|
433
|
+
const titleText = `${chunk.title} ${(chunk.key_phrases ?? []).join(' ')}`.toLowerCase();
|
|
434
|
+
const overlap = promptTokens.reduce((acc, token) => (titleText.includes(token) ? acc + 1 : acc), 0);
|
|
435
|
+
if (overlap > 0) {
|
|
436
|
+
multiplier *= 1 + Math.min(0.06, overlap * (isIotProfile ? 0.015 : 0.008));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
// Phase2: IoT feature_domain 软回退(IoT 唯一排序信号)
|
|
440
|
+
if (chunk.product === 'iot') {
|
|
441
|
+
if (chunk.feature_domain && opts.preferred_iot_feature_domain) {
|
|
442
|
+
if (chunk.feature_domain === opts.preferred_iot_feature_domain)
|
|
443
|
+
multiplier *= 1.15;
|
|
444
|
+
else
|
|
445
|
+
multiplier *= 0.9;
|
|
446
|
+
}
|
|
447
|
+
// Phase2b: 强 feature 意图 → source 精准置顶
|
|
448
|
+
// 中文意图词(云台/语音对讲)与英文文件名(ptz-control/voice-intercom)无词面关系,
|
|
449
|
+
// 用 source 路径关键词精准命中 feature 文档,越过短文本泛文档的 BM25 优势。
|
|
450
|
+
if (opts.preferred_iot_feature_source && chunk.source.includes(opts.preferred_iot_feature_source)) {
|
|
451
|
+
multiplier *= 1.7;
|
|
452
|
+
}
|
|
453
|
+
// 非 demo 意图下,弱化 app_demo/device_demo 对功能问法的抢位
|
|
454
|
+
if (chunk.feature_domain && /demo$/i.test(chunk.feature_domain)) {
|
|
455
|
+
if (!/\bdemo\b|示例|sample|example|演示/i.test(prompt)) {
|
|
456
|
+
multiplier *= 0.82;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
405
460
|
return { ...item, score: item.score * multiplier };
|
|
406
461
|
});
|
|
407
462
|
return adjusted.sort((a, b) => b.score - a.score);
|
|
@@ -8,6 +8,7 @@ import { computeGenericAnchorBoosts } from './generic-rerank.js';
|
|
|
8
8
|
import { embedQuery, withQueryInstruction } from '../embedding/embed-model.js';
|
|
9
9
|
import { queryVectors } from '../embedding/vector-index.js';
|
|
10
10
|
import { applyRankMultipliers, computeApiNameCoverage, computeMissingApiTokens, isUrlMappingSource, postProcess, } from './search-core.js';
|
|
11
|
+
import { resolveRankProfile } from './rank-profile.js';
|
|
11
12
|
function isBestPracticeSource(source) {
|
|
12
13
|
return /\/best-practice\//i.test(source);
|
|
13
14
|
}
|
|
@@ -311,6 +312,74 @@ function stableSortRanked(items) {
|
|
|
311
312
|
return a.id.localeCompare(b.id);
|
|
312
313
|
});
|
|
313
314
|
}
|
|
315
|
+
function inferIotFeatureDomainFromPrompt(prompt) {
|
|
316
|
+
if (!prompt)
|
|
317
|
+
return undefined;
|
|
318
|
+
if (/安防摄像头|云台|\bPTZ\b|语音对讲|监控|回放|录像|录制|截图/i.test(prompt)) {
|
|
319
|
+
return 'security-camera';
|
|
320
|
+
}
|
|
321
|
+
if (/儿童手表/i.test(prompt))
|
|
322
|
+
return 'kids-watch';
|
|
323
|
+
if (/录音卡|语音卡/i.test(prompt))
|
|
324
|
+
return 'voice-recorder';
|
|
325
|
+
if (/智能视觉|视觉服务/i.test(prompt))
|
|
326
|
+
return 'smart-vision';
|
|
327
|
+
if (/设备端|linux|rtos|模组|芯片/i.test(prompt))
|
|
328
|
+
return 'device';
|
|
329
|
+
if (/客户端\s*api|client\s*api|\bTXIoT[A-Za-z0-9_]+\b/i.test(prompt))
|
|
330
|
+
return 'client_api';
|
|
331
|
+
if (/app\s*demo|示例工程|demo/i.test(prompt))
|
|
332
|
+
return 'app_demo';
|
|
333
|
+
if (/应用端接入|app接入|app\s*集成/i.test(prompt))
|
|
334
|
+
return 'app_integration';
|
|
335
|
+
return undefined;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* IoT 强 feature 意图 → source 路径关键词映射。
|
|
339
|
+
* 中文意图词(云台/语音对讲)与英文文件名(ptz-control/voice-intercom)无直接词面关系,
|
|
340
|
+
* 需显式映射才能在排序层精准置顶对应 feature 文档,避免被短文本泛文档的 BM25 优势压制。
|
|
341
|
+
*
|
|
342
|
+
* 注意:仅收录「一 feature 一精准文件」的映射。像 monitor-playback 这类分布在
|
|
343
|
+
* 多端侧(app/device/security-camera)的 feature 不在此列,避免无差别 source boost
|
|
344
|
+
* 把 device 侧文档抬高、压制 app 侧(见 regression case 22)。
|
|
345
|
+
*/
|
|
346
|
+
const IOT_FEATURE_INTENT_MAP = [
|
|
347
|
+
{ re: /云台|\bPTZ\b/i, keyword: 'ptz-control' },
|
|
348
|
+
{ re: /语音对讲|对讲|intercom/i, keyword: 'voice-intercom' },
|
|
349
|
+
];
|
|
350
|
+
function inferIotFeatureSourceKeyword(prompt) {
|
|
351
|
+
if (!prompt)
|
|
352
|
+
return undefined;
|
|
353
|
+
for (const { re, keyword } of IOT_FEATURE_INTENT_MAP) {
|
|
354
|
+
if (re.test(prompt))
|
|
355
|
+
return keyword;
|
|
356
|
+
}
|
|
357
|
+
return undefined;
|
|
358
|
+
}
|
|
359
|
+
function inferPreferredIotFeatureDomain(ranked, chunksById, prompt) {
|
|
360
|
+
const byPrompt = inferIotFeatureDomainFromPrompt(prompt ?? '');
|
|
361
|
+
if (byPrompt)
|
|
362
|
+
return byPrompt;
|
|
363
|
+
const scoreByDomain = new Map();
|
|
364
|
+
const sampleWindow = Math.min(ranked.length, 80);
|
|
365
|
+
for (let i = 0; i < sampleWindow; i += 1) {
|
|
366
|
+
const item = ranked[i];
|
|
367
|
+
const chunk = chunksById.get(item.id);
|
|
368
|
+
if (!chunk || chunk.product !== 'iot' || !chunk.feature_domain)
|
|
369
|
+
continue;
|
|
370
|
+
const domain = chunk.feature_domain;
|
|
371
|
+
scoreByDomain.set(domain, (scoreByDomain.get(domain) ?? 0) + Math.max(item.score, 0));
|
|
372
|
+
}
|
|
373
|
+
let preferred;
|
|
374
|
+
let best = -1;
|
|
375
|
+
for (const [domain, score] of scoreByDomain.entries()) {
|
|
376
|
+
if (score > best) {
|
|
377
|
+
best = score;
|
|
378
|
+
preferred = domain;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return preferred;
|
|
382
|
+
}
|
|
314
383
|
function fuseByRRF(params) {
|
|
315
384
|
const { bm25Ranked, vectorHits, rrfK, baseBeta, alpha, profile, } = params;
|
|
316
385
|
const bmWeight = profile?.bmWeight ?? 1;
|
|
@@ -392,8 +461,35 @@ function resolveFusionProfile(prompt, queryApiTokens) {
|
|
|
392
461
|
}
|
|
393
462
|
return { name: 'default', bmWeight: 1.0, vecWeight: 1.0, alphaScale: 1.0 };
|
|
394
463
|
}
|
|
464
|
+
function normalizeCompactText(input) {
|
|
465
|
+
return input.toLowerCase().replace(/[\s\-_]+/g, '');
|
|
466
|
+
}
|
|
467
|
+
function hasTitleExactMatch(prompt, title) {
|
|
468
|
+
if (!prompt || !title)
|
|
469
|
+
return false;
|
|
470
|
+
const p = normalizeCompactText(prompt);
|
|
471
|
+
const t = normalizeCompactText(title);
|
|
472
|
+
if (!p || !t)
|
|
473
|
+
return false;
|
|
474
|
+
if (t.length >= 3 && p.includes(t))
|
|
475
|
+
return true;
|
|
476
|
+
if (p.length >= 3 && t.includes(p))
|
|
477
|
+
return true;
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
function shouldTriggerLowConfidenceRerank(params) {
|
|
481
|
+
const { ranked, rankProfile } = params;
|
|
482
|
+
if (rankProfile.lowConfidenceRerankTopK <= 0 || ranked.length < 2)
|
|
483
|
+
return false;
|
|
484
|
+
const top = ranked[0]?.score ?? 0;
|
|
485
|
+
const second = ranked[1]?.score ?? 0;
|
|
486
|
+
if (top <= 0)
|
|
487
|
+
return false;
|
|
488
|
+
const ratio = second > 0 ? top / second : Number.POSITIVE_INFINITY;
|
|
489
|
+
return top <= rankProfile.lowConfidenceTopScoreThreshold || ratio <= rankProfile.lowConfidenceGapRatioThreshold;
|
|
490
|
+
}
|
|
395
491
|
function rerankTopK(params) {
|
|
396
|
-
const { prompt, ranked, chunksById, topK } = params;
|
|
492
|
+
const { prompt, ranked, chunksById, topK, rankProfile, } = params;
|
|
397
493
|
if (ranked.length < 2 || topK <= 0)
|
|
398
494
|
return { ranked, applied: false };
|
|
399
495
|
const head = ranked.slice(0, topK);
|
|
@@ -408,9 +504,13 @@ function rerankTopK(params) {
|
|
|
408
504
|
return item;
|
|
409
505
|
const text = [chunk.title, ...(chunk.key_phrases ?? [])].join(' ').toLowerCase();
|
|
410
506
|
const overlap = promptTokens.reduce((acc, token) => (text.includes(token.toLowerCase()) ? acc + 1 : acc), 0);
|
|
411
|
-
if (overlap <= 0)
|
|
507
|
+
if (overlap <= 0 && !hasTitleExactMatch(prompt, chunk.title))
|
|
412
508
|
return item;
|
|
413
|
-
|
|
509
|
+
let boost = topScore * 0.002 * overlap;
|
|
510
|
+
if (hasTitleExactMatch(prompt, chunk.title)) {
|
|
511
|
+
boost += Math.max(topScore * 0.015, 1.5) * (rankProfile.titleExactMultiplier - 1);
|
|
512
|
+
}
|
|
513
|
+
boost += rankProfile.titleTokenBoost * overlap;
|
|
414
514
|
return { ...item, score: item.score + boost };
|
|
415
515
|
});
|
|
416
516
|
const rerankedHead = stableSortRanked(bumped);
|
|
@@ -422,6 +522,7 @@ export async function runSearchPass(params) {
|
|
|
422
522
|
const effectivePassNorm = retrievalMode === 'discovery'
|
|
423
523
|
? { ...passNorm, types: undefined }
|
|
424
524
|
: passNorm;
|
|
525
|
+
const rankProfile = resolveRankProfile({ product: effectivePassNorm.product });
|
|
425
526
|
let pool = filterPool(allChunks, effectivePassNorm);
|
|
426
527
|
// types 误传自愈:首轮保留,二次扩检也同样保留该能力
|
|
427
528
|
if (pool.length === 0 && effectivePassNorm.types?.length) {
|
|
@@ -468,7 +569,7 @@ export async function runSearchPass(params) {
|
|
|
468
569
|
const baseBeta = readEnvNumber('VECTOR_AUGMENT_BASE_BETA', 0.3);
|
|
469
570
|
const topK = Math.max(1, Math.floor(readEnvNumber('VECTOR_TOP_K', DEFAULT_VECTOR_TOP_K)));
|
|
470
571
|
const rrfK = Math.max(1, Math.floor(readEnvNumber('VECTOR_RRF_K', DEFAULT_RRF_K)));
|
|
471
|
-
const rerankTopKLimit = Math.max(0, Math.floor(readEnvNumber('VECTOR_RERANK_TOP_K', DEFAULT_RERANK_TOP_K)));
|
|
572
|
+
const rerankTopKLimit = Math.max(0, Math.floor(readEnvNumber('VECTOR_RERANK_TOP_K', rankProfile.rerankTopK || DEFAULT_RERANK_TOP_K)));
|
|
472
573
|
const fullDocumentMaxChars = Math.max(1000, Math.floor(readEnvNumber('SEARCH_FULL_DOCUMENT_MAX_CHARS', 7000)));
|
|
473
574
|
let rankedFused = ranked;
|
|
474
575
|
// 向量归因埋点采集(终态归因在函数末尾统一构造):
|
|
@@ -536,6 +637,7 @@ export async function runSearchPass(params) {
|
|
|
536
637
|
ranked: fused.ranked,
|
|
537
638
|
chunksById,
|
|
538
639
|
topK: rerankTopKLimit,
|
|
640
|
+
rankProfile,
|
|
539
641
|
});
|
|
540
642
|
rankedFused = reranked.ranked;
|
|
541
643
|
}
|
|
@@ -545,12 +647,30 @@ export async function runSearchPass(params) {
|
|
|
545
647
|
// 快照变量维持初始值即可。归因阶段 vector_top1_id 为 null 天然反映降级。
|
|
546
648
|
}
|
|
547
649
|
}
|
|
650
|
+
const preferredIotFeatureDomain = inferPreferredIotFeatureDomain(rankedFused, chunksById, passNorm.prompt);
|
|
651
|
+
const preferredIotFeatureSource = inferIotFeatureSourceKeyword(passNorm.prompt);
|
|
548
652
|
const rankedWithMultipliers = applyRankMultipliers(rankedFused, chunksById, {
|
|
549
653
|
product: passNorm.product,
|
|
550
654
|
framework: passNorm.framework,
|
|
551
655
|
frameworks: passNorm.frameworks,
|
|
656
|
+
preferred_iot_feature_domain: preferredIotFeatureDomain,
|
|
657
|
+
preferred_iot_feature_source: preferredIotFeatureSource,
|
|
658
|
+
prompt: passNorm.prompt,
|
|
659
|
+
rank_profile: rankProfile.name,
|
|
552
660
|
});
|
|
553
|
-
|
|
661
|
+
let rankedAfterIntentGuard = applyDiagnosisIntentGuard(rankedWithMultipliers, chunksById, passNorm.prompt);
|
|
662
|
+
if (shouldTriggerLowConfidenceRerank({ ranked: rankedAfterIntentGuard, rankProfile })) {
|
|
663
|
+
const secondPass = rerankTopK({
|
|
664
|
+
prompt: passNorm.prompt,
|
|
665
|
+
ranked: rankedAfterIntentGuard,
|
|
666
|
+
chunksById,
|
|
667
|
+
topK: rankProfile.lowConfidenceRerankTopK,
|
|
668
|
+
rankProfile,
|
|
669
|
+
});
|
|
670
|
+
if (secondPass.applied) {
|
|
671
|
+
rankedAfterIntentGuard = secondPass.ranked;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
554
674
|
const promptLockPolicy = decidePromptLockPolicy(passNorm.prompt);
|
|
555
675
|
const allowContentPriority = promptLockPolicy.enableContentPriority;
|
|
556
676
|
const allowFullDocumentLock = promptLockPolicy.enableFullDocumentLock;
|
|
@@ -593,6 +713,7 @@ export async function runSearchPass(params) {
|
|
|
593
713
|
preferredSource: dominantBestPractice.preferredSource,
|
|
594
714
|
fullDocumentMode: dominantBestPractice.fullDocumentMode,
|
|
595
715
|
fullDocumentMaxChars,
|
|
716
|
+
maxPerSource: rankProfile.maxPerSource,
|
|
596
717
|
});
|
|
597
718
|
const urlMappingSources = [...new Set(fragments.map((f) => f.source).filter((source) => isUrlMappingSource(source)))];
|
|
598
719
|
const references = buildReferences(fragments);
|