zra-mcp 0.3.0__tar.gz
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.
- zra_mcp-0.3.0/.env.example +79 -0
- zra_mcp-0.3.0/.github/workflows/ci.yml +39 -0
- zra_mcp-0.3.0/.gitignore +58 -0
- zra_mcp-0.3.0/CHANGELOG.md +218 -0
- zra_mcp-0.3.0/CLAUDE.md +119 -0
- zra_mcp-0.3.0/DEVELOPMENT_LOG.md +8 -0
- zra_mcp-0.3.0/DEVELOPMENT_PLAN.md +148 -0
- zra_mcp-0.3.0/LICENSE +21 -0
- zra_mcp-0.3.0/PKG-INFO +436 -0
- zra_mcp-0.3.0/README.md +394 -0
- zra_mcp-0.3.0/README_zh.md +389 -0
- zra_mcp-0.3.0/docs/DEVELOPMENT_LOG.md +658 -0
- zra_mcp-0.3.0/docs/DEVELOPMENT_LOG_EN.md +488 -0
- zra_mcp-0.3.0/docs/cherry-studio-setup-en.md +593 -0
- zra_mcp-0.3.0/docs/cherry-studio-setup.md +606 -0
- zra_mcp-0.3.0/docs/test-prompts.md +451 -0
- zra_mcp-0.3.0/project_a_mcp/__init__.py +1 -0
- zra_mcp-0.3.0/project_a_mcp/server.py +1944 -0
- zra_mcp-0.3.0/pyproject.toml +76 -0
- zra_mcp-0.3.0/research_core/__init__.py +3 -0
- zra_mcp-0.3.0/research_core/parsers/__init__.py +12 -0
- zra_mcp-0.3.0/research_core/parsers/chunker.py +1014 -0
- zra_mcp-0.3.0/research_core/parsers/pdf.py +51 -0
- zra_mcp-0.3.0/research_core/parsers/section_detector.py +338 -0
- zra_mcp-0.3.0/research_core/parsers/text_cleaner.py +526 -0
- zra_mcp-0.3.0/research_core/rag/__init__.py +6 -0
- zra_mcp-0.3.0/research_core/rag/bm25_index.py +273 -0
- zra_mcp-0.3.0/research_core/rag/database.py +490 -0
- zra_mcp-0.3.0/research_core/rag/embedding.py +234 -0
- zra_mcp-0.3.0/research_core/rag/embedding_diagnostics.py +373 -0
- zra_mcp-0.3.0/research_core/rag/evaluation.py +413 -0
- zra_mcp-0.3.0/research_core/rag/indexer.py +157 -0
- zra_mcp-0.3.0/research_core/rag/logger.py +321 -0
- zra_mcp-0.3.0/research_core/rag/query_dict.json +318 -0
- zra_mcp-0.3.0/research_core/rag/query_rewriter.py +267 -0
- zra_mcp-0.3.0/research_core/rag/rendering.py +859 -0
- zra_mcp-0.3.0/research_core/rag/reranker.py +77 -0
- zra_mcp-0.3.0/research_core/rag/retriever.py +674 -0
- zra_mcp-0.3.0/research_core/rag/store.py +98 -0
- zra_mcp-0.3.0/research_core/rag/sync_state.py +101 -0
- zra_mcp-0.3.0/research_core/sources/__init__.py +5 -0
- zra_mcp-0.3.0/research_core/sources/cnki/__init__.py +25 -0
- zra_mcp-0.3.0/research_core/sources/cnki/browser.py +75 -0
- zra_mcp-0.3.0/research_core/sources/cnki/detail.py +173 -0
- zra_mcp-0.3.0/research_core/sources/cnki/exceptions.py +17 -0
- zra_mcp-0.3.0/research_core/sources/cnki/models.py +27 -0
- zra_mcp-0.3.0/research_core/sources/cnki/navigate.py +160 -0
- zra_mcp-0.3.0/research_core/sources/cnki/scripts.py +268 -0
- zra_mcp-0.3.0/research_core/sources/cnki/search.py +191 -0
- zra_mcp-0.3.0/research_core/sources/cnki/zotero_export.py +247 -0
- zra_mcp-0.3.0/research_core/sources/crossref.py +145 -0
- zra_mcp-0.3.0/research_core/sources/http_client.py +201 -0
- zra_mcp-0.3.0/research_core/sources/models.py +51 -0
- zra_mcp-0.3.0/research_core/sources/openalex.py +392 -0
- zra_mcp-0.3.0/research_core/sources/semantic_scholar.py +221 -0
- zra_mcp-0.3.0/research_core/sources/verify.py +164 -0
- zra_mcp-0.3.0/research_core/tools/__init__.py +106 -0
- zra_mcp-0.3.0/research_core/tools/admin.py +603 -0
- zra_mcp-0.3.0/research_core/tools/arguments.py +214 -0
- zra_mcp-0.3.0/research_core/tools/citation_network.py +149 -0
- zra_mcp-0.3.0/research_core/tools/cite.py +130 -0
- zra_mcp-0.3.0/research_core/tools/cnki_detail.py +44 -0
- zra_mcp-0.3.0/research_core/tools/cnki_navigate.py +85 -0
- zra_mcp-0.3.0/research_core/tools/cnki_zotero.py +68 -0
- zra_mcp-0.3.0/research_core/tools/discover_cnki.py +71 -0
- zra_mcp-0.3.0/research_core/tools/discover_online.py +270 -0
- zra_mcp-0.3.0/research_core/tools/find_related.py +788 -0
- zra_mcp-0.3.0/research_core/tools/health.py +425 -0
- zra_mcp-0.3.0/research_core/tools/inspect_index.py +292 -0
- zra_mcp-0.3.0/research_core/tools/manage.py +819 -0
- zra_mcp-0.3.0/research_core/tools/read.py +303 -0
- zra_mcp-0.3.0/research_core/tools/reading_note.py +120 -0
- zra_mcp-0.3.0/research_core/tools/reading_status.py +169 -0
- zra_mcp-0.3.0/research_core/tools/recommend.py +251 -0
- zra_mcp-0.3.0/research_core/tools/review.py +192 -0
- zra_mcp-0.3.0/research_core/tools/search.py +634 -0
- zra_mcp-0.3.0/research_core/tools/suggest_tags.py +173 -0
- zra_mcp-0.3.0/research_core/utils.py +72 -0
- zra_mcp-0.3.0/research_core/zotero/__init__.py +6 -0
- zra_mcp-0.3.0/research_core/zotero/client.py +845 -0
- zra_mcp-0.3.0/research_core/zotero/models.py +38 -0
- zra_mcp-0.3.0/scripts/audit_index.py +891 -0
- zra_mcp-0.3.0/scripts/benchmark_chunk_size.py +369 -0
- zra_mcp-0.3.0/scripts/benchmark_e2e.py +198 -0
- zra_mcp-0.3.0/scripts/benchmark_int8.py +113 -0
- zra_mcp-0.3.0/scripts/benchmark_output_format.py +130 -0
- zra_mcp-0.3.0/scripts/compare_output_formats.py +314 -0
- zra_mcp-0.3.0/scripts/generate_eval_queries.py +279 -0
- zra_mcp-0.3.0/scripts/index_library.py +47 -0
- zra_mcp-0.3.0/scripts/index_sample.py +117 -0
- zra_mcp-0.3.0/scripts/publish.sh +90 -0
- zra_mcp-0.3.0/scripts/run_evaluation.py +173 -0
- zra_mcp-0.3.0/scripts/test_names.py +30 -0
- zra_mcp-0.3.0/tests/__init__.py +0 -0
- zra_mcp-0.3.0/tests/core/__init__.py +0 -0
- zra_mcp-0.3.0/tests/core/test_chunker.py +30 -0
- zra_mcp-0.3.0/tests/eval_queries.json +554 -0
- zra_mcp-0.3.0/tests/mcp/__init__.py +0 -0
- zra_mcp-0.3.0/tests/mcp/test_cnki.py +43 -0
- zra_mcp-0.3.0/tests/mcp/test_scenarios.py +606 -0
- zra_mcp-0.3.0/tests/mcp/test_tools.py +392 -0
- zra_mcp-0.3.0/tests/unit/test_cnki_helpers.py +291 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# ── Zotero ──
|
|
2
|
+
# Local mode: reads from Zotero desktop app (fast, no auth needed)
|
|
3
|
+
ZOTERO_LOCAL=true
|
|
4
|
+
# Web API credentials (required for writes and hybrid mode)
|
|
5
|
+
# Get your key at https://www.zotero.org/settings/keys
|
|
6
|
+
ZOTERO_LIBRARY_ID=0
|
|
7
|
+
ZOTERO_LIBRARY_TYPE=user
|
|
8
|
+
ZOTERO_API_KEY=
|
|
9
|
+
# Hybrid mode: set ZOTERO_LOCAL=true AND provide ZOTERO_API_KEY + ZOTERO_LIBRARY_ID
|
|
10
|
+
# → reads stay local (fast), writes go through web API (writable)
|
|
11
|
+
#
|
|
12
|
+
# Note: this is an MCP *server* — the LLM is supplied by your MCP client
|
|
13
|
+
# (Cursor / Claude / Cherry Studio / …), so no OpenAI/Anthropic key is needed here.
|
|
14
|
+
|
|
15
|
+
# ── Embedding ──
|
|
16
|
+
# Backend selection (auto / onnx_int8 / sentence_transformers):
|
|
17
|
+
# auto — ONNX INT8 if available, otherwise FP32 (default)
|
|
18
|
+
# onnx_int8 — ONNX Runtime INT8 quantized (~347MB, 2-3x faster, 4x smaller)
|
|
19
|
+
# sentence_transformers — Original FP32 PyTorch (~2.3GB, highest precision)
|
|
20
|
+
# ONNX INT8 is recommended for most users — it is 2-3x faster on CPU,
|
|
21
|
+
# uses 4x less disk space, and has <2% retrieval precision impact.
|
|
22
|
+
# EMBEDDING_BACKEND=auto
|
|
23
|
+
|
|
24
|
+
# Model name (used by sentence_transformers backend only; ONNX INT8 uses a
|
|
25
|
+
# pre-quantized model automatically).
|
|
26
|
+
EMBEDDING_MODEL=BAAI/bge-m3
|
|
27
|
+
# HuggingFace mirror for users in China (uncomment if download is slow)
|
|
28
|
+
# HF_ENDPOINT=https://hf-mirror.com
|
|
29
|
+
|
|
30
|
+
# Cap embedding sequence length to bound memory (chunks are short; 1024 is
|
|
31
|
+
# ample and prevents GPU/MPS out-of-memory on pathological long inputs).
|
|
32
|
+
# EMBEDDING_MAX_SEQ_LEN=1024
|
|
33
|
+
|
|
34
|
+
# ── Tables & figures ──
|
|
35
|
+
# Tables and figures are indexed as lightweight caption-anchored records (where
|
|
36
|
+
# they are + caption + rough content), not structured into cells. No setting is
|
|
37
|
+
# needed. For true table structuring, preprocess your PDFs with a visual parser
|
|
38
|
+
# (docling / open-parse / unstructured) — see the README "Tables & figures" note.
|
|
39
|
+
|
|
40
|
+
# ── Reranker (optional, improves search precision) ──
|
|
41
|
+
# cross-encoder model for re-scoring retrieved chunks
|
|
42
|
+
# Default: cross-encoder/ms-marco-MiniLM-L-6-v2 (~80MB, auto-downloaded)
|
|
43
|
+
# Set to "none" to disable reranking entirely
|
|
44
|
+
RERANKER_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2
|
|
45
|
+
|
|
46
|
+
# ── ChromaDB ──
|
|
47
|
+
CHROMA_PERSIST_DIR=.chroma_db
|
|
48
|
+
|
|
49
|
+
# ── Text Cleaning ──
|
|
50
|
+
# Strip journal boilerplate (headers, footers, article-info blocks) before
|
|
51
|
+
# chunking. 52 blacklist rules cover EN+CN journals. Set to "false" to disable.
|
|
52
|
+
ZRA_CLEAN_ENABLED=true
|
|
53
|
+
|
|
54
|
+
# ── Server Behavior ──
|
|
55
|
+
# Auto-sync index on MCP server startup (set to "false" to disable)
|
|
56
|
+
ZRA_AUTO_SYNC=true
|
|
57
|
+
|
|
58
|
+
# ── Online literature search (optional) ──
|
|
59
|
+
# Semantic Scholar: higher rate limits — https://www.semanticscholar.org/product/api
|
|
60
|
+
SEMANTIC_SCHOLAR_API_KEY=
|
|
61
|
+
# OpenAlex polite pool — your contact email
|
|
62
|
+
OPENALEX_MAILTO=
|
|
63
|
+
# Unpaywall + OA PDF waterfall contact email
|
|
64
|
+
UNPAYWALL_EMAIL=
|
|
65
|
+
# CORE repository full-text — https://core.ac.uk/services/api
|
|
66
|
+
CORE_API_KEY=
|
|
67
|
+
|
|
68
|
+
# ── CNKI / 知网 (optional, disabled by default) ──
|
|
69
|
+
# CNKI browser automation via Chrome DevTools Protocol (inspired by cookjohn/cnki-skills).
|
|
70
|
+
# Only needed when you want to search Chinese journal papers.
|
|
71
|
+
# Setup: see README.md "CNKI 中文文献检索" section.
|
|
72
|
+
CNKI_ENABLED=false
|
|
73
|
+
# Start Chrome with: --remote-debugging-port=9222, then log in to CNKI.
|
|
74
|
+
CNKI_CDP_URL=http://127.0.0.1:9222
|
|
75
|
+
# Alternative: Playwright storage state JSON exported after manual login
|
|
76
|
+
# CNKI_STORAGE_STATE=.cnki_storage_state.json
|
|
77
|
+
# CNKI_HEADLESS=false
|
|
78
|
+
# CNKI_USE_CHROME=true
|
|
79
|
+
# CNKI_TIMEOUT_MS=45000
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ci-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
lint-and-test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.11", "3.12"]
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
cache: pip
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: |
|
|
30
|
+
python -m pip install --upgrade pip
|
|
31
|
+
pip install -e ".[dev]"
|
|
32
|
+
|
|
33
|
+
- name: Lint (ruff)
|
|
34
|
+
run: ruff check .
|
|
35
|
+
|
|
36
|
+
- name: Unit + core tests
|
|
37
|
+
# tests/mcp are integration tests that need a live Zotero + index, so
|
|
38
|
+
# they are intentionally excluded from CI.
|
|
39
|
+
run: pytest tests/core tests/unit -q
|
zra_mcp-0.3.0/.gitignore
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
*.egg
|
|
8
|
+
.venv/
|
|
9
|
+
|
|
10
|
+
# Environment / credentials (contain API keys & tokens)
|
|
11
|
+
.env
|
|
12
|
+
.pypirc
|
|
13
|
+
*.pypirc
|
|
14
|
+
|
|
15
|
+
# IDE
|
|
16
|
+
.vscode/
|
|
17
|
+
.idea/
|
|
18
|
+
.cursor/
|
|
19
|
+
.claude/
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
|
|
23
|
+
# ChromaDB / Vector store
|
|
24
|
+
.chroma_db/
|
|
25
|
+
|
|
26
|
+
# Sync state + retrieval logs (generated per-machine, inside .chroma_db/)
|
|
27
|
+
_sync_state.json
|
|
28
|
+
_retrieval_log.jsonl
|
|
29
|
+
_retrieval_log.idx
|
|
30
|
+
|
|
31
|
+
# User-defined query synonyms (per-machine)
|
|
32
|
+
query_dict_user.json
|
|
33
|
+
|
|
34
|
+
# Evaluation baseline (per-machine, depends on local library content)
|
|
35
|
+
tests/eval_baseline.json
|
|
36
|
+
|
|
37
|
+
# Ruff
|
|
38
|
+
.ruff_cache/
|
|
39
|
+
|
|
40
|
+
# uv
|
|
41
|
+
.local/
|
|
42
|
+
uv.lock
|
|
43
|
+
|
|
44
|
+
# pytest
|
|
45
|
+
.pytest_cache/
|
|
46
|
+
htmlcov/
|
|
47
|
+
.coverage
|
|
48
|
+
|
|
49
|
+
# Docs (internal guides, not for distribution)
|
|
50
|
+
docs/internal/
|
|
51
|
+
|
|
52
|
+
# Development progress / roadmap (internal)
|
|
53
|
+
DEVELOPMENT.md
|
|
54
|
+
ARCHITECTURE.md
|
|
55
|
+
|
|
56
|
+
# OS
|
|
57
|
+
.DS_Store
|
|
58
|
+
Thumbs.db
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **BM25 sparse keyword index on chunk texts** — `rank_bm25` with CJK-aware
|
|
12
|
+
tokenizer (character unigrams+bigrams for CN, alpha words for EN). Two-way
|
|
13
|
+
RRF fusion: BM25 (lexical) + ChromaDB (semantic). Persists to
|
|
14
|
+
`.chroma_db/_bm25_index.pkl`. Auto-rebuilt on every sync.
|
|
15
|
+
- **Contextual chunk enrichment** — each chunk text is prepended with
|
|
16
|
+
`[Keywords: ...] [Title: ...] [Section: ...]` before embedding and BM25
|
|
17
|
+
indexing. Implements Anthropic "Contextual Retrieval" 2024 technique
|
|
18
|
+
using existing metadata — zero additional cost. Keywords are filtered
|
|
19
|
+
from Zotero tags (excludes organizational labels).
|
|
20
|
+
- **Dual-format output (JSON + Markdown context_block)** — key retrieval tools now
|
|
21
|
+
return a `context_block` field containing pre-rendered LLM-optimized Markdown
|
|
22
|
+
alongside the existing JSON items. Blockquote (>) for evidence, star ratings
|
|
23
|
+
(★★★) for relevance tiers, sentence-boundary truncation. Covers all 8
|
|
24
|
+
retrieval/insight tools: `search_papers`, `get_paper_content`,
|
|
25
|
+
`generate_review_note`, `suggest_citations`, `find_similar_papers`,
|
|
26
|
+
`find_arguments`, `generate_reading_note`, `suggest_tags`.
|
|
27
|
+
- **Relevance tiers** — each `search_papers` result now carries a `relevance_tier`
|
|
28
|
+
field ("high"/"medium"/"low") computed from Cross-Encoder score percentiles.
|
|
29
|
+
- **Full-pipeline evaluation mode** — `run_evaluation.py --full-pipeline` tests
|
|
30
|
+
the complete `search_papers()` pipeline (BM25 + CE rerank + MMR + RRF fusion),
|
|
31
|
+
not just raw semantic search. `evaluate_full_pipeline()` in evaluation.py.
|
|
32
|
+
- **Retrieval log rotation** — auto-cleans log entries older than 90 days.
|
|
33
|
+
Triggers on server startup and after each `sync_index`. Uses `f.tell()` for
|
|
34
|
+
cross-platform byte offset accuracy.
|
|
35
|
+
- **Expanded section detection** — Roman numerals (I., II.), Chapter prefix
|
|
36
|
+
(CHAPTER 1:), section symbol (§1.), letter subsections (A., B.). ~50 new
|
|
37
|
+
type classification keywords covering non-standard academic headings.
|
|
38
|
+
Number-only fallback for papers with bare numbered markers.
|
|
39
|
+
- **ONNX INT8 embedding backend** (`EMBEDDING_BACKEND=auto` / `onnx_int8`) —
|
|
40
|
+
2-3x faster, 4x smaller (347MB vs 2.3GB) embedding on CPU. Zero-config.
|
|
41
|
+
- **MMR (Maximal Marginal Relevance) diversity reranking** — chunk-level MMR
|
|
42
|
+
with per-document cap (max 3 chunks per paper) and per-document penalty.
|
|
43
|
+
Default λ=0.4 (grid-search tuned from 0.6).
|
|
44
|
+
- **Multi-layer bilingual query expansion** — 3-layer system with ~300 built-in
|
|
45
|
+
methodology term pairs, auto-extracted Zotero tags, and user-defined synonyms.
|
|
46
|
+
- **Neighbor chunk expansion** — `expand_neighbors=True` returns hit chunk ±1
|
|
47
|
+
adjacent chunk within the same section.
|
|
48
|
+
- **Min chunk size floor (200 chars)** — post-chunking merge pass eliminating
|
|
49
|
+
fragments below the FloTorch 2026 threshold for e2e accuracy.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
- **Two-way RRF fusion** — simplified from three-way (Zotero API + BM25 + Dense)
|
|
53
|
+
to two-way (BM25 + Dense). Zotero API remains for paper metadata, filters,
|
|
54
|
+
and empty query mode.
|
|
55
|
+
- **MMR diversity_weight tuned: 0.6 → 0.4** — grid search on 10 queries.
|
|
56
|
+
- **Chunk quality scoring simplified** — dropped unused heuristic fields
|
|
57
|
+
(coherence_score, information_density, boilerplate_ratio).
|
|
58
|
+
- **MCP tools: 32 → 36** with add_query_synonym, recent_retrievals,
|
|
59
|
+
retrieval_trace, and retrieval_stats.
|
|
60
|
+
- **CHUNKING_VERSION: v2.9.0 → v3.1.0-contextual-chunks**.
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
- **SQLite authors field** — was empty string, now populated from Zotero item metadata.
|
|
64
|
+
- **sync_index dead parameters** — removed unused `chunk_size` and `chunk_overlap`.
|
|
65
|
+
- **Section detection `\s*` newline bug** — `\s*` in heading patterns now replaced
|
|
66
|
+
with `[ \\t]*` to prevent greedy newline consumption causing false headings.
|
|
67
|
+
- **inspect_index pagination bug** — `len(docs)` was only the last page's count,
|
|
68
|
+
now uses `total_count` for accurate stats.
|
|
69
|
+
- **diversity_weight docstring** — corrected from 0.6 to 0.4 in both search.py
|
|
70
|
+
and server.py.
|
|
71
|
+
|
|
72
|
+
## [0.3.0] - 2026-07-06
|
|
73
|
+
|
|
74
|
+
A major RAG quality release — production-grade retrieval pipeline with text cleaning,
|
|
75
|
+
chunk quality scoring, SQLite metadata layer, section-parent context expansion,
|
|
76
|
+
embedding diagnostics, retrieval observability, and systematic evaluation.
|
|
77
|
+
|
|
78
|
+
### Added
|
|
79
|
+
|
|
80
|
+
**RAG Pipeline — Data Quality**
|
|
81
|
+
- **Text cleaning engine** (`research_core/parsers/text_cleaner.py`): 52 blacklist
|
|
82
|
+
regex rules removing journal boilerplate — EN article-info blocks, CN volume/issue
|
|
83
|
+
lines, CLC numbers, funding footers, page numbers, DOI lines. Controlled by
|
|
84
|
+
`ZRA_CLEAN_ENABLED=true` (default on). Cleaning stats reported in `sync_index`.
|
|
85
|
+
|
|
86
|
+
**RAG Pipeline — Chunk Quality**
|
|
87
|
+
- **Chunk quality scoring** (`research_core/parsers/chunker.py`, v2.9.0): 7 quality
|
|
88
|
+
fields per chunk — `coherence_score`, `information_density`, `boilerplate_ratio`,
|
|
89
|
+
`sentence_count`, `starts_with_conjunction`, `language` (zh/en/mixed), `quality_flag`
|
|
90
|
+
(good/noisy/incomplete/boilerplate). Lightweight heuristic scoring for quality-aware
|
|
91
|
+
retrieval filtering.
|
|
92
|
+
|
|
93
|
+
**RAG Pipeline — Metadata & Context**
|
|
94
|
+
- **SQLite metadata database** (`research_core/rag/database.py`): 7 relational tables
|
|
95
|
+
(`papers`, `sections`, `chunks_meta`, `figures`, `table_records`, and cross-reference
|
|
96
|
+
tables) inside `.chroma_db/papers.db`. Zero user setup — auto-created on first sync.
|
|
97
|
+
- **Section-parent context expansion** (`Retriever.expand_to_section()`): hit a chunk
|
|
98
|
+
→ fetch its entire enclosing section from SQLite + ChromaDB, providing LLM with
|
|
99
|
+
complete paragraph context instead of isolated fragments. Cache-batched.
|
|
100
|
+
- **Result enrichment** (`Retriever.enrich()`): batch-fetches paper + section metadata
|
|
101
|
+
(abstract, authors, year, DOI, keywords, section heading/type) via SQLite JOIN.
|
|
102
|
+
|
|
103
|
+
**RAG Pipeline — Diagnostics & Evaluation**
|
|
104
|
+
- **Embedding quality diagnostics** (`research_core/rag/embedding_diagnostics.py`):
|
|
105
|
+
6-phase analysis — per-paper intra-similarity, cross-paper separation ratio, outlier
|
|
106
|
+
chunk detection (centroid coherence < 0.3), chunk length-similarity Pearson
|
|
107
|
+
correlation, section-type embedding separation, automated issues + fix suggestions.
|
|
108
|
+
- **Evaluation framework** (`research_core/rag/evaluation.py`): Recall@5/10/20, MRR,
|
|
109
|
+
NDCG@10 metrics. 60 golden queries (`tests/eval_queries.json`) across direct hit,
|
|
110
|
+
cross-document, and no-answer categories. `scripts/run_evaluation.py` with
|
|
111
|
+
`--save-baseline` / `--compare` for A/B testing.
|
|
112
|
+
- **Index audit script** (`scripts/audit_index.py`): 7-phase full-library quality
|
|
113
|
+
audit — paginated scan, per-paper scoring, library coverage, noise detection,
|
|
114
|
+
embedding separation, health scoring, and actionable recommendations.
|
|
115
|
+
|
|
116
|
+
**RAG Pipeline — Observability**
|
|
117
|
+
- **Retrieval logging** (`research_core/rag/logger.py`): JSONL append-only trace
|
|
118
|
+
logging with byte-offset index. Captures: query, strategy, candidate counts,
|
|
119
|
+
reranker details, top-20 results with scores/sources, latency breakdown
|
|
120
|
+
(keyword/semantic/rerank/total). 3 new MCP tools: `recent_retrievals`,
|
|
121
|
+
`retrieval_trace` (replay by trace ID), `retrieval_stats` (aggregate analytics).
|
|
122
|
+
|
|
123
|
+
**MCP Tools**
|
|
124
|
+
- Total tool count: 32 → 35 (3 retrieval log tools: `recent_retrievals`,
|
|
125
|
+
`retrieval_trace`, `retrieval_stats`).
|
|
126
|
+
|
|
127
|
+
**Documentation**
|
|
128
|
+
- READMEs (EN/CN) updated with all new RAG features, enhanced client setup sections
|
|
129
|
+
for Claude Desktop, Cherry Studio, and Codex CLI.
|
|
130
|
+
- `DEVELOPMENT_PLAN.md` updated: Phase 0/1/2 marked complete, decision log synced.
|
|
131
|
+
- `DEVELOPMENT_LOG.md` — developer-facing detailed change log from project inception
|
|
132
|
+
to v0.3.0.
|
|
133
|
+
|
|
134
|
+
### Changed
|
|
135
|
+
|
|
136
|
+
- **Chunking overlap rewritten** (`chunker.py`, v2.8.0): sentence-based (1 sentence)
|
|
137
|
+
→ character-based (100 chars) with sentence-boundary completion. Forward-then-backward
|
|
138
|
+
search algorithm ensures overlap always captures meaningful context.
|
|
139
|
+
- **Section detection** (`section_detector.py`): IMRaD classification via regex heading
|
|
140
|
+
patterns (EN numbered "1. Introduction", CN "一、引言"). Quality-aware — skips
|
|
141
|
+
boilerplate/incomplete chunks for heading detection.
|
|
142
|
+
- **Retriever search** now auto-enriches results with paper + section metadata from
|
|
143
|
+
SQLite (zero latency cost — single JOIN). `expand_context` parameter enables
|
|
144
|
+
section-parent context expansion.
|
|
145
|
+
- **`search_papers`** emits JSONL retrieval trace on every call with full latency
|
|
146
|
+
breakdown.
|
|
147
|
+
- **Architecture**: `research_core/rag/` now includes `database.py`, `evaluation.py`,
|
|
148
|
+
`logger.py`, `embedding_diagnostics.py`.
|
|
149
|
+
- Removed emoji from all terminal output for Windows GBK compatibility.
|
|
150
|
+
|
|
151
|
+
### Fixed
|
|
152
|
+
|
|
153
|
+
- Sentence-boundary overlap algorithm: forward-then-backward search now correctly
|
|
154
|
+
finds sentence boundaries within the overlap region. Previous backward-only search
|
|
155
|
+
missed boundaries, producing only 1% overlap for English text.
|
|
156
|
+
- Syntax errors in `search.py` from duplicate `matched_passage`/`matched_page` lines
|
|
157
|
+
after edit.
|
|
158
|
+
- `.claude/` directory added to `.gitignore`.
|
|
159
|
+
|
|
160
|
+
## [0.2.0] - 2026-06-11
|
|
161
|
+
|
|
162
|
+
A large reliability- and productization-focused release. The project is now a
|
|
163
|
+
standalone MCP server (no agent scaffold) with 32 single-intent tools.
|
|
164
|
+
|
|
165
|
+
### Added
|
|
166
|
+
- **Standalone MCP server** exposing 32 tools across Discover / Read / Write /
|
|
167
|
+
Cite / Insight / Admin, each mapping to one user intent and composing via `item_key`.
|
|
168
|
+
- **`expand_citation_network`** — forward/backward citation-graph expansion via
|
|
169
|
+
OpenAlex, with multi-seed DOI support.
|
|
170
|
+
- **`find_related_literature`** — one call runs 5 parallel strategies
|
|
171
|
+
(Corpus-First, keyword, citation network, S2 recommendations, OpenAlex related
|
|
172
|
+
works) with three-index verification.
|
|
173
|
+
- **Table & figure cross-referencing** — prose that cites "Table 3 / Figure 2"
|
|
174
|
+
is linked to caption-anchored table/figure records, resolved together in
|
|
175
|
+
`get_paper_content` (`referenced_tables` / `referenced_figures`).
|
|
176
|
+
- **CJK-aware chunking** — sentence splitting and soft-wrap repair so Chinese
|
|
177
|
+
text is no longer cut mid-word.
|
|
178
|
+
- Shared HTTP client with global concurrency cap, per-host rate limiting,
|
|
179
|
+
retry/backoff, and a short-TTL response cache.
|
|
180
|
+
- Configurable `EMBEDDING_MAX_SEQ_LEN` (bounds GPU/MPS memory) and `HF_ENDPOINT`
|
|
181
|
+
(HuggingFace mirror, e.g. for users in China).
|
|
182
|
+
- Bilingual README and a Cherry Studio setup guide (English + Chinese) aimed at
|
|
183
|
+
non-developers.
|
|
184
|
+
|
|
185
|
+
### Changed
|
|
186
|
+
- **Tables and figures are now caption-anchored records** instead of being parsed
|
|
187
|
+
into structured cells. Reliable table structuring is a vision problem;
|
|
188
|
+
geometric/line-based detection produced garbage on borderless academic tables
|
|
189
|
+
and mis-segmented multi-column prose. Table *values* stay searchable; users who
|
|
190
|
+
need true structure are pointed to docling / open-parse / unstructured.
|
|
191
|
+
- Hardened MCP tools: write operations are dry-run by default and require explicit
|
|
192
|
+
confirmation; responses are size-capped to protect the LLM context window;
|
|
193
|
+
errors return structured bilingual diagnostics.
|
|
194
|
+
- Improved RAG recall and speed; thread-safe lazy initialization of Zotero client,
|
|
195
|
+
retriever, and indexer.
|
|
196
|
+
- Incremental index sync by default (Zotero version tracking); auto full rebuild
|
|
197
|
+
when the embedding model or chunking version changes.
|
|
198
|
+
|
|
199
|
+
### Removed
|
|
200
|
+
- Built-in structured table extraction (PyMuPDF "lite" mode + Table Transformer
|
|
201
|
+
"ml" mode), the `[tables]` optional extra, and `table_ml.py`.
|
|
202
|
+
- Legacy agent scaffold (the project is MCP-server only).
|
|
203
|
+
|
|
204
|
+
### Fixed
|
|
205
|
+
- Correct Zotero item filtering and ChromaDB `search_ef` modification.
|
|
206
|
+
- Hard chunk-size cap to prevent embedding out-of-memory on pathological inputs.
|
|
207
|
+
- Unit tests updated for the shared HTTP client refactor.
|
|
208
|
+
|
|
209
|
+
## [0.1.1] - earlier
|
|
210
|
+
|
|
211
|
+
- Initial public iteration: literature search, RAG pipeline, reading analysis,
|
|
212
|
+
citation management, review/reading-note generation, tag suggestions, and the
|
|
213
|
+
first Cherry Studio setup guide.
|
|
214
|
+
|
|
215
|
+
[Unreleased]: https://github.com/qiobn/zotero-research-assistant/compare/v0.3.0...main
|
|
216
|
+
[0.3.0]: https://github.com/qiobn/zotero-research-assistant/releases/tag/v0.3.0
|
|
217
|
+
[0.2.0]: https://github.com/qiobn/zotero-research-assistant/releases/tag/v0.2.0
|
|
218
|
+
[0.1.1]: https://github.com/qiobn/zotero-research-assistant/releases/tag/v0.1.1
|
zra_mcp-0.3.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
This is **Zotero Research Assistant** — an MCP (Model Context Protocol) server that turns a Zotero reference library into an AI-searchable knowledge base. 36 MCP tools across 6 categories. **Core focus: production-grade RAG pipeline (chunking + retrieval quality) for academic papers.**
|
|
6
|
+
|
|
7
|
+
- **Author:** qiobn
|
|
8
|
+
- **Language:** Python 3.11+
|
|
9
|
+
- **Package:** `zotero-research-assistant`
|
|
10
|
+
- **Entry:** `project_a_mcp/server.py` → `zra-mcp` CLI command
|
|
11
|
+
- **Key deps:** ChromaDB, onnxruntime (INT8 default), sentence-transformers (FP32 fallback), PyMuPDF, FastMCP, PyZotero
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
research_core/
|
|
17
|
+
parsers/ — PDF extraction, text cleaner (52 rules), chunker, section detector
|
|
18
|
+
rag/ — ChromaDB store, retriever, SQLite metadata DB, evaluation, logger, diagnostics
|
|
19
|
+
tools/ — 36 MCP tool implementations
|
|
20
|
+
zotero/ — Zotero local + web API client
|
|
21
|
+
project_a_mcp/ — MCP server entry point (stdio)
|
|
22
|
+
scripts/ — CLI utils (index_library, audit_index, run_evaluation, publish)
|
|
23
|
+
tests/ — pytest suite + 60 golden eval queries
|
|
24
|
+
docs/ — Setup guides (Cherry Studio CN/EN)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Development Rules
|
|
28
|
+
|
|
29
|
+
### Commit & Log Protocol
|
|
30
|
+
|
|
31
|
+
**On every significant change (new feature, bug fix, non-trivial refactor), you MUST:**
|
|
32
|
+
|
|
33
|
+
1. **Update `DEVELOPMENT_LOG.md`** — Record:
|
|
34
|
+
- What was changed (with commit hash)
|
|
35
|
+
- What problem it solved
|
|
36
|
+
- Technical decisions made and their rationale
|
|
37
|
+
- Future optimization directions
|
|
38
|
+
- Known issues introduced
|
|
39
|
+
|
|
40
|
+
2. **Update `CHANGELOG.md`** — Keep a Changelog format (`Added`/`Changed`/`Fixed`/`Removed` sections under current version). User-facing, less technical than DEVELOPMENT_LOG.
|
|
41
|
+
|
|
42
|
+
3. **Commit with a conventional commit message — ALWAYS include a body, never an empty commit:**
|
|
43
|
+
- First line: `<type>: <summary>` (50-80 chars, imperative mood)
|
|
44
|
+
- Then a BLANK LINE
|
|
45
|
+
- Then body paragraphs explaining **what** changed, **why**, and any design notes
|
|
46
|
+
- Types: `feat:` / `fix:` / `docs:` / `refactor:` / `chore:`
|
|
47
|
+
- Example:
|
|
48
|
+
```
|
|
49
|
+
feat: add query rewrite for bilingual academic search
|
|
50
|
+
|
|
51
|
+
Dictionary-based CN<->EN term expansion with three layers:
|
|
52
|
+
Layer 1: ~300 built-in methodology pairs from query_dict.json
|
|
53
|
+
Layer 2: auto-extracted from user's Zotero tags during sync
|
|
54
|
+
Layer 3: user-defined via add_query_synonym MCP tool
|
|
55
|
+
|
|
56
|
+
Expansion runs in search_papers() — zero added latency, no LLM
|
|
57
|
+
dependency. Each expanded term runs independent semantic search
|
|
58
|
+
with RRF merging and expansion weight scoring.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
4. **Push** after each logical unit of work (not after every micro-edit).
|
|
62
|
+
|
|
63
|
+
### Code Style
|
|
64
|
+
|
|
65
|
+
- Follow surrounding code patterns: comment density, naming, idiom
|
|
66
|
+
- Use `from __future__ import annotations` in all new files
|
|
67
|
+
- Use dataclasses for data containers
|
|
68
|
+
- Return typed dataclass instances, not raw dicts
|
|
69
|
+
- All write operations default to dry-run preview; require explicit confirmation
|
|
70
|
+
- MCP tools: one tool per user intent, compose via `item_key`
|
|
71
|
+
- Windows compatibility: no emoji in terminal output (use ASCII alternatives), use `os.path` or `pathlib`
|
|
72
|
+
|
|
73
|
+
### Testing
|
|
74
|
+
|
|
75
|
+
- Unit tests in `tests/` with pytest
|
|
76
|
+
- Run: `pytest tests/ -v`
|
|
77
|
+
- Lint: `ruff check .`
|
|
78
|
+
- Format: `ruff format .`
|
|
79
|
+
- Evaluation: `python scripts/run_evaluation.py`
|
|
80
|
+
|
|
81
|
+
### Environment
|
|
82
|
+
|
|
83
|
+
- `.env` is gitignored; `.env.example` is committed (template only, no real secrets)
|
|
84
|
+
- All configurable values have env var overrides
|
|
85
|
+
- Defaults are zero-config: users should get basic functionality without any `.env` edits
|
|
86
|
+
- New env vars must be documented in: `.env.example`, both READMEs' config tables
|
|
87
|
+
|
|
88
|
+
### Documentation Sync
|
|
89
|
+
|
|
90
|
+
When adding/removing features or changing behavior, update:
|
|
91
|
+
1. `README.md` (English) + `README_zh.md` (Chinese) — keep in sync
|
|
92
|
+
2. `CHANGELOG.md` — keep-a-changelog format
|
|
93
|
+
3. `DEVELOPMENT_LOG.md` — technical details and decisions
|
|
94
|
+
4. `DEVELOPMENT_PLAN.md` — progress bars and task checkboxes
|
|
95
|
+
5. `.env.example` — new env vars with comments
|
|
96
|
+
|
|
97
|
+
## Key Files Reference
|
|
98
|
+
|
|
99
|
+
| File | Purpose |
|
|
100
|
+
|------|---------|
|
|
101
|
+
| `DEVELOPMENT_LOG.md` | Detailed technical changelog (dev-facing) |
|
|
102
|
+
| `CHANGELOG.md` | Release changelog (user-facing) |
|
|
103
|
+
| `DEVELOPMENT_PLAN.md` | Task tracking + progress bars |
|
|
104
|
+
| `README.md` / `README_zh.md` | Bilingual project READMEs |
|
|
105
|
+
| `research_core/parsers/chunker.py` | Chunking with CHUNKING_VERSION for auto-rebuild |
|
|
106
|
+
| `research_core/parsers/text_cleaner.py` | 52 blacklist rules, CLEANER_VERSION |
|
|
107
|
+
| `research_core/rag/database.py` | SQLite metadata DB (auto-created on first sync) |
|
|
108
|
+
| `research_core/rag/logger.py` | JSONL retrieval trace logging |
|
|
109
|
+
| `research_core/rag/evaluation.py` | Recall@K, MRR, NDCG |
|
|
110
|
+
| `research_core/rag/retriever.py` | ChromaDB retriever with section expansion + enrichment |
|
|
111
|
+
|
|
112
|
+
## Current State (v0.4.0-dev)
|
|
113
|
+
|
|
114
|
+
- Phase 0/1/2/3 (partial) complete; Phase 4 (v0.4.0) in progress
|
|
115
|
+
- 36 MCP tools (32 always-on + 4 CNKI-conditional), all operational
|
|
116
|
+
- Key features: BM25+Dense hybrid retrieval, ONNX INT8 embedding, MMR diversity,
|
|
117
|
+
bilingual query expansion, contextual chunk enrichment, dual-format output
|
|
118
|
+
- Known issues: evaluation only run on small test set (8 papers)
|
|
119
|
+
- Next priorities: run full-pipeline evaluation on real library, chunk size tuning
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Development Log
|
|
2
|
+
|
|
3
|
+
> Detailed technical development log with problem/solution/decision records.
|
|
4
|
+
|
|
5
|
+
- **[中文版](./docs/DEVELOPMENT_LOG.md)** — 完整中文版
|
|
6
|
+
- **[English](./docs/DEVELOPMENT_LOG_EN.md)** — Full English version
|
|
7
|
+
|
|
8
|
+
See also: [CHANGELOG.md](./CHANGELOG.md) for user-facing release notes.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Development Plan — RAG Full-Pipeline Optimization
|
|
2
|
+
|
|
3
|
+
> Last updated: 2026-07-13 | Current version: v0.4.0-dev
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Progress Overview
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Phase 0 (Audit) ████████████████████ 100% ✅ DONE
|
|
11
|
+
Phase 1 (P0) ████████████████████ 100% ✅ DONE
|
|
12
|
+
Phase 2 (P1) ████████████████████ 100% ✅ DONE
|
|
13
|
+
Phase 3 (P2) ████████░░░░░░░░░░░░ 40% (completed: 3.1, 3.3; remaining: 3.2, 3.4, 3.5)
|
|
14
|
+
Phase 4 (v0.4.0) ░░░░░░░░░░░░░░░░░░░░ 0% Architecture audit findings
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Phase 3: P2 — Refinements (Partial)
|
|
20
|
+
|
|
21
|
+
### 3.1 Query Rewrite (Academic Scene) ✅
|
|
22
|
+
|
|
23
|
+
> Implemented: `research_core/rag/query_rewriter.py`. Three-layer bilingual expansion (built-in ~310 pairs + Zotero tags + user synonyms). LRU-cached. `research_core/rag/query_dict.json`.
|
|
24
|
+
|
|
25
|
+
### 3.2 Adaptive Chunk Granularity ⬜
|
|
26
|
+
|
|
27
|
+
> **RESEARCHED & DEFERRED**: 2025-2026 literature (NAACL, Chroma, PaperQA2) shows fixed-size chunking is the strong baseline. Semantic/adaptive chunking does not consistently beat it. PaperQA2 uses fixed ~9000 chars with downstream LLM reranking. Chunk size is the dominant variable, not the splitter method.
|
|
28
|
+
|
|
29
|
+
### 3.3 Search Result Post-Processing ✅
|
|
30
|
+
|
|
31
|
+
> All three originally planned items completed:
|
|
32
|
+
> - MMR diversity (λ=0.4, grid-search tuned, max 3 chunks/paper)
|
|
33
|
+
> - Neighbor chunk expansion (±1 chunk, section-constrained)
|
|
34
|
+
> - Source diversity (MMR cap + per-document penalty)
|
|
35
|
+
|
|
36
|
+
### 3.4 Comprehensive Diagnostic MCP Tool ⬜
|
|
37
|
+
|
|
38
|
+
> **DEFERRED**: Normal users don't trace why results ranked a certain way. De-prioritized.
|
|
39
|
+
|
|
40
|
+
### 3.5 Metadata-Enhanced Re-Ranking ⬜
|
|
41
|
+
|
|
42
|
+
> **RESEARCHED & DEFERRED**: Marginal improvement for personal libraries (5-10%). The strongest signals (citation count, journal tier) are external and add latency. Not worth the complexity at this scale.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Phase 4: v0.4.0 — Architecture Audit Findings (2026-07-13)
|
|
47
|
+
|
|
48
|
+
Issues identified during full architecture review:
|
|
49
|
+
|
|
50
|
+
### 4.1 Evaluation Tests Full Pipeline 🔴 HIGH (in progress)
|
|
51
|
+
|
|
52
|
+
> **Problem**: `evaluate_retrieval()` only tests `retriever.search()` (pure semantic). BM25, CE reranker, MMR, and RRF fusion have NEVER been evaluated. Every retrieval component you've built lacks quantitative validation.
|
|
53
|
+
>
|
|
54
|
+
> **Fix**: Add `--full-pipeline` mode to `run_evaluation.py` that calls `search_papers()` instead of `retriever.search()`. Compare semantic-only vs full-pipeline metrics. Save baselines for future regression testing.
|
|
55
|
+
|
|
56
|
+
**Estimate:** 1 day
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### 4.2 Log Rotation ⬜ 🟡 MEDIUM
|
|
61
|
+
|
|
62
|
+
> **Problem**: `_retrieval_log.jsonl` grows unboundedly. Large libraries could hit GB-scale log files.
|
|
63
|
+
>
|
|
64
|
+
> **Fix**: Add size-based rotation (e.g., keep last 100MB / 10K entries). Or time-based (keep 30 days).
|
|
65
|
+
|
|
66
|
+
**Estimate:** 0.5 day
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### 4.3 Authors Field in SQLite ⬜ 🟡 MEDIUM
|
|
71
|
+
|
|
72
|
+
> **Problem**: SQLite `papers.authors` is always `""`. Comment says "ZoteroItem doesn't expose authors as JSON" but `Item.authors` is `list[str]` — it's available.
|
|
73
|
+
>
|
|
74
|
+
> **Fix**: `json.dumps(item.authors)` when writing to SQLite in `_index_metadata()`.
|
|
75
|
+
|
|
76
|
+
**Estimate:** 5 minutes
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### 4.4 Section Parent Linking ⬜ 🟡 MEDIUM
|
|
81
|
+
|
|
82
|
+
> **Problem**: `section_detector.py` computes `parent_idx` (subsection hierarchy) but SQLite `sections.parent_id` is always NULL. Subsections of Methods, etc. are flattened.
|
|
83
|
+
>
|
|
84
|
+
> **Fix**: Store parent-child relationships in SQLite during `_index_metadata()`.
|
|
85
|
+
|
|
86
|
+
**Estimate:** 0.5 day
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### 4.5 Dead Parameters in sync_index ⬜ 🟢 LOW
|
|
91
|
+
|
|
92
|
+
> **Problem**: `sync_index(chunk_size=800, chunk_overlap=120)` accepts parameters that the chunker ignores (uses its own `target_chunk_size=600` internally since v2).
|
|
93
|
+
>
|
|
94
|
+
> **Fix**: Remove dead parameters or add deprecation warning.
|
|
95
|
+
|
|
96
|
+
**Estimate:** 5 minutes
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### 4.6 Docstring Bug ⬜ 🟢 LOW
|
|
101
|
+
|
|
102
|
+
> **Problem**: `search_papers()` docstring says `diversity_weight=0.6`, actual default is `0.4` (grid-search tuned).
|
|
103
|
+
>
|
|
104
|
+
> **Fix**: Update docstring.
|
|
105
|
+
|
|
106
|
+
**Estimate:** 1 minute
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### 4.7 BM25 Chinese Tokenization ⬜ 🟢 LOW
|
|
111
|
+
|
|
112
|
+
> **Problem**: Character bigrams work but jieba segmentation would be more accurate for Chinese BM25 queries.
|
|
113
|
+
>
|
|
114
|
+
> **Fix**: Optional jieba dependency, use if available, fall back to bigrams.
|
|
115
|
+
|
|
116
|
+
**Estimate:** 0.5 day
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### 4.8 Personalized Re-Ranking ⬜ 🔵 FUTURE
|
|
121
|
+
|
|
122
|
+
> **Problem**: User engagement signals (annotations, reading depth, saved notes) are never used for ranking.
|
|
123
|
+
>
|
|
124
|
+
> **Fix**: Light boost for papers with user annotations/notes. Available from Zotero local API.
|
|
125
|
+
|
|
126
|
+
**Estimate:** 1 day
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Summary
|
|
131
|
+
|
|
132
|
+
| Phase | # Tasks | Completed | Remaining |
|
|
133
|
+
|-------|---------|-----------|-----------|
|
|
134
|
+
| Phase 0 (Audit) | 5 | 5 | 0 |
|
|
135
|
+
| Phase 1 (P0) | 3 | 3 | 0 |
|
|
136
|
+
| Phase 2 (P1) | 5 | 4 | 1 (deferred) |
|
|
137
|
+
| Phase 3 (P2) | 5 | 2 | 3 (deferred) |
|
|
138
|
+
| Phase 4 (v0.4.0) | 8 | 0 | 8 |
|
|
139
|
+
| **Total** | **26** | **14** | **12** |
|
|
140
|
+
|
|
141
|
+
### Immediate Next Steps
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
→ Phase 4.1: Full-pipeline evaluation (in progress)
|
|
145
|
+
→ Phase 4.3: Authors field fix (trivial, quick win)
|
|
146
|
+
→ Phase 4.6: Docstring fix (trivial)
|
|
147
|
+
→ Phase 4.5: Dead parameters cleanup
|
|
148
|
+
```
|