Skip to content

Commit 6687d77

Browse files
committed
feat: rebuild alignment pipeline and upgrade retrieval/ui flow
1 parent d185402 commit 6687d77

6 files changed

Lines changed: 487 additions & 48 deletions

File tree

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,23 @@ certbot --nginx -d your-domain.com
391391

392392
## 📋 更新日志
393393

394+
### 2026-03-05: 页面对齐重建 + 交互链路加固
395+
396+
**数据底座重建(可回滚)**
397+
- ✅ 使用 `33_rebuild_mineru_chunks_from_content_list.py``page_idx` 真值)重建教材 chunks,替代历史启发式页码修复
398+
- ✅ 重建参数固定:`--include-discarded --max-chars 750 --min-chars 140`
399+
- ✅ 对齐闸门从基线错配率 `2.089% (259/12400)` 降至 `0.138% (12/8690)``risky_count``13` 降至 `0`
400+
- ✅ 重建前执行物理备份与审计快照(`logs/migration_baseline/backups/` + `snapshots/`
401+
- ✅ 保全 `search_logs` / `ai_batch_jobs`:重建后行数保持不变(用于热门与检索行为分析)
402+
- ✅ 新增 FAISS 一致性闸门:若向量数量与 DB 行数不一致,自动降级禁用向量检索,避免错 ID 召回
403+
404+
**前端与后端改造**
405+
- ✅ 原文查看容错窗口从 `±2` 升级为 `±4`(总计最多 9 页)
406+
- ✅ 搜索结果新增“精确命中 / 语义召回”双通道标识与“图文来源可信度 + 关联路径”视图
407+
- ✅ 关于页新增“反馈问题/提交建议”按钮,直达 GitHub issue 创建页
408+
- ✅ 底部文案改为“前端重构版本”动态显示(`frontend/assets/version.json`),便于核验前端是否更新
409+
- ✅ AI 跨学科解读升级为“有记忆对话流”,支持多轮追问与一键复制全部对话
410+
394411
### 2026-03-04: 技术栈全面升级
395412

396413
**AI与检索**

backend/main.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,29 @@ def _resolve_data_asset(filename: str) -> Path:
8888
print(f"Failed to load FAISS/model: {e}", flush=True)
8989
import traceback; traceback.print_exc()
9090

91+
92+
def _expected_vector_rows() -> Optional[int]:
93+
try:
94+
con = sqlite3.connect(DB_PATH)
95+
row = con.execute(
96+
"SELECT COUNT(*) FROM chunks WHERE source != 'gaokao' AND text IS NOT NULL AND text != ''"
97+
).fetchone()
98+
con.close()
99+
return int(row[0]) if row else None
100+
except Exception:
101+
return None
102+
103+
104+
if faiss_index is not None:
105+
expected_rows = _expected_vector_rows()
106+
if expected_rows is not None and faiss_index.ntotal != expected_rows:
107+
print(
108+
f"FAISS disabled: index vectors={faiss_index.ntotal}, expected_rows={expected_rows}. "
109+
"Rebuild textbook_chunks.index to re-enable dense retrieval.",
110+
flush=True,
111+
)
112+
faiss_index = None
113+
91114
# ── Jieba custom dictionary ──────────────────────────────────────────
92115
try:
93116
import jieba
@@ -226,6 +249,7 @@ def search(
226249
d = dict(r)
227250
# Add basic highlighting for the LIKE snippet
228251
d['snippet'] = d['snippet'].replace(clean_q, f"<mark>{clean_q}</mark>")
252+
d["match_channel"] = "exact"
229253
rows.append(d)
230254
existing_ids.add(d['id'])
231255

@@ -252,7 +276,9 @@ def search(
252276

253277
for r in fts_rows:
254278
if r['id'] not in existing_ids:
255-
rows.append(dict(r))
279+
d = dict(r)
280+
d["match_channel"] = "fts"
281+
rows.append(d)
256282
existing_ids.add(r['id'])
257283

258284
# 3. Sort by rank (exact matches get -100.0 so they appear first) and trim to limit
@@ -290,6 +316,7 @@ def search(
290316
"text": text[:2000],
291317
"image_count": img_count,
292318
"source": r["source"] or "mineru",
319+
"match_channel": r.get("match_channel", "fts"),
293320
"page_url": page_url,
294321
"page_num": page_num,
295322
"total_pages": bm_info.get("pages", 0),
@@ -1631,7 +1658,7 @@ def health():
16311658
def page_image(
16321659
book_key: str = Query(..., description="book_key from search result"),
16331660
page: int = Query(..., ge=0, description="Page number (0-indexed)"),
1634-
context: int = Query(2, ge=0, le=5, description="Number of context pages before/after"),
1661+
context: int = Query(4, ge=0, le=8, description="Number of context pages before/after"),
16351662
):
16361663
"""Return R2 CDN URLs for a page and surrounding context pages."""
16371664
# Find the book in book_map

0 commit comments

Comments
 (0)