更新
This commit is contained in:
@@ -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("古籍参考:本次未记录可核查的古籍片段")
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user