koishi-plugin-image-prompt 1.1.1 → 1.2.0
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/lib/index.d.ts +63 -1
- package/lib/index.js +340 -16
- package/package.json +1 -1
- package/readme.md +65 -6
- package/src/index.ts +446 -17
package/lib/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare const inject: {
|
|
|
9
9
|
required: string[];
|
|
10
10
|
optional: string[];
|
|
11
11
|
};
|
|
12
|
-
export declare const usage = "\n---\n\n\u6B64\u63D2\u4EF6\u76F4\u63A5\u8C03\u7528 OpenAI \u517C\u5BB9\u7684 Chat Completions \u63A5\u53E3\u751F\u6210\u56FE\u7247\n\n\u8BF7\u5728\u63D2\u4EF6\u8BBE\u7F6E\u4E2D\u586B\u5199\uFF1A\n\n- API \u670D\u52A1\u5668\u5730\u5740\uFF08baseUrl\uFF09\n- \u4F7F\u7528\u7684\u6A21\u578B\uFF08model\uFF09\n- API \u5BC6\u94A5\uFF08apiKey\uFF09\n\n\u3010AI \u9009\u62E9\u53C2\u8003\u56FE\u7247\u3011\n\n1. \u5728\u300C\u53C2\u8003\u56FE\u7247\u7EC4\u300D\u4E2D\u6CE8\u518C\u5206\u7EC4\uFF1A\u6BCF\u7EC4\u586B\u5199\u82E5\u5E72\u5F20\u300C\u56FE\u7247\u94FE\u63A5 + \u63CF\u8FF0\u300D\uFF08\u63CF\u8FF0\u7528\u4E8E\u8BA9 AI \u5224\u65AD\u8BE5\u56FE\u7684\u7528\u9014\uFF09\u3002\n2. \u5728\u6307\u4EE4\u914D\u7F6E\u7684\u300C\u5F15\u7528\u7684\u53C2\u8003\u56FE\u7247\u7EC4\u540D\u79F0\u300D\u4E2D\u586B\u5165\u7EC4\u540D\uFF08\u53EF\u586B\u591A\u4E2A\uFF09\uFF0C\u8BE5\u6307\u4EE4\u6267\u884C\u65F6\u4F1A\u628A\u7EC4\u5185\u56FE\u7247\u5168\u90E8\u4EA4\u7ED9 AI \u6311\u9009\u3002\n3. \u300CAI \u9009\u56FE\u8BBE\u7F6E\u300D\u53EF\u4FEE\u6539\u5BF9\u8BDD\u6A21\u578B\uFF08\u9ED8\u8BA4 Qwen/Qwen2.5-7B-Instruct\uFF09\u3001\u9009\u62E9\u63D0\u793A\u8BCD\u6A21\u677F\u3001\u8D85\u65F6\u4E0E\u91CD\u8BD5\u7B49\uFF1B\n \u63A5\u53E3\u5730\u5740/\u5BC6\u94A5\u7559\u7A7A\u65F6\u590D\u7528\u7ED8\u56FE\u63A5\u53E3\u7684\u914D\u7F6E\u3002\n4. \
|
|
12
|
+
export declare const usage = "\n---\n\n\u6B64\u63D2\u4EF6\u76F4\u63A5\u8C03\u7528 OpenAI \u517C\u5BB9\u7684 Chat Completions \u63A5\u53E3\u751F\u6210\u56FE\u7247\n\n\u8BF7\u5728\u63D2\u4EF6\u8BBE\u7F6E\u4E2D\u586B\u5199\uFF1A\n\n- API \u670D\u52A1\u5668\u5730\u5740\uFF08baseUrl\uFF09\n- \u4F7F\u7528\u7684\u6A21\u578B\uFF08model\uFF09\n- API \u5BC6\u94A5\uFF08apiKey\uFF09\n\n\u3010AI \u9009\u62E9\u53C2\u8003\u56FE\u7247\u3011\n\n1. \u5728\u300C\u53C2\u8003\u56FE\u7247\u7EC4\u300D\u4E2D\u6CE8\u518C\u5206\u7EC4\uFF1A\u6BCF\u7EC4\u586B\u5199\u82E5\u5E72\u5F20\u300C\u56FE\u7247\u94FE\u63A5 + \u63CF\u8FF0\u300D\uFF08\u63CF\u8FF0\u7528\u4E8E\u8BA9 AI \u5224\u65AD\u8BE5\u56FE\u7684\u7528\u9014\uFF09\u3002\n **\u63CF\u8FF0\u4E00\u5B9A\u8981\u5199\u5177\u4F53**\uFF08\u53D1\u8272\u53D1\u578B\u3001\u670D\u88C5\u3001\u52A8\u4F5C\u3001\u753B\u98CE\uFF09\u2014\u2014 \u6253\u5206\u5236\u4E0B\u6CA1\u63CF\u8FF0\u7684\u56FE\u6C38\u8FDC\u9009\u4E0D\u4E0A\u3002\n2. \u5728\u6307\u4EE4\u914D\u7F6E\u7684\u300C\u5F15\u7528\u7684\u53C2\u8003\u56FE\u7247\u7EC4\u540D\u79F0\u300D\u4E2D\u586B\u5165\u7EC4\u540D\uFF08\u53EF\u586B\u591A\u4E2A\uFF09\uFF0C\u8BE5\u6307\u4EE4\u6267\u884C\u65F6\u4F1A\u628A\u7EC4\u5185\u56FE\u7247\u5168\u90E8\u4EA4\u7ED9 AI \u6311\u9009\u3002\n3. \u300CAI \u9009\u56FE\u8BBE\u7F6E\u300D\u53EF\u4FEE\u6539\u5BF9\u8BDD\u6A21\u578B\uFF08\u9ED8\u8BA4 Qwen/Qwen2.5-7B-Instruct\uFF09\u3001\u9009\u62E9\u6A21\u5F0F\u3001\u63D0\u793A\u8BCD\u6A21\u677F\u3001\u8D85\u65F6\u4E0E\u91CD\u8BD5\u7B49\uFF1B\n \u63A5\u53E3\u5730\u5740/\u5BC6\u94A5\u7559\u7A7A\u65F6\u590D\u7528\u7ED8\u56FE\u63A5\u53E3\u7684\u914D\u7F6E\u3002\n4. \u300C\u9009\u56FE\u6A21\u5F0F\u300D\u9ED8\u8BA4\u662F**\u6253\u5206\u5236**\uFF1A\u5148\u53EA\u505A\u9700\u6C42\u5206\u6790\uFF08**\u4E0D\u7ED9\u6A21\u578B\u5019\u9009\u56FE**\uFF0C\u5B83\u6CA1\u6709\u300C\u53EF\u6311\u7684\u5BF9\u8C61\u300D\uFF09\uFF0C\n \u518D\u7528\u5173\u952E\u8BCD\u5728\u672C\u5730\u53EC\u56DE\uFF0C\u7136\u540E\u8981\u6C42\u6A21\u578B\u7ED9\u6BCF\u5F20\u5019\u9009\u56FE\u6253 0-100 \u5206\uFF0C\u4F4E\u4E8E\u300C\u6700\u4F4E\u5206\u6570\u7EBF\u300D\u7684\u4E00\u5F8B\u4E0D\u8981\u3002\n \u4E00\u5F20\u90FD\u4E0D\u8FBE\u6807\u5C31\u5982\u5B9E\u544A\u77E5\u7528\u6237\u300C\u56FE\u5E93\u91CC\u6CA1\u6709\u5408\u9002\u7684\u53C2\u8003\u56FE\u300D\uFF0C**\u4E0D\u4F1A\u786C\u51D1**\uFF1B\n \u82E5\u5F00\u542F\u300C\u7F3A\u5C11\u5408\u9002\u53C2\u8003\u56FE\u65F6\u8BE2\u95EE\u7528\u6237\u8865\u5145\u53D1\u9001\u300D\uFF0C\u4F1A\u8BF7\u7528\u6237\u8865\u53D1\u4E00\u5F20\u53C2\u8003\u56FE\uFF08\u7528\u6237\u53D1\u7684\u56FE\u4F1A\u88AB\u76F4\u63A5\u4F7F\u7528\uFF09\u3002\n \u60F3\u56DE\u5230\u8001\u884C\u4E3A\u5C31\u628A\u300C\u9009\u56FE\u6A21\u5F0F\u300D\u6539\u6210\u300C\u65E7\u7248\u300D\u3002\n5. \u5F53\u7528\u6237\u660E\u786E\u8BF4\u300C\u4E0D\u7528\u53C2\u8003 / \u968F\u610F\u753B / \u81EA\u7531\u53D1\u6325\u300D\u65F6\uFF0C\u76F4\u63A5\u8DF3\u8FC7\u9009\u56FE\uFF0C\u4E00\u6B21\u9009\u56FE\u8BF7\u6C42\u90FD\u4E0D\u53D1\u3002\n6. \u300C\u542F\u7528 AI \u667A\u80FD\u9009\u62E9\u53C2\u8003\u56FE\u7247\u300D\u9ED8\u8BA4\u5173\u95ED\uFF0C\u9700\u624B\u52A8\u5F00\u542F\uFF1B\u300CAI \u9009\u56FE\u5931\u8D25\u65F6\u56DE\u9000\u4E3A\u4F7F\u7528\u5019\u9009\u6C60\u5185\u5168\u90E8\u56FE\u7247\u300D\u9ED8\u8BA4\u5173\u95ED\uFF0C\n \u5931\u8D25\u65F6\u672C\u6B21\u4E0D\u4F7F\u7528\u53C2\u8003\u56FE\u7247\uFF08\u5F00\u542F\u5219\u6539\u7528\u5019\u9009\u6C60\u5185\u5168\u90E8\u56FE\u7247\uFF09\u3002\u6CE8\u610F\u300C\u56DE\u9000\u300D\u53EA\u5BF9**\u8BF7\u6C42\u5931\u8D25**\u751F\u6548\uFF0C\n \u5BF9\u300C\u6253\u5206\u4E0D\u8FBE\u6807\u300D\u4E0D\u751F\u6548 \u2014\u2014 \u540E\u8005\u5C31\u8BE5\u4E0D\u5E26\u53C2\u8003\u56FE\u3002\n7. \u300C\u65E7\u7248\u300D\u6A21\u5F0F\u4E0B\u53C2\u8003\u56FE\u8F83\u591A\u65F6\uFF08\u8D85\u8FC7 12 \u5F20\uFF09\u81EA\u52A8\u8D70\u4E24\u7EA7\u68C0\u7D22\uFF1A\u5148\u8BA9\u6A21\u578B\u4EA7\u51FA\u68C0\u7D22\u5173\u952E\u8BCD\u3001\u672C\u5730\u5339\u914D\u53EC\u56DE\uFF0C\n \u518D\u5BF9\u53EC\u56DE\u7ED3\u679C\u7CBE\u6392\uFF1B\u8BC6\u56FE\u6A21\u5F0F\u4E0B\u4E5F\u53EA\u53D1\u9001\u53EC\u56DE\u7684\u8FD9\u51E0\u5F20\u56FE\u7247\uFF0C\u907F\u514D\u6BCF\u6B21\u90FD\u628A\u6574\u4E2A\u56FE\u5E93\u53D1\u7ED9\u6A21\u578B\u3002\n8. \u63CF\u8FF0\u53EF\u4EE5\u7528\u300C\u751F\u6210\u63CF\u8FF0\u300D\u6307\u4EE4\u8BA9\u6A21\u578B\u770B\u56FE\u81EA\u52A8\u751F\u6210\u5E76\u5199\u56DE\u914D\u7F6E\uFF08\u9700\u8981\u652F\u6301\u56FE\u7247\u8F93\u5165\u7684\u6A21\u578B\uFF09\u3002\n \u82E5\u9009\u56FE\u6A21\u578B\u652F\u6301\u8BC6\u522B\u56FE\u7247\uFF08\u591A\u6A21\u6001\uFF09\uFF0C\u53EF\u52FE\u9009\u300C\u9009\u56FE\u6A21\u578B\u652F\u6301\u8BC6\u522B\u56FE\u7247\u300D\uFF0C\u63D2\u4EF6\u4F1A\u628A\u5019\u9009\u56FE\u7247\u672C\u8EAB\u53D1\u7ED9\u6A21\u578B\uFF0C\n \u6A21\u578B\u5BF9\u7740\u771F\u5B9E\u56FE\u7247\u6311\u9009\uFF1B\u5B83\u7ED9\u51FA\u7684\u5173\u952E\u89C6\u89C9\u7279\u5F81\u8FD8\u4F1A\u5E76\u5165\u7ED8\u56FE\u63D0\u793A\u8BCD\uFF0C\u8BA9\u51FA\u56FE\u66F4\u8FD8\u539F\u53C2\u8003\u56FE\u3002\n9. \u751F\u6210\u7ED3\u679C\u53EF\u81EA\u52A8\u5165\u5E93\uFF08\u9ED8\u8BA4\u5173\u95ED\uFF09\uFF0C\u4E0B\u6B21\u80FD\u88AB\u81EA\u5DF1\u68C0\u7D22\u5230\u5E76\u590D\u7528\uFF0C\u5F62\u6210\u95ED\u73AF\uFF1B\n \u5F00\u542F\u300C\u540E\u53F0\u7ED8\u56FE\u300D\u540E\u51FA\u56FE\u4E0D\u518D\u963B\u585E\uFF0C\u5148\u56DE\u300C\u6B63\u5728\u753B\u300D\uFF0C\u753B\u597D\u4E3B\u52A8\u63A8\u9001\u3002\n\n\u63D0\u793A\u8BCD\u6A21\u677F\u53EF\u7528\u5360\u4F4D\u7B26\uFF1A{candidates} \u5019\u9009\u56FE\u7247\u5217\u8868\u3001{userInput} \u7528\u6237\u9644\u52A0\u9700\u6C42\u3001{max} \u6700\u591A\u9009\u62E9\u6570\u91CF\u3001{command} \u6307\u4EE4\u540D\u3001{prompt} \u6307\u4EE4\u63D0\u793A\u8BCD\n\n---\n\u6B64\u9879\u76EE\u6240\u9700\u7684koishi\u670D\u52A1\uFF1A\u5FC5\u9700 'http', 'logger', 'i18n'\uFF1B\u53EF\u9009 'puppeteer'\uFF08\u4EC5\u300C\u6587\u5B57\u6E32\u67D3\u53C2\u8003\u56FE\u300D\u9700\u8981\uFF09\n\n---\n";
|
|
13
13
|
/**
|
|
14
14
|
* 解析模型返回的 JSON 选择结果(纯函数,便于单独测试)
|
|
15
15
|
* @param raw 模型的原始回复
|
|
@@ -33,6 +33,56 @@ export declare function computeRetryDelay(status: any, retryAfter: number | unde
|
|
|
33
33
|
export declare function matchCandidatesByKeywords(candidates: CandidateImage[], keywords: string[], topK: number): CandidateImage[];
|
|
34
34
|
/** 去重合并候选(按 url 判重) */
|
|
35
35
|
export declare function mergeCandidates(...lists: CandidateImage[][]): CandidateImage[];
|
|
36
|
+
/** 选图第一步的产物:先想清楚「要什么」,再去看「有什么」 */
|
|
37
|
+
export interface RequirementAnalysis {
|
|
38
|
+
/** 画面主体(一句话) */
|
|
39
|
+
subject: string;
|
|
40
|
+
/** 硬性要素:缺一个就不该选这张图 */
|
|
41
|
+
must: string[];
|
|
42
|
+
/** 加分要素:有更好,没有也能用 */
|
|
43
|
+
nice: string[];
|
|
44
|
+
/** 明确不要出现的 */
|
|
45
|
+
avoid: string[];
|
|
46
|
+
/** 画面需要出现的文字(台词/标题/招牌),交给浏览器渲染 */
|
|
47
|
+
text: string;
|
|
48
|
+
/** 用户表示「不用参考/随意画」时跳过检索 */
|
|
49
|
+
skipReference: boolean;
|
|
50
|
+
/** 判定需要用户补图时,用一句话说明要什么样的图 */
|
|
51
|
+
needTypes: string;
|
|
52
|
+
}
|
|
53
|
+
/** 单张候选图的打分结果(index 从 1 开始,对应候选列表位置) */
|
|
54
|
+
export interface ScoredCandidate {
|
|
55
|
+
index: number;
|
|
56
|
+
score: number;
|
|
57
|
+
why: string;
|
|
58
|
+
}
|
|
59
|
+
/** 从任意文本里挖出第一个 JSON 对象(容忍代码块围栏和前后废话) */
|
|
60
|
+
export declare function extractJsonObject(raw: string | null | undefined): any | null;
|
|
61
|
+
/** 把模型给的字段统一成字符串数组(支持数组 / 逗号顿号换行分隔的字符串) */
|
|
62
|
+
export declare function toStrList(value: any): string[];
|
|
63
|
+
/** 用户这句话是不是「不用参考了」 */
|
|
64
|
+
export declare function isSkipReferenceInput(userInput: string): boolean;
|
|
65
|
+
/** 解析「需求抽取」的返回 */
|
|
66
|
+
export declare function parseAnalysisResult(raw: string | null): RequirementAnalysis | null;
|
|
67
|
+
/** 把「需求要素」转成本地检索用的关键词 */
|
|
68
|
+
export declare function keywordsFromAnalysis(analysis: RequirementAnalysis | null): string[];
|
|
69
|
+
/** 把分数归一化到 0-100(兼容 0.85 这种小数写法、以及 "85分" 这种字符串) */
|
|
70
|
+
export declare function normalizeScore(value: any): number | null;
|
|
71
|
+
/** 解析「逐图打分」的返回 */
|
|
72
|
+
export declare function parseScoreResult(raw: string | null, candidates: CandidateImage[]): ScoredCandidate[];
|
|
73
|
+
/**
|
|
74
|
+
* 按分数阈值筛选:只有达到 minScore 的才留下,按分数从高到低取前 max 张。
|
|
75
|
+
* 一张都不达标时返回空数组 —— 这是「宁可不选也不乱选」的兜底。
|
|
76
|
+
*/
|
|
77
|
+
export declare function selectByScore(scored: ScoredCandidate[], candidates: CandidateImage[], minScore: number, max: number): {
|
|
78
|
+
picked: CandidateImage[];
|
|
79
|
+
best: number;
|
|
80
|
+
passed: number;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* 去掉重复图:链接相同的直接去掉;描述完全相同的(同一批入库的近似图)只留第一张。
|
|
84
|
+
*/
|
|
85
|
+
export declare function dedupeCandidates(list: CandidateImage[]): CandidateImage[];
|
|
36
86
|
/**
|
|
37
87
|
* 图库容量裁剪:超出容量时淘汰最旧的(按 time 升序),只保留每个组最近 capacity 条
|
|
38
88
|
*/
|
|
@@ -314,6 +364,18 @@ interface AISelectorConfig {
|
|
|
314
364
|
maxTokensCeiling?: number;
|
|
315
365
|
/** 诊断指令名:发一次选图请求并回显模型原始返回 */
|
|
316
366
|
debugCommand?: string;
|
|
367
|
+
/** 选图模式:score = 抽需求+逐图打分(默认);legacy = 旧的候选全量丢给模型挑 */
|
|
368
|
+
selectionMode?: 'score' | 'legacy';
|
|
369
|
+
/** 打分制的最低分数线(0-100),低于它的图一律不选 */
|
|
370
|
+
minScore?: number;
|
|
371
|
+
/** 打分制第一步「需求分析」的提示词模板 */
|
|
372
|
+
analyzePrompt?: string;
|
|
373
|
+
/** 打分制第二步「逐图打分」的提示词模板 */
|
|
374
|
+
scorePrompt?: string;
|
|
375
|
+
/** 是否合并描述完全相同的重复参考图(默认开) */
|
|
376
|
+
dedupe?: boolean;
|
|
377
|
+
/** 用户说「不用参考/随意画」时是否跳过选图(默认开) */
|
|
378
|
+
respectSkipReference?: boolean;
|
|
317
379
|
}
|
|
318
380
|
/** 交给 AI 挑选的候选图片 */
|
|
319
381
|
interface CandidateImage {
|
package/lib/index.js
CHANGED
|
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
));
|
|
27
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
28
|
|
|
29
|
-
// src/index.ts
|
|
29
|
+
// plugins/koishi-plugin-image-prompt/src/index.ts
|
|
30
30
|
var src_exports = {};
|
|
31
31
|
__export(src_exports, {
|
|
32
32
|
Config: () => Config,
|
|
@@ -37,8 +37,10 @@ __export(src_exports, {
|
|
|
37
37
|
buildSelectorContent: () => buildSelectorContent,
|
|
38
38
|
buildTextHtml: () => buildTextHtml,
|
|
39
39
|
computeRetryDelay: () => computeRetryDelay,
|
|
40
|
+
dedupeCandidates: () => dedupeCandidates,
|
|
40
41
|
describeSelectorError: () => describeSelectorError,
|
|
41
42
|
escapeHtml: () => escapeHtml,
|
|
43
|
+
extractJsonObject: () => extractJsonObject,
|
|
42
44
|
extractResponseText: () => extractResponseText,
|
|
43
45
|
extractServerMessage: () => extractServerMessage,
|
|
44
46
|
extractTextToRender: () => extractTextToRender,
|
|
@@ -46,19 +48,26 @@ __export(src_exports, {
|
|
|
46
48
|
inject: () => inject,
|
|
47
49
|
isPassiveReplyError: () => isPassiveReplyError,
|
|
48
50
|
isRetryableStatus: () => isRetryableStatus,
|
|
51
|
+
isSkipReferenceInput: () => isSkipReferenceInput,
|
|
52
|
+
keywordsFromAnalysis: () => keywordsFromAnalysis,
|
|
49
53
|
matchCandidatesByKeywords: () => matchCandidatesByKeywords,
|
|
50
54
|
mergeCandidates: () => mergeCandidates,
|
|
51
55
|
mergePrompt: () => mergePrompt,
|
|
52
56
|
name: () => name,
|
|
57
|
+
normalizeScore: () => normalizeScore,
|
|
58
|
+
parseAnalysisResult: () => parseAnalysisResult,
|
|
53
59
|
parseRetryAfterHeader: () => parseRetryAfterHeader,
|
|
60
|
+
parseScoreResult: () => parseScoreResult,
|
|
54
61
|
parseSelectionResult: () => parseSelectionResult,
|
|
55
62
|
previewJson: () => previewJson,
|
|
56
63
|
readImageSize: () => readImageSize,
|
|
57
64
|
resolveTokenParam: () => resolveTokenParam,
|
|
58
65
|
sanitizeCaption: () => sanitizeCaption,
|
|
66
|
+
selectByScore: () => selectByScore,
|
|
59
67
|
stripCommandName: () => stripCommandName,
|
|
60
68
|
stripThinkTags: () => stripThinkTags,
|
|
61
69
|
supportsMarkdown: () => supportsMarkdown,
|
|
70
|
+
toStrList: () => toStrList,
|
|
62
71
|
trimGallery: () => trimGallery,
|
|
63
72
|
truncateText: () => truncateText,
|
|
64
73
|
usage: () => usage,
|
|
@@ -87,18 +96,25 @@ var usage = `
|
|
|
87
96
|
\u3010AI \u9009\u62E9\u53C2\u8003\u56FE\u7247\u3011
|
|
88
97
|
|
|
89
98
|
1. \u5728\u300C\u53C2\u8003\u56FE\u7247\u7EC4\u300D\u4E2D\u6CE8\u518C\u5206\u7EC4\uFF1A\u6BCF\u7EC4\u586B\u5199\u82E5\u5E72\u5F20\u300C\u56FE\u7247\u94FE\u63A5 + \u63CF\u8FF0\u300D\uFF08\u63CF\u8FF0\u7528\u4E8E\u8BA9 AI \u5224\u65AD\u8BE5\u56FE\u7684\u7528\u9014\uFF09\u3002
|
|
99
|
+
**\u63CF\u8FF0\u4E00\u5B9A\u8981\u5199\u5177\u4F53**\uFF08\u53D1\u8272\u53D1\u578B\u3001\u670D\u88C5\u3001\u52A8\u4F5C\u3001\u753B\u98CE\uFF09\u2014\u2014 \u6253\u5206\u5236\u4E0B\u6CA1\u63CF\u8FF0\u7684\u56FE\u6C38\u8FDC\u9009\u4E0D\u4E0A\u3002
|
|
90
100
|
2. \u5728\u6307\u4EE4\u914D\u7F6E\u7684\u300C\u5F15\u7528\u7684\u53C2\u8003\u56FE\u7247\u7EC4\u540D\u79F0\u300D\u4E2D\u586B\u5165\u7EC4\u540D\uFF08\u53EF\u586B\u591A\u4E2A\uFF09\uFF0C\u8BE5\u6307\u4EE4\u6267\u884C\u65F6\u4F1A\u628A\u7EC4\u5185\u56FE\u7247\u5168\u90E8\u4EA4\u7ED9 AI \u6311\u9009\u3002
|
|
91
|
-
3. \u300CAI \u9009\u56FE\u8BBE\u7F6E\u300D\u53EF\u4FEE\u6539\u5BF9\u8BDD\u6A21\u578B\uFF08\u9ED8\u8BA4 Qwen/Qwen2.5-7B-Instruct\uFF09\u3001\u9009\u62E9\u63D0\u793A\u8BCD\u6A21\u677F\u3001\u8D85\u65F6\u4E0E\u91CD\u8BD5\u7B49\uFF1B
|
|
101
|
+
3. \u300CAI \u9009\u56FE\u8BBE\u7F6E\u300D\u53EF\u4FEE\u6539\u5BF9\u8BDD\u6A21\u578B\uFF08\u9ED8\u8BA4 Qwen/Qwen2.5-7B-Instruct\uFF09\u3001\u9009\u62E9\u6A21\u5F0F\u3001\u63D0\u793A\u8BCD\u6A21\u677F\u3001\u8D85\u65F6\u4E0E\u91CD\u8BD5\u7B49\uFF1B
|
|
92
102
|
\u63A5\u53E3\u5730\u5740/\u5BC6\u94A5\u7559\u7A7A\u65F6\u590D\u7528\u7ED8\u56FE\u63A5\u53E3\u7684\u914D\u7F6E\u3002
|
|
93
|
-
4. \
|
|
103
|
+
4. \u300C\u9009\u56FE\u6A21\u5F0F\u300D\u9ED8\u8BA4\u662F**\u6253\u5206\u5236**\uFF1A\u5148\u53EA\u505A\u9700\u6C42\u5206\u6790\uFF08**\u4E0D\u7ED9\u6A21\u578B\u5019\u9009\u56FE**\uFF0C\u5B83\u6CA1\u6709\u300C\u53EF\u6311\u7684\u5BF9\u8C61\u300D\uFF09\uFF0C
|
|
104
|
+
\u518D\u7528\u5173\u952E\u8BCD\u5728\u672C\u5730\u53EC\u56DE\uFF0C\u7136\u540E\u8981\u6C42\u6A21\u578B\u7ED9\u6BCF\u5F20\u5019\u9009\u56FE\u6253 0-100 \u5206\uFF0C\u4F4E\u4E8E\u300C\u6700\u4F4E\u5206\u6570\u7EBF\u300D\u7684\u4E00\u5F8B\u4E0D\u8981\u3002
|
|
105
|
+
\u4E00\u5F20\u90FD\u4E0D\u8FBE\u6807\u5C31\u5982\u5B9E\u544A\u77E5\u7528\u6237\u300C\u56FE\u5E93\u91CC\u6CA1\u6709\u5408\u9002\u7684\u53C2\u8003\u56FE\u300D\uFF0C**\u4E0D\u4F1A\u786C\u51D1**\uFF1B
|
|
106
|
+
\u82E5\u5F00\u542F\u300C\u7F3A\u5C11\u5408\u9002\u53C2\u8003\u56FE\u65F6\u8BE2\u95EE\u7528\u6237\u8865\u5145\u53D1\u9001\u300D\uFF0C\u4F1A\u8BF7\u7528\u6237\u8865\u53D1\u4E00\u5F20\u53C2\u8003\u56FE\uFF08\u7528\u6237\u53D1\u7684\u56FE\u4F1A\u88AB\u76F4\u63A5\u4F7F\u7528\uFF09\u3002
|
|
107
|
+
\u60F3\u56DE\u5230\u8001\u884C\u4E3A\u5C31\u628A\u300C\u9009\u56FE\u6A21\u5F0F\u300D\u6539\u6210\u300C\u65E7\u7248\u300D\u3002
|
|
108
|
+
5. \u5F53\u7528\u6237\u660E\u786E\u8BF4\u300C\u4E0D\u7528\u53C2\u8003 / \u968F\u610F\u753B / \u81EA\u7531\u53D1\u6325\u300D\u65F6\uFF0C\u76F4\u63A5\u8DF3\u8FC7\u9009\u56FE\uFF0C\u4E00\u6B21\u9009\u56FE\u8BF7\u6C42\u90FD\u4E0D\u53D1\u3002
|
|
109
|
+
6. \u300C\u542F\u7528 AI \u667A\u80FD\u9009\u62E9\u53C2\u8003\u56FE\u7247\u300D\u9ED8\u8BA4\u5173\u95ED\uFF0C\u9700\u624B\u52A8\u5F00\u542F\uFF1B\u300CAI \u9009\u56FE\u5931\u8D25\u65F6\u56DE\u9000\u4E3A\u4F7F\u7528\u5019\u9009\u6C60\u5185\u5168\u90E8\u56FE\u7247\u300D\u9ED8\u8BA4\u5173\u95ED\uFF0C
|
|
110
|
+
\u5931\u8D25\u65F6\u672C\u6B21\u4E0D\u4F7F\u7528\u53C2\u8003\u56FE\u7247\uFF08\u5F00\u542F\u5219\u6539\u7528\u5019\u9009\u6C60\u5185\u5168\u90E8\u56FE\u7247\uFF09\u3002\u6CE8\u610F\u300C\u56DE\u9000\u300D\u53EA\u5BF9**\u8BF7\u6C42\u5931\u8D25**\u751F\u6548\uFF0C
|
|
111
|
+
\u5BF9\u300C\u6253\u5206\u4E0D\u8FBE\u6807\u300D\u4E0D\u751F\u6548 \u2014\u2014 \u540E\u8005\u5C31\u8BE5\u4E0D\u5E26\u53C2\u8003\u56FE\u3002
|
|
112
|
+
7. \u300C\u65E7\u7248\u300D\u6A21\u5F0F\u4E0B\u53C2\u8003\u56FE\u8F83\u591A\u65F6\uFF08\u8D85\u8FC7 12 \u5F20\uFF09\u81EA\u52A8\u8D70\u4E24\u7EA7\u68C0\u7D22\uFF1A\u5148\u8BA9\u6A21\u578B\u4EA7\u51FA\u68C0\u7D22\u5173\u952E\u8BCD\u3001\u672C\u5730\u5339\u914D\u53EC\u56DE\uFF0C
|
|
113
|
+
\u518D\u5BF9\u53EC\u56DE\u7ED3\u679C\u7CBE\u6392\uFF1B\u8BC6\u56FE\u6A21\u5F0F\u4E0B\u4E5F\u53EA\u53D1\u9001\u53EC\u56DE\u7684\u8FD9\u51E0\u5F20\u56FE\u7247\uFF0C\u907F\u514D\u6BCF\u6B21\u90FD\u628A\u6574\u4E2A\u56FE\u5E93\u53D1\u7ED9\u6A21\u578B\u3002
|
|
114
|
+
8. \u63CF\u8FF0\u53EF\u4EE5\u7528\u300C\u751F\u6210\u63CF\u8FF0\u300D\u6307\u4EE4\u8BA9\u6A21\u578B\u770B\u56FE\u81EA\u52A8\u751F\u6210\u5E76\u5199\u56DE\u914D\u7F6E\uFF08\u9700\u8981\u652F\u6301\u56FE\u7247\u8F93\u5165\u7684\u6A21\u578B\uFF09\u3002
|
|
94
115
|
\u82E5\u9009\u56FE\u6A21\u578B\u652F\u6301\u8BC6\u522B\u56FE\u7247\uFF08\u591A\u6A21\u6001\uFF09\uFF0C\u53EF\u52FE\u9009\u300C\u9009\u56FE\u6A21\u578B\u652F\u6301\u8BC6\u522B\u56FE\u7247\u300D\uFF0C\u63D2\u4EF6\u4F1A\u628A\u5019\u9009\u56FE\u7247\u672C\u8EAB\u53D1\u7ED9\u6A21\u578B\uFF0C
|
|
95
116
|
\u6A21\u578B\u5BF9\u7740\u771F\u5B9E\u56FE\u7247\u6311\u9009\uFF1B\u5B83\u7ED9\u51FA\u7684\u5173\u952E\u89C6\u89C9\u7279\u5F81\u8FD8\u4F1A\u5E76\u5165\u7ED8\u56FE\u63D0\u793A\u8BCD\uFF0C\u8BA9\u51FA\u56FE\u66F4\u8FD8\u539F\u53C2\u8003\u56FE\u3002
|
|
96
|
-
|
|
97
|
-
\u5931\u8D25\u65F6\u672C\u6B21\u4E0D\u4F7F\u7528\u53C2\u8003\u56FE\u7247\uFF08\u5F00\u542F\u5219\u6539\u7528\u5019\u9009\u6C60\u5185\u5168\u90E8\u56FE\u7247\uFF09\u3002
|
|
98
|
-
6. \u53C2\u8003\u56FE\u8F83\u591A\u65F6\uFF08\u8D85\u8FC7 12 \u5F20\uFF09\u81EA\u52A8\u8D70\u4E24\u7EA7\u68C0\u7D22\uFF1A\u5148\u8BA9\u6A21\u578B\u4EA7\u51FA\u68C0\u7D22\u5173\u952E\u8BCD\u3001\u672C\u5730\u5339\u914D\u53EC\u56DE\uFF0C\u518D\u5BF9\u53EC\u56DE\u7ED3\u679C\u7CBE\u6392\uFF1B
|
|
99
|
-
\u8BC6\u56FE\u6A21\u5F0F\u4E0B\u4E5F\u53EA\u53D1\u9001\u53EC\u56DE\u7684\u8FD9\u51E0\u5F20\u56FE\u7247\uFF0C\u907F\u514D\u6BCF\u6B21\u90FD\u628A\u6574\u4E2A\u56FE\u5E93\u53D1\u7ED9\u6A21\u578B\u3002
|
|
100
|
-
7. \u63CF\u8FF0\u53EF\u4EE5\u7528\u300C\u751F\u6210\u63CF\u8FF0\u300D\u6307\u4EE4\u8BA9\u6A21\u578B\u770B\u56FE\u81EA\u52A8\u751F\u6210\u5E76\u5199\u56DE\u914D\u7F6E\uFF08\u9700\u8981\u652F\u6301\u56FE\u7247\u8F93\u5165\u7684\u6A21\u578B\uFF09\u3002
|
|
101
|
-
8. \u751F\u6210\u7ED3\u679C\u53EF\u81EA\u52A8\u5165\u5E93\uFF08\u9ED8\u8BA4\u5173\u95ED\uFF09\uFF0C\u4E0B\u6B21\u80FD\u88AB\u81EA\u5DF1\u68C0\u7D22\u5230\u5E76\u590D\u7528\uFF0C\u5F62\u6210\u95ED\u73AF\uFF1B
|
|
117
|
+
9. \u751F\u6210\u7ED3\u679C\u53EF\u81EA\u52A8\u5165\u5E93\uFF08\u9ED8\u8BA4\u5173\u95ED\uFF09\uFF0C\u4E0B\u6B21\u80FD\u88AB\u81EA\u5DF1\u68C0\u7D22\u5230\u5E76\u590D\u7528\uFF0C\u5F62\u6210\u95ED\u73AF\uFF1B
|
|
102
118
|
\u5F00\u542F\u300C\u540E\u53F0\u7ED8\u56FE\u300D\u540E\u51FA\u56FE\u4E0D\u518D\u963B\u585E\uFF0C\u5148\u56DE\u300C\u6B63\u5728\u753B\u300D\uFF0C\u753B\u597D\u4E3B\u52A8\u63A8\u9001\u3002
|
|
103
119
|
|
|
104
120
|
\u63D0\u793A\u8BCD\u6A21\u677F\u53EF\u7528\u5360\u4F4D\u7B26\uFF1A{candidates} \u5019\u9009\u56FE\u7247\u5217\u8868\u3001{userInput} \u7528\u6237\u9644\u52A0\u9700\u6C42\u3001{max} \u6700\u591A\u9009\u62E9\u6570\u91CF\u3001{command} \u6307\u4EE4\u540D\u3001{prompt} \u6307\u4EE4\u63D0\u793A\u8BCD
|
|
@@ -212,6 +228,132 @@ function mergeCandidates(...lists) {
|
|
|
212
228
|
}
|
|
213
229
|
return result;
|
|
214
230
|
}
|
|
231
|
+
var SKIP_REFERENCE_RE = new RegExp([
|
|
232
|
+
"(\u4E0D\u7528|\u4E0D\u9700\u8981|\u65E0\u9700|\u4E0D\u8981|\u522B)(\u53C2\u8003|\u57AB\u56FE|\u770B\u56FE|\u627E\u56FE|\u641C\u56FE|\u8C03\u56FE\u5E93)",
|
|
233
|
+
"(\u53C2\u8003\u56FE|\u57AB\u56FE|\u56FE\u5E93)(\u4E0D\u7528|\u4E0D\u9700\u8981|\u5C31\u522B|\u53BB\u6389)",
|
|
234
|
+
"(\u968F\u610F|\u968F\u4FBF|\u81EA\u7531|\u4EFB\u610F)\u53D1\u6325",
|
|
235
|
+
"\u968F\u610F\u753B|\u968F\u4FBF\u753B|\u4F60\u770B\u7740\u753B|\u770B\u7740\u529E|\u4F60\u51B3\u5B9A"
|
|
236
|
+
].join("|"));
|
|
237
|
+
function extractJsonObject(raw) {
|
|
238
|
+
if (!raw) return null;
|
|
239
|
+
let text = String(raw).trim();
|
|
240
|
+
const fence = text.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
241
|
+
if (fence) text = fence[1].trim();
|
|
242
|
+
const start = text.indexOf("{");
|
|
243
|
+
const end = text.lastIndexOf("}");
|
|
244
|
+
if (start === -1 || end <= start) return null;
|
|
245
|
+
try {
|
|
246
|
+
const value = JSON.parse(text.slice(start, end + 1));
|
|
247
|
+
return value && typeof value === "object" ? value : null;
|
|
248
|
+
} catch {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function toStrList(value) {
|
|
253
|
+
if (Array.isArray(value)) return value.map((v) => String(v ?? "").trim()).filter(Boolean);
|
|
254
|
+
if (typeof value === "string" && value.trim()) {
|
|
255
|
+
return value.split(/[,,、;;\n]+/).map((s) => s.trim()).filter(Boolean);
|
|
256
|
+
}
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
259
|
+
function isSkipReferenceInput(userInput) {
|
|
260
|
+
const text = String(userInput || "").trim();
|
|
261
|
+
if (!text) return false;
|
|
262
|
+
return SKIP_REFERENCE_RE.test(text);
|
|
263
|
+
}
|
|
264
|
+
function parseAnalysisResult(raw) {
|
|
265
|
+
const data = extractJsonObject(raw);
|
|
266
|
+
if (!data) return null;
|
|
267
|
+
const text = data.text ?? data.texts ?? data.lines ?? data.renderText;
|
|
268
|
+
return {
|
|
269
|
+
subject: String(data.subject ?? data.\u4E3B\u4F53 ?? "").trim(),
|
|
270
|
+
must: toStrList(data.must ?? data.mustHave ?? data.required ?? data.\u786C\u6027\u8981\u7D20),
|
|
271
|
+
nice: toStrList(data.nice ?? data.niceToHave ?? data.optional ?? data.\u52A0\u5206\u8981\u7D20),
|
|
272
|
+
avoid: toStrList(data.avoid ?? data.exclude ?? data.negative ?? data.\u4E0D\u8981\u51FA\u73B0),
|
|
273
|
+
text: Array.isArray(text) ? toStrList(text).join("\n") : String(text ?? "").trim(),
|
|
274
|
+
skipReference: data.skipReference === true || data.skip_reference === true,
|
|
275
|
+
needTypes: String(data.needTypes ?? data.need_types ?? data.\u9700\u8981\u7684\u56FE ?? "").trim()
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function keywordsFromAnalysis(analysis) {
|
|
279
|
+
if (!analysis) return [];
|
|
280
|
+
const words = [];
|
|
281
|
+
const push = (value) => {
|
|
282
|
+
const item = String(value || "").trim();
|
|
283
|
+
if (item && !words.includes(item)) words.push(item);
|
|
284
|
+
};
|
|
285
|
+
if (analysis.subject) push(analysis.subject);
|
|
286
|
+
analysis.must.forEach(push);
|
|
287
|
+
analysis.nice.forEach(push);
|
|
288
|
+
return words;
|
|
289
|
+
}
|
|
290
|
+
function normalizeScore(value) {
|
|
291
|
+
if (typeof value === "number" && isFinite(value)) {
|
|
292
|
+
const num = value > 0 && value <= 1 ? Math.round(value * 100) : Math.round(value);
|
|
293
|
+
return Math.max(0, Math.min(100, num));
|
|
294
|
+
}
|
|
295
|
+
if (typeof value === "string") {
|
|
296
|
+
const matched = value.match(/-?\d+(?:\.\d+)?/);
|
|
297
|
+
if (!matched) return null;
|
|
298
|
+
return normalizeScore(parseFloat(matched[0]));
|
|
299
|
+
}
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
function parseScoreResult(raw, candidates) {
|
|
303
|
+
const data = extractJsonObject(raw);
|
|
304
|
+
if (!data) return [];
|
|
305
|
+
const list = data.scores ?? data.score ?? data.items ?? data.results ?? data.\u8BC4\u5206;
|
|
306
|
+
if (!Array.isArray(list)) return [];
|
|
307
|
+
const out = [];
|
|
308
|
+
for (const entry of list) {
|
|
309
|
+
if (!entry || typeof entry !== "object") continue;
|
|
310
|
+
const rawIndex = entry.index ?? entry.id ?? entry.no ?? entry.n ?? entry.\u7F16\u53F7;
|
|
311
|
+
const index = rawIndex === void 0 ? null : parseInt(String(rawIndex).replace(/[^0-9-]/g, ""), 10);
|
|
312
|
+
const score = normalizeScore(entry.score ?? entry.points ?? entry.\u5206\u6570 ?? entry.value);
|
|
313
|
+
if (index === null || isNaN(index) || score === null) continue;
|
|
314
|
+
const candidate = candidates[index - 1] || candidates[index];
|
|
315
|
+
if (!candidate) continue;
|
|
316
|
+
out.push({ index: candidates.indexOf(candidate) + 1, score, why: String(entry.why ?? entry.reason ?? entry.\u8BF4\u660E ?? "").trim() });
|
|
317
|
+
}
|
|
318
|
+
return out;
|
|
319
|
+
}
|
|
320
|
+
function selectByScore(scored, candidates, minScore, max) {
|
|
321
|
+
const threshold = minScore > 0 ? minScore : 0;
|
|
322
|
+
const best = /* @__PURE__ */ new Map();
|
|
323
|
+
for (const item of scored || []) {
|
|
324
|
+
const prev = best.get(item.index);
|
|
325
|
+
if (!prev || item.score > prev.score) best.set(item.index, item);
|
|
326
|
+
}
|
|
327
|
+
const eligible = [...best.values()].filter((item) => item.score >= threshold).sort((a, b) => b.score - a.score);
|
|
328
|
+
const limit = max > 0 ? max : 1;
|
|
329
|
+
const picked = [];
|
|
330
|
+
for (const item of eligible) {
|
|
331
|
+
if (picked.length >= limit) break;
|
|
332
|
+
const candidate = candidates[item.index - 1];
|
|
333
|
+
if (candidate && !picked.includes(candidate)) picked.push(candidate);
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
picked,
|
|
337
|
+
best: (scored || []).reduce((acc, item) => Math.max(acc, item.score), 0),
|
|
338
|
+
passed: eligible.length
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function dedupeCandidates(list) {
|
|
342
|
+
const out = [];
|
|
343
|
+
const seenUrl = /* @__PURE__ */ new Set();
|
|
344
|
+
const seenDesc = /* @__PURE__ */ new Set();
|
|
345
|
+
for (const item of list || []) {
|
|
346
|
+
if (!item || !item.url || seenUrl.has(item.url)) continue;
|
|
347
|
+
const desc = normalizeText(item.description || "");
|
|
348
|
+
if (desc.length >= 6) {
|
|
349
|
+
if (seenDesc.has(desc)) continue;
|
|
350
|
+
seenDesc.add(desc);
|
|
351
|
+
}
|
|
352
|
+
seenUrl.add(item.url);
|
|
353
|
+
out.push(item);
|
|
354
|
+
}
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
215
357
|
function trimGallery(records, capacity) {
|
|
216
358
|
const limit = capacity > 0 ? capacity : 50;
|
|
217
359
|
const byGroup = /* @__PURE__ */ new Map();
|
|
@@ -694,6 +836,56 @@ var DEFAULT_KEYWORD_PROMPT = `\u4F60\u662F\u4E00\u4E2A\u53C2\u8003\u56FE\u7247\u
|
|
|
694
836
|
|
|
695
837
|
\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981\u8F93\u51FA\u89E3\u91CA\u6216\u4EE3\u7801\u5757\uFF1A
|
|
696
838
|
{"keywords":["\u5173\u952E\u8BCD1","\u5173\u952E\u8BCD2"],"candidates":[1,3]}`;
|
|
839
|
+
var DEFAULT_ANALYZE_PROMPT = `\u4F60\u662F\u7ED8\u56FE\u53C2\u8003\u56FE\u7684\u300C\u9700\u6C42\u5206\u6790\u52A9\u624B\u300D\u3002**\u8FD9\u4E00\u6B65\u53EA\u505A\u5206\u6790\uFF0C\u4E0D\u8981\u6311\u9009\u4EFB\u4F55\u56FE\u7247\u3002**
|
|
840
|
+
|
|
841
|
+
\u7ED8\u56FE\u6307\u4EE4\uFF1A{command}
|
|
842
|
+
\u8BE5\u6307\u4EE4\u7684\u7528\u9014\u63D0\u793A\u8BCD\uFF1A{prompt}
|
|
843
|
+
\u7528\u6237\u672C\u6B21\u7684\u9700\u6C42\uFF1A{userInput}
|
|
844
|
+
|
|
845
|
+
\u8BF7\u5148\u628A\u300C\u8FD9\u6B21\u753B\u9762\u4E0A\u5FC5\u987B\u6709 / \u6700\u597D\u6709\u7684\u89C6\u89C9\u8981\u7D20\u300D\u60F3\u6E05\u695A\uFF0C\u518D\u8F93\u51FA JSON\u3002
|
|
846
|
+
|
|
847
|
+
\u89C4\u5219\uFF1A
|
|
848
|
+
1. must\uFF08\u786C\u6027\u8981\u7D20\uFF09\uFF1A\u7F3A\u4E00\u4E2A\u5C31\u4E0D\u8BE5\u9009\u8FD9\u5F20\u53C2\u8003\u56FE\u3002\u53EA\u5199**\u80FD\u4ECE\u56FE\u7247\u4E0A\u770B\u51FA\u6765\u7684**\u89C6\u89C9\u7279\u5F81\uFF0C
|
|
849
|
+
\u4F8B\u5982\u89D2\u8272\u540D\u3001\u53D1\u8272\u53D1\u578B\u3001\u77B3\u8272\u3001\u670D\u88C5\u6B3E\u5F0F\u3001\u914D\u9970\u3001\u7269\u79CD\u3001\u753B\u98CE\u3002\u4E0D\u8981\u5199\u62BD\u8C61\u8BCD\uFF08\u5982\u300C\u597D\u770B\u300D\u300C\u9AD8\u7EA7\u300D\uFF09\u3002
|
|
850
|
+
\u6307\u4EE4\u7528\u9014\u63D0\u793A\u8BCD\u91CC\u672C\u6765\u5C31\u56FA\u5B9A\u7684\u98CE\u683C\uFF08\u6BD4\u5982\u300C1/7 \u624B\u529E\u300D\u300C\u900F\u660E\u4E9A\u514B\u529B\u5E95\u5EA7\u300D\uFF09\u4E0D\u8981\u5199\u8FDB must\u3002
|
|
851
|
+
2. nice\uFF08\u52A0\u5206\u8981\u7D20\uFF09\uFF1A\u6709\u66F4\u597D\u3001\u6CA1\u6709\u4E5F\u80FD\u7528\uFF0C\u4F8B\u5982\u52A8\u4F5C\u3001\u8868\u60C5\u3001\u6784\u56FE\u3001\u573A\u666F\u3001\u6C1B\u56F4\u3002
|
|
852
|
+
3. avoid\uFF1A\u660E\u786E\u4E0D\u8981\u51FA\u73B0\u7684\u4E1C\u897F\uFF08\u7528\u6237\u8BF4\u300C\u4E0D\u8981 XX\u300D\u300C\u6362\u6210 YY\u300D\u65F6\uFF0C\u628A\u88AB\u5426\u6389\u7684\u90A3\u4E2A\u5199\u8FD9\u91CC\uFF09\u3002
|
|
853
|
+
4. subject\uFF1A\u8FD9\u6B21\u753B\u9762\u7684\u4E3B\u4F53\uFF0C\u4E00\u53E5\u8BDD\uFF08\u5982\u300C\u767D\u53D1\u7684\u5C11\u5973\u300D\uFF09\u3002
|
|
854
|
+
5. text\uFF1A\u753B\u9762\u4E0A\u9700\u8981\u51FA\u73B0\u7684\u6587\u5B57\uFF08\u53F0\u8BCD/\u6807\u9898/\u62DB\u724C/\u5B57\u5E55\uFF09\uFF0C\u591A\u884C\u7528 \\n \u6362\u884C\uFF1B\u4E0D\u9700\u8981\u5C31\u7A7A\u5B57\u7B26\u4E32\u3002
|
|
855
|
+
6. skipReference\uFF1A\u7528\u6237\u660E\u786E\u8868\u793A\u300C\u4E0D\u7528\u53C2\u8003 / \u968F\u610F\u753B / \u81EA\u7531\u53D1\u6325 / \u4F60\u770B\u7740\u529E\u300D\u65F6\u4E3A true\u3002
|
|
856
|
+
7. needTypes\uFF1A\u56FE\u5E93\u91CC**\u6CA1\u6709**\u5408\u9002\u53C2\u8003\u56FE\u65F6\uFF0C\u63D2\u4EF6\u8981\u8BF7\u7528\u6237\u8865\u53D1\u4E00\u5F20\u3002\u8FD9\u91CC\u5199\u4E00\u53E5**\u76F4\u63A5\u5BF9\u7528\u6237\u8BF4**\u7684\u8BDD
|
|
857
|
+
\uFF08\u4E2D\u6587\uFF0C40 \u5B57\u4EE5\u5185\uFF0C\u8BED\u6C14\u81EA\u7136\uFF0C\u4E0D\u8981\u7528\u300C\u8BF7\u63D0\u4F9B\u56FE\u7247\u300D\u8FD9\u79CD\u5957\u8BDD\uFF09\uFF0C\u4F8B\u5982\u300C\u80FD\u53D1\u4E00\u5F20\u767D\u53D1\u6C34\u624B\u670D\u7684\u7ACB\u7ED8\u5417\uFF1F\u300D\u3002
|
|
858
|
+
\u56FE\u5E93\u91CC\u4E0D\u7F3A\u56FE\u5C31\u7559\u7A7A\u5B57\u7B26\u4E32\u3002
|
|
859
|
+
|
|
860
|
+
\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981\u89E3\u91CA\u3001\u4E0D\u8981 Markdown \u4EE3\u7801\u5757\uFF1A
|
|
861
|
+
{"subject":"","must":[],"nice":[],"avoid":[],"text":"","skipReference":false,"needTypes":""}`;
|
|
862
|
+
var DEFAULT_SCORE_PROMPT = `\u4F60\u662F\u7ED8\u56FE\u53C2\u8003\u56FE\u7684\u300C\u6253\u5206\u52A9\u624B\u300D\u3002\u4E0B\u9762\u662F\u5DF2\u7ECF\u5206\u6790\u597D\u7684\u9700\u6C42\uFF0C\u4EE5\u53CA\u82E5\u5E72\u5019\u9009\u53C2\u8003\u56FE\u3002
|
|
863
|
+
**\u4F60\u7684\u4EFB\u52A1\u662F\u7ED9\u6BCF\u4E00\u5F20\u5019\u9009\u56FE\u6253\u5206\uFF0C\u800C\u4E0D\u662F\u6311\u51FA\u300C\u6700\u50CF\u7684\u300D\u6765\u51D1\u6570\u3002**
|
|
864
|
+
|
|
865
|
+
\u672C\u6B21\u9700\u6C42\uFF1A
|
|
866
|
+
\u4E3B\u4F53\uFF1A{subject}
|
|
867
|
+
\u786C\u6027\u8981\u7D20\uFF08\u7F3A\u4E00\u4E2A\u5C31\u4E0D\u5408\u683C\uFF09\uFF1A{must}
|
|
868
|
+
\u52A0\u5206\u8981\u7D20\uFF1A{nice}
|
|
869
|
+
\u4E0D\u8981\u51FA\u73B0\uFF1A{avoid}
|
|
870
|
+
|
|
871
|
+
\u5019\u9009\u53C2\u8003\u56FE\uFF08\u7F16\u53F7 | \u6240\u5C5E\u7EC4 | \u63CF\u8FF0\uFF09\uFF1A
|
|
872
|
+
{candidates}
|
|
873
|
+
|
|
874
|
+
\u6253\u5206\u89C4\u5219\uFF1A
|
|
875
|
+
1. **\u5FC5\u987B\u7ED9\u6BCF\u4E00\u5F20\u5019\u9009\u56FE\u90FD\u6253\u4E00\u4E2A 0-100 \u7684\u5206\u6570**\uFF0C\u4E00\u5F20\u90FD\u4E0D\u80FD\u6F0F\u3002
|
|
876
|
+
2. \u6253\u5206\u53EA\u770B\u300C\u8FD9\u5F20\u56FE\u80FD\u4E0D\u80FD\u5F53\u672C\u6B21\u7ED8\u56FE\u7684\u53C2\u8003\u300D\uFF1A
|
|
877
|
+
- \u786C\u6027\u8981\u7D20\u547D\u4E2D\u5F97\u8D8A\u591A\u5206\u8D8A\u9AD8\uFF1B**\u786C\u6027\u8981\u7D20\u7F3A\u5931\u6216\u4E0E\u9700\u6C42\u77DB\u76FE \u2192 \u53EA\u80FD\u7ED9 0-30 \u5206**\u3002
|
|
878
|
+
- \u63CF\u8FF0\u4E3A\u7A7A\u3001\u770B\u4E0D\u61C2\u5185\u5BB9\u3001\u65E0\u6CD5\u5224\u65AD\u7684\u56FE \u2192 **\u4E00\u5F8B\u7ED9 0 \u5206**\uFF0C\u4E0D\u8981\u9760\u731C\u3002
|
|
879
|
+
- \u4E0E avoid \u51B2\u7A81\u7684 \u2192 0 \u5206\u3002
|
|
880
|
+
- \u547D\u4E2D\u52A0\u5206\u8981\u7D20\u3001\u6216\u7EC4\u540D/\u63CF\u8FF0\u4E0E\u9700\u6C42\u9AD8\u5EA6\u543B\u5408 \u2192 \u53EF\u4EE5\u7ED9 80-100\u3002
|
|
881
|
+
3. **\u5B81\u53EF\u6F0F\u9009\uFF0C\u4E0D\u53EF\u4E71\u9009\u3002** \u62FF\u4E0D\u51C6\u5C31\u6253\u4F4E\u5206\u3002\u7ED9\u4E0D\u76F8\u5173\u7684\u56FE\u6253\u9AD8\u5206\u662F\u6700\u4E25\u91CD\u7684\u9519\u8BEF\u3002
|
|
882
|
+
4. \u5982\u679C\u6240\u6709\u5019\u9009\u90FD\u4E0D\u5408\u9002\uFF0C\u5C31\u7167\u5B9E\u5168\u90E8\u6253\u4F4E\u5206\uFF0C**\u4E0D\u8981\u4E3A\u4E86\u51D1\u6570\u62AC\u9AD8\u5206\u6570**\u3002
|
|
883
|
+
5. why \u7528\u4E0D\u8D85\u8FC7 15 \u4E2A\u5B57\u8BF4\u660E\u7406\u7531\uFF0C\u4F8B\u5982\u300C\u547D\u4E2D\u767D\u53D1+\u6C34\u624B\u670D\u300D\u300C\u63CF\u8FF0\u4E3A\u7A7A\u65E0\u6CD5\u5224\u65AD\u300D\u3002
|
|
884
|
+
6. hint\uFF08\u53EF\u9009\uFF09\uFF1A**\u53EA\u6709\u5728\u4F60\u5B9E\u9645\u770B\u5230\u4E86\u56FE\u7247\u65F6**\u624D\u586B \u2014\u2014 \u7528\u4E00\u53E5\u8BDD\u6982\u62EC\u9009\u4E2D\u56FE\u7247\u91CC\u51B3\u5B9A\u5916\u89C2\u7684\u5173\u952E\u89C6\u89C9\u7279\u5F81
|
|
885
|
+
\uFF08\u53D1\u8272\u53D1\u578B/\u77B3\u8272/\u670D\u88C5/\u914D\u9970/\u753B\u98CE\uFF09\uFF0C\u4FBF\u4E8E\u5E76\u5165\u7ED8\u56FE\u63D0\u793A\u8BCD\uFF1B\u53EA\u7ED9\u4E86\u6587\u5B57\u63CF\u8FF0\u5C31\u7559\u7A7A\u5B57\u7B26\u4E32\u3002
|
|
886
|
+
|
|
887
|
+
\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981\u89E3\u91CA\u3001\u4E0D\u8981 Markdown \u4EE3\u7801\u5757\uFF1A
|
|
888
|
+
{"scores":[{"index":1,"score":85,"why":"\u547D\u4E2D\u767D\u53D1\u53CC\u9A6C\u5C3E"},{"index":2,"score":0,"why":"\u63CF\u8FF0\u4E3A\u7A7A"}],"hint":""}`;
|
|
697
889
|
var defaultCommands = [
|
|
698
890
|
{
|
|
699
891
|
name: "\u624B\u529E\u5316",
|
|
@@ -1195,6 +1387,13 @@ var Config = import_koishi.Schema.intersect([
|
|
|
1195
1387
|
import_koishi.Schema.object({
|
|
1196
1388
|
aiSelector: import_koishi.Schema.object({
|
|
1197
1389
|
enabled: import_koishi.Schema.boolean().default(false).description("\u542F\u7528 AI \u667A\u80FD\u9009\u62E9\u53C2\u8003\u56FE\u7247\uFF08\u9ED8\u8BA4\u5173\u95ED\uFF0C\u9700\u8981\u65F6\u624B\u52A8\u5F00\u542F\uFF09"),
|
|
1390
|
+
selectionMode: import_koishi.Schema.union([
|
|
1391
|
+
import_koishi.Schema.const("score").description("\u6253\u5206\u5236\uFF08\u63A8\u8350\uFF09\uFF1A\u5148\u5206\u6790\u9700\u6C42 \u2192 \u5173\u952E\u8BCD\u53EC\u56DE \u2192 \u9010\u56FE\u6253\u5206 \u2192 \u5206\u6570\u4E0D\u591F\u5C31\u5982\u5B9E\u8BF4\u300C\u6CA1\u6709\u5408\u9002\u7684\u56FE\u300D"),
|
|
1392
|
+
import_koishi.Schema.const("legacy").description("\u65E7\u7248\uFF1A\u628A\u5019\u9009\u56FE\u5168\u90E8\u4E22\u7ED9\u6A21\u578B\u4E00\u6B21\u6311\u5B8C\uFF08\u5BB9\u6613\u786C\u51D1\u6570\uFF0C\u4EC5\u5728\u9700\u8981\u517C\u5BB9\u65F6\u4F7F\u7528\uFF09")
|
|
1393
|
+
]).default("score").description("\u9009\u56FE\u6A21\u5F0F\u3002\u6253\u5206\u5236\u4F1A\u7ED9\u6A21\u578B\u7559\u9000\u8DEF\uFF0C\u4E0D\u4F1A\u5728\u6CA1\u6709\u5408\u9002\u56FE\u65F6\u786C\u6311\u4E00\u5F20"),
|
|
1394
|
+
minScore: import_koishi.Schema.number().default(60).min(0).max(100).step(5).description("\u6253\u5206\u5236\u7684\u6700\u4F4E\u5206\u6570\u7EBF\uFF080-100\uFF09\u3002\u4F4E\u4E8E\u8BE5\u5206\u6570\u7684\u53C2\u8003\u56FE\u4E00\u5F8B\u4E0D\u9009\uFF1B\u5168\u90E8\u4E0D\u8FBE\u6807\u5C31\u5224\u5B9A\u300C\u56FE\u5E93\u6CA1\u6709\u5408\u9002\u7684\u56FE\u300D\u5E76\u8BE2\u95EE\u7528\u6237\u8865\u56FE"),
|
|
1395
|
+
dedupe: import_koishi.Schema.boolean().default(true).description("\u5408\u5E76\u91CD\u590D\u53C2\u8003\u56FE\uFF08\u94FE\u63A5\u76F8\u540C\uFF0C\u6216\u63CF\u8FF0\u5B8C\u5168\u76F8\u540C\u7684\u8FD1\u4F3C\u56FE\u53EA\u4FDD\u7559\u4E00\u5F20\uFF09"),
|
|
1396
|
+
respectSkipReference: import_koishi.Schema.boolean().default(true).description("\u7528\u6237\u8BF4\u300C\u4E0D\u7528\u53C2\u8003 / \u968F\u610F\u753B / \u81EA\u7531\u53D1\u6325\u300D\u65F6\u8DF3\u8FC7\u9009\u56FE\uFF0C\u4E00\u6B21\u9009\u56FE\u8BF7\u6C42\u90FD\u4E0D\u53D1\uFF08\u9700\u6C42\u5206\u6790\u4E5F\u7701\u6389\uFF09"),
|
|
1198
1397
|
baseUrl: import_koishi.Schema.string().role("link").description("AI \u9009\u56FE\u63A5\u53E3\u5730\u5740\uFF08OpenAI \u517C\u5BB9 Chat Completions\uFF0C\u7559\u7A7A\u5219\u590D\u7528\u7ED8\u56FE\u63A5\u53E3\u5730\u5740\uFF09"),
|
|
1199
1398
|
apiKey: import_koishi.Schema.string().role("secret").description("AI \u9009\u56FE\u63A5\u53E3\u5BC6\u94A5\uFF08\u7559\u7A7A\u5219\u590D\u7528\u7ED8\u56FE API \u5BC6\u94A5\uFF09"),
|
|
1200
1399
|
model: import_koishi.Schema.string().default("Qwen/Qwen2.5-7B-Instruct").description("\u7528\u4E8E\u9009\u62E9\u53C2\u8003\u56FE\u7247\u7684\u5BF9\u8BDD\u6A21\u578B"),
|
|
@@ -1215,10 +1414,12 @@ var Config = import_koishi.Schema.intersect([
|
|
|
1215
1414
|
visionMaxImages: import_koishi.Schema.number().default(6).min(1).max(20).step(1).description("\u5F00\u542F\u8BC6\u522B\u56FE\u7247\u65F6\uFF0C\u6700\u591A\u9644\u5E26\u591A\u5C11\u5F20\u5019\u9009\u56FE\u7247\uFF08\u8D85\u51FA\u90E8\u5206\u53EA\u53D1\u6587\u5B57\u63CF\u8FF0\uFF0C\u907F\u514D\u8BF7\u6C42\u8FC7\u5927\uFF09"),
|
|
1216
1415
|
visionFallback: import_koishi.Schema.boolean().default(true).description("\u5E26\u56FE\u7247\u8BF7\u6C42\u5931\u8D25\u65F6\uFF0C\u81EA\u52A8\u9000\u56DE\u7EAF\u6587\u5B57\u518D\u8BD5\u4E00\u6B21"),
|
|
1217
1416
|
appendHint: import_koishi.Schema.boolean().default(true).description("\u628A\u6A21\u578B\u770B\u56FE\u540E\u7ED9\u51FA\u7684\u5173\u952E\u89C6\u89C9\u7279\u5F81\u5E76\u5165\u7ED8\u56FE\u63D0\u793A\u8BCD\uFF08\u4EC5\u5728\u5F00\u542F\u8BC6\u522B\u56FE\u7247\u65F6\u751F\u6548\uFF0C\u8BA9\u51FA\u56FE\u66F4\u8FD8\u539F\u53C2\u8003\u56FE\uFF09"),
|
|
1218
|
-
twoStage: import_koishi.Schema.boolean().default(true).description("\u4E24\u7EA7\u68C0\u7D22\u9009\u56FE\uFF1A\u5148\u8BA9\u6A21\u578B\u4EA7\u51FA\u68C0\u7D22\u5173\u952E\u8BCD\u5E76\u5728\u672C\u5730\u53EC\u56DE\uFF0C\u518D\u5BF9\u53EC\u56DE\u7ED3\u679C\u7CBE\u6392\u3002\
|
|
1417
|
+
twoStage: import_koishi.Schema.boolean().default(true).description("\u3010\u4EC5\u65E7\u7248\u6A21\u5F0F\u751F\u6548\u3011\u4E24\u7EA7\u68C0\u7D22\u9009\u56FE\uFF1A\u5148\u8BA9\u6A21\u578B\u4EA7\u51FA\u68C0\u7D22\u5173\u952E\u8BCD\u5E76\u5728\u672C\u5730\u53EC\u56DE\uFF0C\u518D\u5BF9\u53EC\u56DE\u7ED3\u679C\u7CBE\u6392\u3002\u6253\u5206\u5236\u5DF2\u5185\u7F6E\u53EC\u56DE\uFF0C\u65E0\u9700\u6B64\u9879"),
|
|
1219
1418
|
twoStageThreshold: import_koishi.Schema.number().default(12).min(2).max(200).step(1).description("\u5019\u9009\u56FE\u7247\u8D85\u8FC7\u591A\u5C11\u5F20\u624D\u542F\u7528\u4E24\u7EA7\u68C0\u7D22\uFF08\u5C11\u4E8E\u6B64\u503C\u76F4\u63A5\u4E00\u6B21\u95EE\u5B8C\uFF0C\u66F4\u7701\u4E8B\uFF09"),
|
|
1220
1419
|
retrievalTopK: import_koishi.Schema.number().default(12).min(1).max(50).step(1).description("\u7B2C\u4E00\u7EA7\u53EC\u56DE\u7684\u5019\u9009\u6570\u91CF\u4E0A\u9650\uFF08\u7CBE\u6392\u53EA\u770B\u8FD9\u4E48\u591A\u5F20\uFF09"),
|
|
1221
1420
|
keywordPrompt: import_koishi.Schema.string().role("textarea", { rows: [10, 6] }).default(DEFAULT_KEYWORD_PROMPT).description("\u68C0\u7D22\u63D0\u793A\u8BCD\u6A21\u677F\uFF0C\u53EF\u7528\u5360\u4F4D\u7B26\uFF1A{index} \u56FE\u7247\u7D22\u5F15\u3001{userInput} \u7528\u6237\u9644\u52A0\u9700\u6C42\u3001{command} \u6307\u4EE4\u540D\u3001{prompt} \u6307\u4EE4\u63D0\u793A\u8BCD\u3001{topK} \u53EC\u56DE\u4E0A\u9650"),
|
|
1421
|
+
analyzePrompt: import_koishi.Schema.string().role("textarea", { rows: [12, 6] }).default(DEFAULT_ANALYZE_PROMPT).description("\uFF08\u6253\u5206\u5236\u7B2C\u4E00\u6B65\uFF09\u9700\u6C42\u5206\u6790\u63D0\u793A\u8BCD\uFF0C\u53EF\u7528\u5360\u4F4D\u7B26\uFF1A{command} \u6307\u4EE4\u540D\u3001{prompt} \u6307\u4EE4\u63D0\u793A\u8BCD\u3001{userInput} \u7528\u6237\u9644\u52A0\u9700\u6C42\u3002\u8FD9\u4E00\u6B65**\u4E0D\u628A\u5019\u9009\u56FE\u7ED9\u6A21\u578B**\uFF0C\u6240\u4EE5\u6A21\u578B\u6CA1\u6709\u4E71\u9009\u7684\u673A\u4F1A"),
|
|
1422
|
+
scorePrompt: import_koishi.Schema.string().role("textarea", { rows: [12, 6] }).default(DEFAULT_SCORE_PROMPT).description("\uFF08\u6253\u5206\u5236\u7B2C\u4E8C\u6B65\uFF09\u9010\u56FE\u6253\u5206\u63D0\u793A\u8BCD\uFF0C\u53EF\u7528\u5360\u4F4D\u7B26\uFF1A{subject} \u4E3B\u4F53\u3001{must} \u786C\u6027\u8981\u7D20\u3001{nice} \u52A0\u5206\u8981\u7D20\u3001{avoid} \u4E0D\u8981\u51FA\u73B0\u3001{candidates} \u5019\u9009\u56FE\u7247\u5217\u8868\u3001{max} \u6700\u591A\u9009\u62E9\u6570\u91CF"),
|
|
1222
1423
|
captionCommand: import_koishi.Schema.string().default("\u751F\u6210\u63CF\u8FF0").description("\u81EA\u52A8\u751F\u6210\u63CF\u8FF0\u7684\u6307\u4EE4\u540D\uFF08\u6302\u5728\u6307\u4EE4\u6839\u4E0B\uFF1B\u76F4\u63A5\u53D1\u56FE\u5219\u53EA\u8BC6\u522B\u5E76\u8FD4\u56DE\u63CF\u8FF0\uFF09"),
|
|
1223
1424
|
captionModel: import_koishi.Schema.string().description("\u751F\u6210\u63CF\u8FF0\u7528\u7684\u6A21\u578B\uFF08\u7559\u7A7A\u5219\u7528\u4E0A\u9762\u7684\u9009\u56FE\u6A21\u578B\uFF1B\u5FC5\u987B\u662F\u652F\u6301\u56FE\u7247\u8F93\u5165\u7684\u6A21\u578B\uFF09"),
|
|
1224
1425
|
captionPrompt: import_koishi.Schema.string().role("textarea", { rows: [8, 4] }).default(DEFAULT_CAPTION_PROMPT).description("\u751F\u6210\u63CF\u8FF0\u7684\u63D0\u793A\u8BCD\uFF08\u8981\u6C42\u6A21\u578B\u5199\u51FA\u4FBF\u4E8E\u68C0\u7D22\u7684\u5173\u952E\u8BCD\uFF09"),
|
|
@@ -1409,10 +1610,11 @@ function apply(ctx, config) {
|
|
|
1409
1610
|
selecting: "\u6B63\u5728\u667A\u80FD\u6311\u9009\u53C2\u8003\u56FE\u7247...",
|
|
1410
1611
|
selectfailed: "AI \u9009\u56FE\u5931\u8D25\uFF08{0}\uFF09\uFF0C\u5DF2\u6539\u7528\u5168\u90E8\u5019\u9009\u53C2\u8003\u56FE\u7247",
|
|
1411
1612
|
selectfailedNoFallback: "AI \u9009\u56FE\u5931\u8D25\uFF08{0}\uFF09\uFF0C\u672C\u6B21\u4E0D\u4F7F\u7528\u53C2\u8003\u56FE\u7247",
|
|
1613
|
+
nomatch: "\u56FE\u5E93\u91CC\u6CA1\u6709\u5408\u9002\u7684\u53C2\u8003\u56FE\uFF1A{0}",
|
|
1412
1614
|
selected: "\u5DF2\u4E3A\u4F60\u6311\u9009\u53C2\u8003\u56FE\u7247\uFF1A\n{0}",
|
|
1413
1615
|
askimage: "{0}\n\u8BF7\u5728{1}\u79D2\u5185\u53D1\u9001\u56FE\u7247...",
|
|
1414
1616
|
askimageDefault: "\u5019\u9009\u53C2\u8003\u56FE\u7247\u91CC\u6CA1\u6709\u5408\u9002\u7684\u56FE\u7247\uFF0C\u9700\u8981\u4F60\u8865\u5145\u4E00\u5F20\u53C2\u8003\u56FE",
|
|
1415
|
-
noask: "\u672A\u6536\u5230\u8865\u5145\u56FE\u7247\uFF0C\
|
|
1617
|
+
noask: "\u672A\u6536\u5230\u8865\u5145\u56FE\u7247\uFF0C\u7EE7\u7EED\u5904\u7406",
|
|
1416
1618
|
gotimage: "\u5DF2\u6536\u5230\u8865\u5145\u56FE\u7247\uFF0C\u7EE7\u7EED\u5904\u7406...",
|
|
1417
1619
|
recalled: "\uFF08\u53C2\u8003\u56FE\u68C0\u7D22\uFF1A{0} \u5F20\u4E2D\u547D\u4E2D {1} \u5F20\u5019\u9009\uFF09",
|
|
1418
1620
|
hintsingle: "\u53C2\u8003\u56FE\u5173\u952E\u7279\u5F81\uFF08\u52A1\u5FC5\u8FD8\u539F\uFF09\uFF1A{0}",
|
|
@@ -1586,15 +1788,20 @@ ${session.text(`image-prompt.messages.${hintKey}`, [selection.hint])}`;
|
|
|
1586
1788
|
aiRenderText = selection.renderText;
|
|
1587
1789
|
logInfo2(`\u9009\u56FE\u6A21\u578B\u7ED9\u51FA\u9700\u8981\u6E32\u67D3\u7684\u6587\u5B57: ${aiRenderText.replace(/\n/g, " / ")}`);
|
|
1588
1790
|
}
|
|
1589
|
-
} else if (
|
|
1590
|
-
|
|
1591
|
-
|
|
1791
|
+
} else if (selection.ok && selection.picked.length === 0) {
|
|
1792
|
+
logInfo2(`[${cmdConfig.name}] \u6CA1\u6709\u53C2\u8003\u56FE\u8FBE\u5230\u9608\u503C\uFF1A${selection.reason}`);
|
|
1793
|
+
if (selector.notify) {
|
|
1794
|
+
selectionNote = "\n" + session.text("image-prompt.messages.nomatch", [
|
|
1795
|
+
selection.reason || "\u65E0\u5339\u914D"
|
|
1796
|
+
]);
|
|
1592
1797
|
}
|
|
1798
|
+
} else if (!selection.ok) {
|
|
1799
|
+
ctx.logger.warn(`[${cmdConfig.name}] AI \u9009\u56FE\u5931\u8D25\uFF0CfallbackOnError=${selector.fallbackOnError}`);
|
|
1593
1800
|
if (selector.fallbackOnError) {
|
|
1594
1801
|
images.push(...candidates.map((c) => c.url));
|
|
1595
1802
|
aiProvidedImages += candidates.length;
|
|
1596
1803
|
}
|
|
1597
|
-
if (selector.notify
|
|
1804
|
+
if (selector.notify) {
|
|
1598
1805
|
selectionNote = "\n" + session.text(
|
|
1599
1806
|
selector.fallbackOnError ? "image-prompt.messages.selectfailed" : "image-prompt.messages.selectfailedNoFallback",
|
|
1600
1807
|
[selection.error || "\u672A\u77E5\u539F\u56E0"]
|
|
@@ -1667,7 +1874,7 @@ Text in the image must be rendered exactly as shown in the attached text-referen
|
|
|
1667
1874
|
}
|
|
1668
1875
|
}
|
|
1669
1876
|
if (images.length === 0 && !textRef) {
|
|
1670
|
-
await reply(session, [session.text("image-prompt.messages.needimages")]);
|
|
1877
|
+
await reply(session, [session.text("image-prompt.messages.needimages") + selectionNote]);
|
|
1671
1878
|
return;
|
|
1672
1879
|
}
|
|
1673
1880
|
logInfo2(images);
|
|
@@ -2142,6 +2349,9 @@ ${lines.join("\n")}`]);
|
|
|
2142
2349
|
}
|
|
2143
2350
|
async function runAISelection(candidates, userInput, cmdConfig, promptText, max) {
|
|
2144
2351
|
const selector = config.aiSelector || {};
|
|
2352
|
+
if (selector.selectionMode !== "legacy") {
|
|
2353
|
+
return runScoredSelection(candidates, userInput, cmdConfig, promptText, max);
|
|
2354
|
+
}
|
|
2145
2355
|
const threshold = selector.twoStageThreshold || 12;
|
|
2146
2356
|
if (selector.twoStage !== false && candidates.length > threshold) {
|
|
2147
2357
|
const result = await runTwoStageSelection(candidates, userInput, cmdConfig, promptText, max);
|
|
@@ -2150,6 +2360,111 @@ ${lines.join("\n")}`]);
|
|
|
2150
2360
|
}
|
|
2151
2361
|
return runSingleStageSelection(candidates, userInput, cmdConfig, promptText, max);
|
|
2152
2362
|
}
|
|
2363
|
+
async function runScoredSelection(candidates, userInput, cmdConfig, promptText, max) {
|
|
2364
|
+
const selector = config.aiSelector || {};
|
|
2365
|
+
const minScore = typeof selector.minScore === "number" ? selector.minScore : 60;
|
|
2366
|
+
const topK = selector.retrievalTopK || 12;
|
|
2367
|
+
const respectSkip = selector.respectSkipReference !== false;
|
|
2368
|
+
if (respectSkip && isSkipReferenceInput(userInput)) {
|
|
2369
|
+
logInfo2("\u7528\u6237\u8868\u793A\u4E0D\u9700\u8981\u53C2\u8003\u56FE\uFF0C\u8DF3\u8FC7\u9009\u56FE");
|
|
2370
|
+
return { picked: [], needUserImage: false, askMessage: "", reason: "\u7528\u6237\u8868\u793A\u4E0D\u9700\u8981\u53C2\u8003\u56FE", ok: true };
|
|
2371
|
+
}
|
|
2372
|
+
const analyzeContent = (selector.analyzePrompt || DEFAULT_ANALYZE_PROMPT).replace(/\{command\}/g, cmdConfig.name || "").replace(/\{prompt\}/g, promptText || "").replace(/\{userInput\}/g, userInput || "\uFF08\u7528\u6237\u672A\u9644\u52A0\u8BF4\u660E\uFF09");
|
|
2373
|
+
const analysisCall = await callSelectorModel(
|
|
2374
|
+
analyzeContent,
|
|
2375
|
+
analyzeContent,
|
|
2376
|
+
false,
|
|
2377
|
+
selector.keywordMaxTokens || 3e3,
|
|
2378
|
+
"\u4F60\u662F\u7ED8\u56FE\u53C2\u8003\u56FE\u9700\u6C42\u5206\u6790\u52A9\u624B\uFF0C\u53EA\u8F93\u51FA JSON\uFF0C\u4E0D\u8981\u6311\u9009\u56FE\u7247\u3002"
|
|
2379
|
+
);
|
|
2380
|
+
const analysis = parseAnalysisResult(analysisCall.raw);
|
|
2381
|
+
if (!analysis) {
|
|
2382
|
+
return {
|
|
2383
|
+
picked: [],
|
|
2384
|
+
needUserImage: false,
|
|
2385
|
+
askMessage: "",
|
|
2386
|
+
reason: "",
|
|
2387
|
+
ok: false,
|
|
2388
|
+
error: analysisCall.error || "\u9700\u6C42\u5206\u6790\u6CA1\u6709\u8FD4\u56DE\u53EF\u89E3\u6790\u7684\u7ED3\u679C"
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
logInfo2(`\u9700\u6C42\u5206\u6790\uFF1A\u4E3B\u4F53=${analysis.subject || "\uFF08\u65E0\uFF09"} \u786C\u6027=${JSON.stringify(analysis.must)} \u52A0\u5206=${JSON.stringify(analysis.nice)}`);
|
|
2392
|
+
if (analysis.skipReference && respectSkip) {
|
|
2393
|
+
logInfo2("\u9700\u6C42\u5206\u6790\u5224\u5B9A\u672C\u6B21\u4E0D\u9700\u8981\u53C2\u8003\u56FE");
|
|
2394
|
+
return {
|
|
2395
|
+
picked: [],
|
|
2396
|
+
needUserImage: false,
|
|
2397
|
+
askMessage: "",
|
|
2398
|
+
reason: "\u672C\u6B21\u4E0D\u9700\u8981\u53C2\u8003\u56FE",
|
|
2399
|
+
ok: true,
|
|
2400
|
+
keywords: keywordsFromAnalysis(analysis)
|
|
2401
|
+
};
|
|
2402
|
+
}
|
|
2403
|
+
const pool = selector.dedupe === false ? candidates : dedupeCandidates(candidates);
|
|
2404
|
+
const keywords = keywordsFromAnalysis(analysis);
|
|
2405
|
+
const matched = matchCandidatesByKeywords(pool, keywords, topK);
|
|
2406
|
+
const shortlist = matched.length > 0 ? matched : pool.slice(0, Math.max(topK, 1) * 2);
|
|
2407
|
+
logInfo2(`\u5173\u952E\u8BCD\u53EC\u56DE ${shortlist.length}/${pool.length} \u5F20\u8FDB\u5165\u6253\u5206\uFF08\u5173\u952E\u8BCD\uFF1A${keywords.join("/") || "\u65E0"}\uFF09`);
|
|
2408
|
+
if (shortlist.length === 0) {
|
|
2409
|
+
return {
|
|
2410
|
+
picked: [],
|
|
2411
|
+
needUserImage: true,
|
|
2412
|
+
askMessage: analysis.needTypes,
|
|
2413
|
+
reason: "\u5019\u9009\u6C60\u91CC\u6CA1\u6709\u56FE\u7247",
|
|
2414
|
+
ok: true,
|
|
2415
|
+
keywords,
|
|
2416
|
+
recalled: 0,
|
|
2417
|
+
total: pool.length,
|
|
2418
|
+
renderText: analysis.text || void 0
|
|
2419
|
+
};
|
|
2420
|
+
}
|
|
2421
|
+
const scoreContent = (selector.scorePrompt || DEFAULT_SCORE_PROMPT).replace(/\{subject\}/g, analysis.subject || "\uFF08\u672A\u6307\u5B9A\uFF09").replace(/\{must\}/g, analysis.must.length ? analysis.must.join("\u3001") : "\uFF08\u65E0\uFF09").replace(/\{nice\}/g, analysis.nice.length ? analysis.nice.join("\u3001") : "\uFF08\u65E0\uFF09").replace(/\{avoid\}/g, analysis.avoid.length ? analysis.avoid.join("\u3001") : "\uFF08\u65E0\uFF09").replace(/\{candidates\}/g, buildIndexText(shortlist)).replace(/\{max\}/g, String(max));
|
|
2422
|
+
const visionOn = selector.vision === true;
|
|
2423
|
+
const scoreUserContent = buildSelectorContent(
|
|
2424
|
+
scoreContent,
|
|
2425
|
+
shortlist,
|
|
2426
|
+
visionOn,
|
|
2427
|
+
selector.visionMaxImages || 6
|
|
2428
|
+
);
|
|
2429
|
+
const scoreCall = await callSelectorModel(
|
|
2430
|
+
scoreUserContent,
|
|
2431
|
+
scoreContent,
|
|
2432
|
+
visionOn,
|
|
2433
|
+
selector.selectMaxTokens || 8e3,
|
|
2434
|
+
"\u4F60\u662F\u53C2\u8003\u56FE\u6253\u5206\u52A9\u624B\uFF0C\u53EA\u8F93\u51FA JSON\u3002"
|
|
2435
|
+
);
|
|
2436
|
+
const scored = parseScoreResult(scoreCall.raw, shortlist);
|
|
2437
|
+
if (scored.length === 0) {
|
|
2438
|
+
return {
|
|
2439
|
+
picked: [],
|
|
2440
|
+
needUserImage: false,
|
|
2441
|
+
askMessage: "",
|
|
2442
|
+
reason: "",
|
|
2443
|
+
ok: false,
|
|
2444
|
+
keywords,
|
|
2445
|
+
recalled: shortlist.length,
|
|
2446
|
+
total: pool.length,
|
|
2447
|
+
error: scoreCall.error || "\u6253\u5206\u9636\u6BB5\u6CA1\u6709\u62FF\u5230\u6709\u6548\u7684\u5206\u6570"
|
|
2448
|
+
};
|
|
2449
|
+
}
|
|
2450
|
+
const { picked, best, passed } = selectByScore(scored, shortlist, minScore, max);
|
|
2451
|
+
const detail = scored.slice().sort((a, b) => b.score - a.score).slice(0, 5).map((item) => `${item.index}:${item.score}\u5206(${item.why || "-"})`).join(" ");
|
|
2452
|
+
logInfo2(`\u9010\u56FE\u6253\u5206\uFF08\u9608\u503C ${minScore}\uFF09\uFF1A\u6700\u9AD8 ${best} \u5206\uFF0C\u8FBE\u6807 ${passed} \u5F20\uFF0C\u9009\u4E2D ${picked.length} \u5F20 | ${detail}`);
|
|
2453
|
+
const hint = String(extractJsonObject(scoreCall.raw)?.hint || "").trim() || void 0;
|
|
2454
|
+
return {
|
|
2455
|
+
picked,
|
|
2456
|
+
// 一张都不达标 = 图库里确实没有合适的 -> 让上层去问用户补图,而不是硬塞
|
|
2457
|
+
needUserImage: picked.length === 0,
|
|
2458
|
+
askMessage: picked.length === 0 ? analysis.needTypes || "" : "",
|
|
2459
|
+
reason: picked.length ? `\u547D\u4E2D\u9700\u6C42\uFF08\u6700\u9AD8 ${best} \u5206\uFF09` : `\u6CA1\u6709\u56FE\u8FBE\u5230 ${minScore} \u5206\u95E8\u69DB\uFF08\u6700\u9AD8\u53EA\u6709 ${best} \u5206\uFF09`,
|
|
2460
|
+
ok: true,
|
|
2461
|
+
keywords,
|
|
2462
|
+
recalled: shortlist.length,
|
|
2463
|
+
total: pool.length,
|
|
2464
|
+
renderText: analysis.text || void 0,
|
|
2465
|
+
hint: visionOn && selector.appendHint !== false ? hint : void 0
|
|
2466
|
+
};
|
|
2467
|
+
}
|
|
2153
2468
|
function buildIndexText(candidates) {
|
|
2154
2469
|
return candidates.map((c, i) => `[${i + 1}] \u6240\u5C5E\u7EC4\uFF1A${c.group} | \u63CF\u8FF0\uFF1A${c.description || "\uFF08\u65E0\u63CF\u8FF0\uFF09"}`).join("\n");
|
|
2155
2470
|
}
|
|
@@ -2483,8 +2798,10 @@ ${lines.join("\n")}`]);
|
|
|
2483
2798
|
buildSelectorContent,
|
|
2484
2799
|
buildTextHtml,
|
|
2485
2800
|
computeRetryDelay,
|
|
2801
|
+
dedupeCandidates,
|
|
2486
2802
|
describeSelectorError,
|
|
2487
2803
|
escapeHtml,
|
|
2804
|
+
extractJsonObject,
|
|
2488
2805
|
extractResponseText,
|
|
2489
2806
|
extractServerMessage,
|
|
2490
2807
|
extractTextToRender,
|
|
@@ -2492,19 +2809,26 @@ ${lines.join("\n")}`]);
|
|
|
2492
2809
|
inject,
|
|
2493
2810
|
isPassiveReplyError,
|
|
2494
2811
|
isRetryableStatus,
|
|
2812
|
+
isSkipReferenceInput,
|
|
2813
|
+
keywordsFromAnalysis,
|
|
2495
2814
|
matchCandidatesByKeywords,
|
|
2496
2815
|
mergeCandidates,
|
|
2497
2816
|
mergePrompt,
|
|
2498
2817
|
name,
|
|
2818
|
+
normalizeScore,
|
|
2819
|
+
parseAnalysisResult,
|
|
2499
2820
|
parseRetryAfterHeader,
|
|
2821
|
+
parseScoreResult,
|
|
2500
2822
|
parseSelectionResult,
|
|
2501
2823
|
previewJson,
|
|
2502
2824
|
readImageSize,
|
|
2503
2825
|
resolveTokenParam,
|
|
2504
2826
|
sanitizeCaption,
|
|
2827
|
+
selectByScore,
|
|
2505
2828
|
stripCommandName,
|
|
2506
2829
|
stripThinkTags,
|
|
2507
2830
|
supportsMarkdown,
|
|
2831
|
+
toStrList,
|
|
2508
2832
|
trimGallery,
|
|
2509
2833
|
truncateText,
|
|
2510
2834
|
usage,
|
package/package.json
CHANGED