This commit is contained in:
Your Name
2026-10-09 09:36:17 +08:00
parent 88b94c2fc6
commit 51d8fd409e
727 changed files with 3753398 additions and 102 deletions
@@ -5,6 +5,7 @@ from __future__ import annotations
import re
from collections.abc import Mapping
from typing import Any
from urllib.parse import unquote
_REPORT_SOURCE_COUNTS = (
("diagnosis_count", "诊单"),
@@ -25,6 +26,12 @@ _ANCIENT_BOOKS_COMMIT = "db0155dc7c42b9c6b3736896661f317c7110038f"
_ANCIENT_BOOKS_URL = "https://github.com/xiaopangxia/TCM-Ancient-Books"
def _source_text(value: Any, limit: int) -> str:
"""Keep displayed source metadata brief and free of repository links."""
text = re.sub(r"https://github\.com(?:/[^\s,。;、」)》\]]*)?", "", str(value or ""))
return " ".join(text.split())[:limit]
def report_provenance_lines(raw: Any) -> tuple[str, ...]:
"""Describe recorded inputs; never turn model prose into a claimed citation."""
report = raw if isinstance(raw, Mapping) else {}
@@ -53,16 +60,23 @@ def report_provenance_lines(raw: Any) -> tuple[str, ...]:
knowledge = report.get("knowledge_source")
url = knowledge.get("url") if isinstance(knowledge, Mapping) else None
source_match = re.fullmatch(
legacy_source_match = re.fullmatch(
re.escape(_NIHAIXIA_SOURCE_URL) + r"/blob/([0-9a-f]{40})/SKILL\.md",
url,
) if isinstance(url, str) else None
if isinstance(knowledge, Mapping) and source_match is not None and source_match.group(1) == _NIHAIXIA_COMMIT:
commit = knowledge.get("commit")
commit_text = commit[:12] if isinstance(commit, str) and commit == _NIHAIXIA_COMMIT else ""
valid_knowledge = isinstance(knowledge, Mapping) and knowledge.get("commit") == _NIHAIXIA_COMMIT and (
(url in (None, "") and knowledge.get("path") == "SKILL.md")
or (
legacy_source_match is not None
and legacy_source_match.group(1) == _NIHAIXIA_COMMIT
and knowledge.get("path") in (None, "SKILL.md")
)
)
if valid_knowledge:
lines.append(
"知识参考:倪海厦 skill · SKILL.md"
+ (f"(commit {commit_text})" if commit_text else "")
"知识参考:倪海厦临床参考 Skill;本地资料:"
"server/knowledge/nihaixia-skill/SKILL.md"
+ f"(版本 {_NIHAIXIA_COMMIT[:12]})"
)
sections = knowledge.get("sections")
allowed_sections = {"六经速查表", "六经辨证诊断公式", "七步走辨证思维模式"}
@@ -70,36 +84,55 @@ def report_provenance_lines(raw: Any) -> tuple[str, ...]:
isinstance(item, str) and item in allowed_sections for item in sections
):
lines.append("参考章节:" + "、".join(sections))
lines.append("原文:" + url)
else:
lines.append("知识参考:此报告未记录所用知识资料版本")
ancient_sources = report.get("ancient_book_sources")
shown_urls: set[str] = set()
shown_sources: set[tuple[str, int]] = set()
if isinstance(ancient_sources, (list, tuple)):
for source in ancient_sources[:12]:
if not isinstance(source, Mapping):
if not isinstance(source, Mapping) or source.get("commit") != _ANCIENT_BOOKS_COMMIT:
continue
ancient_url = source.get("url")
if not isinstance(ancient_url, str) or ancient_url in shown_urls:
filename = source.get("path")
line_number = source.get("line")
if ancient_url not in (None, ""):
legacy_match = re.fullmatch(
re.escape(_ANCIENT_BOOKS_URL)
+ r"/blob/"
+ _ANCIENT_BOOKS_COMMIT
+ r"/([^/#?]+\.txt)#L([1-9]\d{0,8})",
ancient_url,
) if isinstance(ancient_url, str) else None
if legacy_match is None:
continue
legacy_filename = unquote(legacy_match.group(1))
legacy_line = int(legacy_match.group(2))
if filename not in (None, legacy_filename) or line_number not in (None, legacy_line):
continue
filename, line_number = legacy_filename, legacy_line
if not (
isinstance(filename, str)
and re.fullmatch(r"[^/\\\x00-\x1f]{1,255}\.txt", filename)
and type(line_number) is int
and 0 < line_number < 1_000_000_000
):
continue
if re.fullmatch(
re.escape(_ANCIENT_BOOKS_URL)
+ r"/blob/"
+ _ANCIENT_BOOKS_COMMIT
+ r"/[^/#?]+\.txt#L[1-9]\d*",
ancient_url,
) is None or source.get("commit") != _ANCIENT_BOOKS_COMMIT:
source_key = (filename, line_number)
if source_key in shown_sources:
continue
shown_urls.add(ancient_url)
title = str(source.get("title") or "古籍原文")[:60]
chapter = str(source.get("chapter") or "")[:60]
shown_sources.add(source_key)
title = _source_text(source.get("title"), 60) or "古籍原文"
chapter = _source_text(source.get("chapter"), 60)
excerpt = _source_text(source.get("excerpt"), 120)
lines.append(
"古籍参考:《" + title + "》"
+ ("「" + chapter + "」" if chapter else "")
+ ";原文:" + ancient_url
+ f";本地资料:server/knowledge/tcm-ancient-books/{filename}"
+ f" 第{line_number}行(版本 {_ANCIENT_BOOKS_COMMIT[:12]})"
+ (";摘录:" + excerpt if excerpt else "")
)
if not shown_urls and "-ancient-" in str(
if not shown_sources and "-ancient-" in str(
report.get("prompt_version") or report.get("context_version") or ""
):
lines.append("古籍参考:本次未记录可核查的古籍片段")
+2 -2
View File
@@ -1668,8 +1668,8 @@ def test_structured_report_shows_recorded_patient_and_skill_sources(
lines = [label.text() for label in card.findChildren(QLabel)]
assert any("#501" in line and "#502" in line for line in lines)
assert any("诊单 2 条" in line and "血糖血压记录 3 条" in line for line in lines)
assert any("commit 270e94e637c4" in line for line in lines)
assert any("/blob/270e94e637c4249dc411e54ac6715f21247de3cb/SKILL.md" in line for line in lines)
assert any("server/knowledge/nihaixia-skill/SKILL.md" in line and "版本 270e94e637c4" in line for line in lines)
assert all("https://github.com" not in line for line in lines)
bubble.deleteLater()
@@ -1351,11 +1351,14 @@ def test_reception_report_displays_recorded_sources(application: QApplication) -
assert "#501" in dialog.source_label.text()
assert "历史处方 2 条" in dialog.source_label.text()
assert "六经速查表" in dialog.source_label.text()
assert "server/knowledge/nihaixia-skill/SKILL.md" in dialog.source_label.text()
assert "https://github.com" not in dialog.source_label.text()
page = ReceptionPage(object(), PermissionSet([]))
page._render_ai_analysis_payload(payload, "qwen")
assert "报告出处" in page.ai_source_label.text()
assert "#501" in page.ai_source_label.text()
assert "https://github.com" not in page.ai_source_label.text()
dialog.close()
page.close()
+44 -1
View File
@@ -17,13 +17,56 @@ def test_recorded_ancient_book_reference_has_title_chapter_and_pinned_line() ->
{
"title": "测试古籍",
"chapter": "消渴篇",
"path": "123-测试古籍.txt",
"line": 42,
"excerpt": "消渴者,当辨其证。",
"url": _URL,
"commit": _COMMIT,
}
],
}
)
assert any("《测试古籍》「消渴篇」" in line and _URL in line for line in lines)
assert any(
"《测试古籍》「消渴篇」" in line
and "server/knowledge/tcm-ancient-books/123-测试古籍.txt 第42行" in line
and "版本 db0155dc7c42" in line
and "摘录:消渴者,当辨其证。" in line
for line in lines
)
assert "https://github.com" not in "\n".join(lines)
def test_locally_bundled_sources_render_without_external_urls() -> None:
lines = report_provenance_lines({
"prompt_version": "patient-longitudinal-report-nihaixia-ancient-v4",
"knowledge_source": {
"commit": "270e94e637c4249dc411e54ac6715f21247de3cb",
"path": "SKILL.md",
"url": "",
},
"ancient_book_sources": [{
"title": "测试古籍",
"chapter": "消渴篇",
"path": "123-测试古籍.txt",
"line": 42,
"excerpt": "消渴者,当辨其证。",
"commit": _COMMIT,
"url": "",
}],
})
assert any("server/knowledge/nihaixia-skill/SKILL.md" in line for line in lines)
assert any("server/knowledge/tcm-ancient-books/123-测试古籍.txt 第42行" in line for line in lines)
assert "https://github.com" not in "\n".join(lines)
def test_ancient_book_reference_rejects_conflicting_local_metadata() -> None:
lines = report_provenance_lines({
"ancient_book_sources": [
{"title": "测试古籍", "path": "别的书.txt", "line": 42, "url": _URL, "commit": _COMMIT},
{"title": "测试古籍", "path": "123-测试古籍.txt", "line": 43, "url": _URL, "commit": _COMMIT},
],
})
assert all("古籍参考:《" not in line for line in lines)
def test_old_or_unverified_report_does_not_gain_ancient_citation() -> None: