@hupan56/wlkj 3.3.13 → 3.3.15
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/bin/cli.js +0 -7
- package/package.json +29 -29
- package/templates/qoder/commands/optional/wl-spec.md +0 -8
- package/templates/qoder/commands/optional/wl-status.md +0 -8
- package/templates/qoder/commands/wl-code.md +0 -8
- package/templates/qoder/commands/wl-commit.md +0 -8
- package/templates/qoder/commands/wl-init.md +129 -129
- package/templates/qoder/commands/wl-search.md +0 -8
- package/templates/qoder/commands/wl-task.md +0 -8
- package/templates/qoder/commands/wl-test.md +0 -8
- package/templates/qoder/config.yaml +2 -3
- package/templates/qoder/contracts/insight.md +55 -55
- package/templates/qoder/hooks/pre-tool-use-commit.py +124 -124
- package/templates/qoder/hooks/session-start.py +384 -384
- package/templates/qoder/hooks/stop-eval.py +383 -383
- package/templates/qoder/scripts/capability/adapters/mcp.py +322 -322
- package/templates/qoder/scripts/capability/registry.py +245 -245
- package/templates/qoder/scripts/deployment/setup/install_qoderwork.py +14 -0
- package/templates/qoder/scripts/deployment/setup/setup.py +0 -11
- package/templates/qoder/scripts/domain/task/wlkj_panel.py +1503 -1503
- package/templates/qoder/scripts/foundation/bootstrap.py +145 -156
- package/templates/qoder/scripts/foundation/io/context_cache.py +94 -94
- package/templates/qoder/scripts/orchestration/wlkj.py +295 -306
- package/templates/qoder/scripts/tool_guide.md +70 -70
- package/templates/qoder/scripts/validation/eval/alignment_matrix.py +176 -176
- package/templates/qoder/scripts/validation/eval/bf2_content_fidelity.py +110 -110
- package/templates/qoder/scripts/validation/eval/bf2_llmjudge.py +104 -104
- package/templates/qoder/scripts/validation/eval/bf_score.py +218 -218
- package/templates/qoder/scripts/validation/eval/code_flywheel.py +150 -150
- package/templates/qoder/scripts/validation/eval/dispatcher_ab.py +156 -156
- package/templates/qoder/scripts/validation/eval/dispatcher_ab_2026-07-21.json +23 -23
- package/templates/qoder/scripts/validation/eval/feature_fidelity_flywheel.py +143 -143
- package/templates/qoder/scripts/validation/eval/gradient_matrix.py +261 -261
- package/templates/qoder/scripts/validation/eval/gradient_matrix_baseline_2026-07-21.json +33 -33
- package/templates/qoder/scripts/validation/eval/metrics_dashboard.py +105 -105
- package/templates/qoder/scripts/validation/eval/multi_turn_flywheel.py +118 -118
- package/templates/qoder/scripts/validation/eval/prd_fidelity_flywheel.py +128 -128
- package/templates/qoder/scripts/validation/eval/prd_flywheel.py +148 -148
- package/templates/qoder/scripts/validation/eval/prototype_fidelity_flywheel.py +166 -166
- package/templates/qoder/scripts/validation/eval/recall_flywheel.py +148 -148
- package/templates/qoder/scripts/validation/eval/robustness_flywheel.py +139 -139
- package/templates/qoder/scripts/validation/eval/speed_accuracy_flywheel.py +188 -188
- package/templates/qoder/scripts/validation/eval/task_flywheel.py +124 -124
- package/templates/qoder/scripts/validation/eval/token_flywheel.py +88 -88
- package/templates/qoder/scripts/validation/metrics/eval_code_ac.py +177 -177
- package/templates/qoder/scripts/validation/metrics/lint_cases.py +170 -170
- package/templates/qoder/scripts/validation/test/test_context_cache.py +78 -78
- package/templates/qoder/scripts/validation/test/test_lint_cases.py +60 -60
- package/templates/qoder/scripts/validation/test/test_pre_tool_use_commit.py +70 -70
- package/templates/qoder/commands/wl-data.md +0 -46
- package/templates/qoder/commands/wl-fix.md +0 -47
- package/templates/qoder/commands/wl-knowledge.md +0 -41
- package/templates/qoder/commands/wl-review.md +0 -49
- package/templates/workspace/specs/REQ-TEST-CTX/.context-cache.json +0 -1
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
{
|
|
2
|
-
"task": "T1.1 mode dispatcher 确定性路由 (wl-search)",
|
|
3
|
-
"date": "2026-07-21",
|
|
4
|
-
"ruler": "scripts/validation/eval/dispatcher_ab.py",
|
|
5
|
-
"env": "云 10.89.7.120, DashScope turbo/plus/max, 14 gold 查询(7通道x2)",
|
|
6
|
-
"change": "wl-search '第一步:先判断问题类型'(纯LLM猜测) -> '确定性路由(按顺序首匹配信号,零猜测)' 7行表+默认rag_search; sync packages->.qoder diff空",
|
|
7
|
-
"matrix": {
|
|
8
|
-
"weak": {"old_acc": 0.857, "new_acc": 1.0, "gain_pp": 14.3},
|
|
9
|
-
"mid": {"old_acc": 0.857, "new_acc": 1.0, "gain_pp": 14.3},
|
|
10
|
-
"strong": {"old_acc": 0.857, "new_acc": 1.0, "gain_pp": 14.3}
|
|
11
|
-
},
|
|
12
|
-
"old_failures": [
|
|
13
|
-
"status 字段有哪些枚举值 -> gold=db, got=rag_search (旧表 db 只在括号注)",
|
|
14
|
-
"盘点考勤有哪些代码和字段 -> gold=context_pack, got=rag_search (旧表'盘点'非明确信号)"
|
|
15
|
-
],
|
|
16
|
-
"insight": "三档同错同对(2错全修)再次印证 T1.0: 结构好时弱模型=强模型; dispatcher 价值在表结构非模型档位",
|
|
17
|
-
"honest_caveats": [
|
|
18
|
-
"gold 仅14条 + 作者同时写 gold 和新表, 有小样本/作者重叠风险(新表可能贴 gold)",
|
|
19
|
-
"2 修复项(枚举->db/盘点->context_pack)确为旧表缺新表补的显式信号, 改进真实",
|
|
20
|
-
"🖥️ 宿主端到端(弱模型跑真/wl-search 是否真按表走) 待用户验"
|
|
21
|
-
],
|
|
22
|
-
"status": "代码改+sync+自验A/B完成; 🖥️宿主端到端列入 §12 V1.2"
|
|
23
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"task": "T1.1 mode dispatcher 确定性路由 (wl-search)",
|
|
3
|
+
"date": "2026-07-21",
|
|
4
|
+
"ruler": "scripts/validation/eval/dispatcher_ab.py",
|
|
5
|
+
"env": "云 10.89.7.120, DashScope turbo/plus/max, 14 gold 查询(7通道x2)",
|
|
6
|
+
"change": "wl-search '第一步:先判断问题类型'(纯LLM猜测) -> '确定性路由(按顺序首匹配信号,零猜测)' 7行表+默认rag_search; sync packages->.qoder diff空",
|
|
7
|
+
"matrix": {
|
|
8
|
+
"weak": {"old_acc": 0.857, "new_acc": 1.0, "gain_pp": 14.3},
|
|
9
|
+
"mid": {"old_acc": 0.857, "new_acc": 1.0, "gain_pp": 14.3},
|
|
10
|
+
"strong": {"old_acc": 0.857, "new_acc": 1.0, "gain_pp": 14.3}
|
|
11
|
+
},
|
|
12
|
+
"old_failures": [
|
|
13
|
+
"status 字段有哪些枚举值 -> gold=db, got=rag_search (旧表 db 只在括号注)",
|
|
14
|
+
"盘点考勤有哪些代码和字段 -> gold=context_pack, got=rag_search (旧表'盘点'非明确信号)"
|
|
15
|
+
],
|
|
16
|
+
"insight": "三档同错同对(2错全修)再次印证 T1.0: 结构好时弱模型=强模型; dispatcher 价值在表结构非模型档位",
|
|
17
|
+
"honest_caveats": [
|
|
18
|
+
"gold 仅14条 + 作者同时写 gold 和新表, 有小样本/作者重叠风险(新表可能贴 gold)",
|
|
19
|
+
"2 修复项(枚举->db/盘点->context_pack)确为旧表缺新表补的显式信号, 改进真实",
|
|
20
|
+
"🖥️ 宿主端到端(弱模型跑真/wl-search 是否真按表走) 待用户验"
|
|
21
|
+
],
|
|
22
|
+
"status": "代码改+sync+自验A/B完成; 🖥️宿主端到端列入 §12 V1.2"
|
|
23
|
+
}
|
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
"""feature_fidelity_flywheel.py — FW10 BF5/BF6 feature-scoped 业务保真飞轮。
|
|
2
|
-
|
|
3
|
-
关键:precision 改成 vs【该 feature 真业务实体集】(非任意真实体)。
|
|
4
|
-
之前 code/search 量"列出的是不是真实体"(可列真但不相关的实体也得分)→ 业务保真虚高。
|
|
5
|
-
BF5/BF6 量"列出的是不是【这个 feature 的】真实体"——真业务相关,非泛实体。
|
|
6
|
-
- BF6 search feature相关率 = 返回实体 ∈ feature_gold / 返回总数
|
|
7
|
-
- BF5 code feature精准 = 改实体 ∈ feature_gold / 改总数
|
|
8
|
-
bare(无接地→泛/编造) vs +该feature gold接地。
|
|
9
|
-
|
|
10
|
-
跑法: docker exec -i wlinkj-workspace-backend-1 python /app/scripts/validation/eval/feature_fidelity_flywheel.py
|
|
11
|
-
"""
|
|
12
|
-
import os
|
|
13
|
-
import re
|
|
14
|
-
import sys
|
|
15
|
-
import json
|
|
16
|
-
import time
|
|
17
|
-
import urllib.request
|
|
18
|
-
import urllib.error
|
|
19
|
-
|
|
20
|
-
for _p in ("/app", os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", ".."))):
|
|
21
|
-
if os.path.isdir(_p) and _p not in sys.path:
|
|
22
|
-
sys.path.insert(0, _p)
|
|
23
|
-
|
|
24
|
-
from sqlalchemy import text # noqa: E402
|
|
25
|
-
from app.db import SessionLocal # noqa: E402
|
|
26
|
-
|
|
27
|
-
CHAT_URL = os.environ.get("ALI_CHAT_BASE", "").rstrip("/") + "/chat/completions"
|
|
28
|
-
CHAT_KEY = os.environ.get("DASHSCOPE_API_KEY", "")
|
|
29
|
-
MODEL = "qwen-turbo"
|
|
30
|
-
FEATURES = [("车辆保险管理", "保险"), ("异常记录管理", "异常"), ("合同维护", "合同")]
|
|
31
|
-
_LINE_CLEAN = re.compile(r"^[\-\*\d\.\)、\s]+")
|
|
32
|
-
_TOK = re.compile(r"[A-Za-z_][\w./\-:]{2,}")
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def chat(prompt, max_tokens=400, timeout=80):
|
|
36
|
-
body = json.dumps({"model": MODEL,
|
|
37
|
-
"messages": [{"role": "system", "content": "你是车辆物联网系统(ICS)助手,只答真实存在的对象。"},
|
|
38
|
-
{"role": "user", "content": prompt}], "temperature": 0.0, "max_tokens": max_tokens}).encode()
|
|
39
|
-
for a in range(3):
|
|
40
|
-
try:
|
|
41
|
-
req = urllib.request.Request(CHAT_URL, data=body,
|
|
42
|
-
headers={"Authorization": f"Bearer {CHAT_KEY}", "Content-Type": "application/json"})
|
|
43
|
-
return json.loads(urllib.request.urlopen(req, timeout=timeout).read())["choices"][0]["message"]["content"]
|
|
44
|
-
except (urllib.error.URLError, TimeoutError, OSError, KeyError) as e:
|
|
45
|
-
if a < 2: time.sleep(1.0*(a+1))
|
|
46
|
-
else: return ""
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def _q(s, sql, p=None):
|
|
50
|
-
try: return s.execute(text(sql), p or {}).fetchall()
|
|
51
|
-
except Exception:
|
|
52
|
-
try: s.rollback()
|
|
53
|
-
except Exception: pass
|
|
54
|
-
return []
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def feature_gold(theme, k=20):
|
|
58
|
-
"""该 feature 的真业务实体集(BF5/BF6 的 gold)。"""
|
|
59
|
-
s = SessionLocal()
|
|
60
|
-
rows = _q(s, "SELECT canonical, cn FROM entities WHERE (canonical ILIKE :p OR cn ILIKE :p) "
|
|
61
|
-
"AND type IN ('CONTROLLER','SERVICE','TABLE','COLUMN','FUNCTION') LIMIT :n",
|
|
62
|
-
{"p": f"%{theme}%", "n": k})
|
|
63
|
-
s.close()
|
|
64
|
-
return [(c, n) for c, n in rows if c]
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def extract_names(ans):
|
|
68
|
-
out = set()
|
|
69
|
-
for line in ans.splitlines():
|
|
70
|
-
line = _LINE_CLEAN.sub("", line).strip()
|
|
71
|
-
if line and len(line) <= 60:
|
|
72
|
-
m = _TOK.findall(line)
|
|
73
|
-
if m: out.add(m[0])
|
|
74
|
-
return out
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def feature_precision(ans, gold):
|
|
78
|
-
"""feature 保真:列出的 ∈ 该feature gold 比例(非任意真实体)。"""
|
|
79
|
-
cands = extract_names(ans)
|
|
80
|
-
if not cands: return 0.0, 0
|
|
81
|
-
gold_canon = {c for c, _ in gold}
|
|
82
|
-
hit = sum(1 for c in cands if c in gold_canon)
|
|
83
|
-
# 也算 cn 命中(ans 文本含 gold cn)
|
|
84
|
-
# precision = 命中gold的候选 / 总候选
|
|
85
|
-
feat_hit = 0
|
|
86
|
-
for c in cands:
|
|
87
|
-
if c in gold_canon:
|
|
88
|
-
feat_hit += 1
|
|
89
|
-
return round(feat_hit / len(cands), 3), len(cands)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def run():
|
|
93
|
-
rep = {"features": []}
|
|
94
|
-
for feat, theme in FEATURES:
|
|
95
|
-
gold = feature_gold(theme, 20)
|
|
96
|
-
gold_ctx = "\n".join("%s (%s)" % (c, n) for c, n in gold) or "(无)"
|
|
97
|
-
# BF6 search
|
|
98
|
-
b_search = chat(f"找 ICS 系统「{feat}」相关的具体对象(类/表/字段/接口),逐行列出,勿编造。")
|
|
99
|
-
s_search = chat(f"找 ICS 系统「{feat}」相关对象。知识图谱检索到(均真实):\n{gold_ctx}\n请把检索结果实体全部逐行列出,直接用名称,勿编造。")
|
|
100
|
-
bP_s, bN_s = feature_precision(b_search, gold)
|
|
101
|
-
sP_s, sN_s = feature_precision(s_search, gold)
|
|
102
|
-
# BF5 code
|
|
103
|
-
b_code = chat(f"给「{feat}」加功能,逐行列出需修改的代码类/方法名,勿编造。")
|
|
104
|
-
s_code = chat(f"给「{feat}」加功能。get_impact 检索到真实实体:\n{gold_ctx}\n请把检索结果实体全部逐行列出,直接用名称,勿编造。")
|
|
105
|
-
bP_c, bN_c = feature_precision(b_code, gold)
|
|
106
|
-
sP_c, sN_c = feature_precision(s_code, gold)
|
|
107
|
-
rep["features"].append({"feature": feat, "gold_n": len(gold),
|
|
108
|
-
"BF6_bare": bP_s, "BF6_scaffold": sP_s,
|
|
109
|
-
"BF5_bare": bP_c, "BF5_scaffold": sP_c})
|
|
110
|
-
print(" %s(gold=%d): BF6 search 相关率 bare=%.0f%%→scaff=%.0f%% | BF5 code 精准 bare=%.0f%%→scaff=%.0f%%" % (
|
|
111
|
-
feat, len(gold), bP_s*100, sP_s*100, bP_c*100, sP_c*100))
|
|
112
|
-
n = len(FEATURES) or 1
|
|
113
|
-
rep["agg"] = {
|
|
114
|
-
"BF6_bare": round(sum(f["BF6_bare"] for f in rep["features"])/n, 3),
|
|
115
|
-
"BF6_scaffold": round(sum(f["BF6_scaffold"] for f in rep["features"])/n, 3),
|
|
116
|
-
"BF5_bare": round(sum(f["BF5_bare"] for f in rep["features"])/n, 3),
|
|
117
|
-
"BF5_scaffold": round(sum(f["BF5_scaffold"] for f in rep["features"])/n, 3),
|
|
118
|
-
}
|
|
119
|
-
return rep
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def main():
|
|
123
|
-
import argparse
|
|
124
|
-
ap = argparse.ArgumentParser()
|
|
125
|
-
ap.add_argument("--json", action="store_true")
|
|
126
|
-
args = ap.parse_args()
|
|
127
|
-
r = run()
|
|
128
|
-
a = r["agg"]
|
|
129
|
-
if args.json:
|
|
130
|
-
print(json.dumps(r, ensure_ascii=False, indent=2))
|
|
131
|
-
return
|
|
132
|
-
print("\n## FW10 BF5/BF6 feature-scoped 业务保真飞轮(列的是【该feature】真实体,非任意真实体)")
|
|
133
|
-
print("| 指标 | bare | +该feature gold接地 | 目标 |")
|
|
134
|
-
print("|---|---|---|---|")
|
|
135
|
-
print("| BF6 search feature相关率 | %.0f%% | %.0f%% | ≥85%% |" % (a["BF6_bare"]*100, a["BF6_scaffold"]*100))
|
|
136
|
-
print("| BF5 code feature精准 | %.0f%% | %.0f%% | ≥85%% |" % (a["BF5_bare"]*100, a["BF5_scaffold"]*100))
|
|
137
|
-
b6 = a["BF6_scaffold"] >= 0.85; b5 = a["BF5_scaffold"] >= 0.85
|
|
138
|
-
print("\nBF6达标?" , "✓" if b6 else "✗", "| BF5达标?", "✓" if b5 else "✗",
|
|
139
|
-
"| 不达标续转(更强feature接地/拒非feature实体)")
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if __name__ == "__main__":
|
|
143
|
-
main()
|
|
1
|
+
"""feature_fidelity_flywheel.py — FW10 BF5/BF6 feature-scoped 业务保真飞轮。
|
|
2
|
+
|
|
3
|
+
关键:precision 改成 vs【该 feature 真业务实体集】(非任意真实体)。
|
|
4
|
+
之前 code/search 量"列出的是不是真实体"(可列真但不相关的实体也得分)→ 业务保真虚高。
|
|
5
|
+
BF5/BF6 量"列出的是不是【这个 feature 的】真实体"——真业务相关,非泛实体。
|
|
6
|
+
- BF6 search feature相关率 = 返回实体 ∈ feature_gold / 返回总数
|
|
7
|
+
- BF5 code feature精准 = 改实体 ∈ feature_gold / 改总数
|
|
8
|
+
bare(无接地→泛/编造) vs +该feature gold接地。
|
|
9
|
+
|
|
10
|
+
跑法: docker exec -i wlinkj-workspace-backend-1 python /app/scripts/validation/eval/feature_fidelity_flywheel.py
|
|
11
|
+
"""
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import sys
|
|
15
|
+
import json
|
|
16
|
+
import time
|
|
17
|
+
import urllib.request
|
|
18
|
+
import urllib.error
|
|
19
|
+
|
|
20
|
+
for _p in ("/app", os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", ".."))):
|
|
21
|
+
if os.path.isdir(_p) and _p not in sys.path:
|
|
22
|
+
sys.path.insert(0, _p)
|
|
23
|
+
|
|
24
|
+
from sqlalchemy import text # noqa: E402
|
|
25
|
+
from app.db import SessionLocal # noqa: E402
|
|
26
|
+
|
|
27
|
+
CHAT_URL = os.environ.get("ALI_CHAT_BASE", "").rstrip("/") + "/chat/completions"
|
|
28
|
+
CHAT_KEY = os.environ.get("DASHSCOPE_API_KEY", "")
|
|
29
|
+
MODEL = "qwen-turbo"
|
|
30
|
+
FEATURES = [("车辆保险管理", "保险"), ("异常记录管理", "异常"), ("合同维护", "合同")]
|
|
31
|
+
_LINE_CLEAN = re.compile(r"^[\-\*\d\.\)、\s]+")
|
|
32
|
+
_TOK = re.compile(r"[A-Za-z_][\w./\-:]{2,}")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def chat(prompt, max_tokens=400, timeout=80):
|
|
36
|
+
body = json.dumps({"model": MODEL,
|
|
37
|
+
"messages": [{"role": "system", "content": "你是车辆物联网系统(ICS)助手,只答真实存在的对象。"},
|
|
38
|
+
{"role": "user", "content": prompt}], "temperature": 0.0, "max_tokens": max_tokens}).encode()
|
|
39
|
+
for a in range(3):
|
|
40
|
+
try:
|
|
41
|
+
req = urllib.request.Request(CHAT_URL, data=body,
|
|
42
|
+
headers={"Authorization": f"Bearer {CHAT_KEY}", "Content-Type": "application/json"})
|
|
43
|
+
return json.loads(urllib.request.urlopen(req, timeout=timeout).read())["choices"][0]["message"]["content"]
|
|
44
|
+
except (urllib.error.URLError, TimeoutError, OSError, KeyError) as e:
|
|
45
|
+
if a < 2: time.sleep(1.0*(a+1))
|
|
46
|
+
else: return ""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _q(s, sql, p=None):
|
|
50
|
+
try: return s.execute(text(sql), p or {}).fetchall()
|
|
51
|
+
except Exception:
|
|
52
|
+
try: s.rollback()
|
|
53
|
+
except Exception: pass
|
|
54
|
+
return []
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def feature_gold(theme, k=20):
|
|
58
|
+
"""该 feature 的真业务实体集(BF5/BF6 的 gold)。"""
|
|
59
|
+
s = SessionLocal()
|
|
60
|
+
rows = _q(s, "SELECT canonical, cn FROM entities WHERE (canonical ILIKE :p OR cn ILIKE :p) "
|
|
61
|
+
"AND type IN ('CONTROLLER','SERVICE','TABLE','COLUMN','FUNCTION') LIMIT :n",
|
|
62
|
+
{"p": f"%{theme}%", "n": k})
|
|
63
|
+
s.close()
|
|
64
|
+
return [(c, n) for c, n in rows if c]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def extract_names(ans):
|
|
68
|
+
out = set()
|
|
69
|
+
for line in ans.splitlines():
|
|
70
|
+
line = _LINE_CLEAN.sub("", line).strip()
|
|
71
|
+
if line and len(line) <= 60:
|
|
72
|
+
m = _TOK.findall(line)
|
|
73
|
+
if m: out.add(m[0])
|
|
74
|
+
return out
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def feature_precision(ans, gold):
|
|
78
|
+
"""feature 保真:列出的 ∈ 该feature gold 比例(非任意真实体)。"""
|
|
79
|
+
cands = extract_names(ans)
|
|
80
|
+
if not cands: return 0.0, 0
|
|
81
|
+
gold_canon = {c for c, _ in gold}
|
|
82
|
+
hit = sum(1 for c in cands if c in gold_canon)
|
|
83
|
+
# 也算 cn 命中(ans 文本含 gold cn)
|
|
84
|
+
# precision = 命中gold的候选 / 总候选
|
|
85
|
+
feat_hit = 0
|
|
86
|
+
for c in cands:
|
|
87
|
+
if c in gold_canon:
|
|
88
|
+
feat_hit += 1
|
|
89
|
+
return round(feat_hit / len(cands), 3), len(cands)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def run():
|
|
93
|
+
rep = {"features": []}
|
|
94
|
+
for feat, theme in FEATURES:
|
|
95
|
+
gold = feature_gold(theme, 20)
|
|
96
|
+
gold_ctx = "\n".join("%s (%s)" % (c, n) for c, n in gold) or "(无)"
|
|
97
|
+
# BF6 search
|
|
98
|
+
b_search = chat(f"找 ICS 系统「{feat}」相关的具体对象(类/表/字段/接口),逐行列出,勿编造。")
|
|
99
|
+
s_search = chat(f"找 ICS 系统「{feat}」相关对象。知识图谱检索到(均真实):\n{gold_ctx}\n请把检索结果实体全部逐行列出,直接用名称,勿编造。")
|
|
100
|
+
bP_s, bN_s = feature_precision(b_search, gold)
|
|
101
|
+
sP_s, sN_s = feature_precision(s_search, gold)
|
|
102
|
+
# BF5 code
|
|
103
|
+
b_code = chat(f"给「{feat}」加功能,逐行列出需修改的代码类/方法名,勿编造。")
|
|
104
|
+
s_code = chat(f"给「{feat}」加功能。get_impact 检索到真实实体:\n{gold_ctx}\n请把检索结果实体全部逐行列出,直接用名称,勿编造。")
|
|
105
|
+
bP_c, bN_c = feature_precision(b_code, gold)
|
|
106
|
+
sP_c, sN_c = feature_precision(s_code, gold)
|
|
107
|
+
rep["features"].append({"feature": feat, "gold_n": len(gold),
|
|
108
|
+
"BF6_bare": bP_s, "BF6_scaffold": sP_s,
|
|
109
|
+
"BF5_bare": bP_c, "BF5_scaffold": sP_c})
|
|
110
|
+
print(" %s(gold=%d): BF6 search 相关率 bare=%.0f%%→scaff=%.0f%% | BF5 code 精准 bare=%.0f%%→scaff=%.0f%%" % (
|
|
111
|
+
feat, len(gold), bP_s*100, sP_s*100, bP_c*100, sP_c*100))
|
|
112
|
+
n = len(FEATURES) or 1
|
|
113
|
+
rep["agg"] = {
|
|
114
|
+
"BF6_bare": round(sum(f["BF6_bare"] for f in rep["features"])/n, 3),
|
|
115
|
+
"BF6_scaffold": round(sum(f["BF6_scaffold"] for f in rep["features"])/n, 3),
|
|
116
|
+
"BF5_bare": round(sum(f["BF5_bare"] for f in rep["features"])/n, 3),
|
|
117
|
+
"BF5_scaffold": round(sum(f["BF5_scaffold"] for f in rep["features"])/n, 3),
|
|
118
|
+
}
|
|
119
|
+
return rep
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def main():
|
|
123
|
+
import argparse
|
|
124
|
+
ap = argparse.ArgumentParser()
|
|
125
|
+
ap.add_argument("--json", action="store_true")
|
|
126
|
+
args = ap.parse_args()
|
|
127
|
+
r = run()
|
|
128
|
+
a = r["agg"]
|
|
129
|
+
if args.json:
|
|
130
|
+
print(json.dumps(r, ensure_ascii=False, indent=2))
|
|
131
|
+
return
|
|
132
|
+
print("\n## FW10 BF5/BF6 feature-scoped 业务保真飞轮(列的是【该feature】真实体,非任意真实体)")
|
|
133
|
+
print("| 指标 | bare | +该feature gold接地 | 目标 |")
|
|
134
|
+
print("|---|---|---|---|")
|
|
135
|
+
print("| BF6 search feature相关率 | %.0f%% | %.0f%% | ≥85%% |" % (a["BF6_bare"]*100, a["BF6_scaffold"]*100))
|
|
136
|
+
print("| BF5 code feature精准 | %.0f%% | %.0f%% | ≥85%% |" % (a["BF5_bare"]*100, a["BF5_scaffold"]*100))
|
|
137
|
+
b6 = a["BF6_scaffold"] >= 0.85; b5 = a["BF5_scaffold"] >= 0.85
|
|
138
|
+
print("\nBF6达标?" , "✓" if b6 else "✗", "| BF5达标?", "✓" if b5 else "✗",
|
|
139
|
+
"| 不达标续转(更强feature接地/拒非feature实体)")
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
if __name__ == "__main__":
|
|
143
|
+
main()
|