TESTING_GUIDE.md 9.61 KB

WeKnora Ragas 评估测试流程指南

本文档用于在服务器上从零验证 WeKnora Ragas 独立评估项目是否可运行。

1. 前置条件

确认服务器满足:

  • Python 3.10 或更高版本。不要使用 Python 3.6。
  • WeKnora API 可访问,例如 http://localhost:9090/api/v1
  • vLLM 已提供 OpenAI-compatible Chat Completions endpoint,例如 http://localhost:8000/v1
  • Infinity 已提供 OpenAI-compatible Embeddings endpoint,例如 http://localhost:7997/v1
  • 可选:Infinity reranker endpoint 可访问,例如 http://localhost:7998/v1

检查 Python:

python3 --version
python3.10 --version
python3.11 --version

推荐使用 Python 3.11:

cd /data/weknora_ragas
python3.11 -m venv .venv
source .venv/bin/activate
python --version
pip install -U pip setuptools wheel
pip install -e ".[pdf]"

如果只跑 XLSX 或文本型 PDF,可以先安装基础依赖:

pip install -e .

2. 配置 .env

复制示例文件:

cp .env.example .env

编辑 .env

WEKNORA_BASE_URL=http://localhost:9090/api/v1
WEKNORA_API_KEY=your-weknora-api-key
WEKNORA_KB_ID=
WEKNORA_KB_NAME=ragas-eval-pilot

RAGAS_LLM_API_KEY=EMPTY
RAGAS_LLM_BASE_URL=http://localhost:8000/v1
RAGAS_GENERATOR_MODEL=your-vllm-model-id
RAGAS_JUDGE_MODEL=your-vllm-model-id

RAGAS_EMBEDDING_API_KEY=EMPTY
RAGAS_EMBEDDING_BASE_URL=http://localhost:7997/v1
RAGAS_EMBEDDING_MODEL=your-embedding-model-id

RAGAS_RERANKER_API_KEY=EMPTY
RAGAS_RERANKER_BASE_URL=http://localhost:7998/v1
RAGAS_RERANKER_MODEL=your-reranker-model-id

TESTSET_SIZE=10
REQUEST_INTERVAL_SECONDS=0.2

如果服务没有鉴权,RAGAS_*_API_KEY 仍建议填 EMPTY,避免 OpenAI client 因空 key 报错。

确认模型 ID:

curl http://localhost:8000/v1/models
curl http://localhost:7997/v1/models

把返回的 id 精确填入 RAGAS_JUDGE_MODELRAGAS_EMBEDDING_MODEL

3. 服务连通性检查

先检查 WeKnora 知识库:

python scripts/00_create_kb.py

如果 .envWEKNORA_KB_ID 为空,该脚本会调用:

POST /api/v1/knowledge-bases
{"name": "..."}

创建成功后会把 ID 写回 .env

再检查模型服务:

python scripts/00_check_models.py

期望输出包括:

[OK] Generator LLM
[OK] Judge LLM
[OK] Embedding
All configured model services are reachable.

如果配置了 reranker,也会检查:

[OK] Reranker

如果 reranker 当前不用,可以让 RAGAS_RERANKER_BASE_URLRAGAS_RERANKER_MODEL 为空,脚本会跳过。

4. 准备 Pilot 数据

首轮不要直接跑大规模数据。建议:

  • 2 个 PDF。
  • 1 个 XLSX。
  • TESTSET_SIZE=10

放置文件:

mkdir -p data/raw_docs
cp /path/to/*.pdf data/raw_docs/
cp /path/to/*.xlsx data/raw_docs/

也兼容旧目录:

mkdir -p data/raw_docs/pdf data/raw_docs/xlsx
cp /path/to/*.pdf data/raw_docs/pdf/
cp /path/to/*.xlsx data/raw_docs/xlsx/

5. 执行完整 Pilot

按顺序执行:

python workflows/01_ingest_export.py
python workflows/02_generate_testset.py
python workflows/03_review_testset.py
python workflows/04_evaluate_report.py

说明:

  • workflows/01_ingest_export.py 对齐原 01_upload_docs.py02_wait_ingestion.py03_export_chunks.py:上传原始文件、等待 WeKnora 解析、导出 chunks。
  • workflows/02_generate_testset.py 对齐原 04_parse_docs.py05_generate_testset.py:从 chunks 构造测试集来源并生成候选 QA。
  • workflows/03_review_testset.py 对齐原 06_review_testset.py:把候选 QA 标为 approved,后续可替换为人工审核。
  • workflows/04_evaluate_report.py 对齐原 07_run_weknora_qa.py08_build_ragas_input.py09_run_ragas_eval.py10_report.py:逐条调用 WeKnora 问答、构造 Ragas 输入、调用 Ragas 打分、生成 Markdown 报告。
  • 每个 workflow 结束时会打印本阶段生成的文件路径。

6. 产物验收

检查这些文件是否生成:

ls -lh data/exported/knowledge.jsonl
ls -lh data/exported/chunks.jsonl
ls -lh data/parsed_docs/documents.jsonl
ls -lh data/parsed_docs/parse_summary.json
ls -lh data/testsets/testset.reviewed.jsonl
ls -lh data/runs/weknora_answers.jsonl
ls -lh data/runs/ragas_input.jsonl
ls -lh data/reports/ragas_scores.csv
ls -lh data/reports/summary.md

快速检查关键字段:

python - <<'PY'
import json
from pathlib import Path

for path in [
    "data/exported/chunks.jsonl",
    "data/parsed_docs/documents.jsonl",
    "data/runs/weknora_answers.jsonl",
    "data/runs/ragas_input.jsonl",
]:
    rows = [json.loads(line) for line in Path(path).read_text(encoding="utf-8").splitlines() if line.strip()]
    print(path, len(rows))
    if rows:
        print(rows[0].keys())
PY

最低验收标准:

  • data/exported/chunks.jsonl 非空。
  • data/parsed_docs/documents.jsonl 非空。
  • data/runs/weknora_answers.jsonl 中大部分 response 非空。
  • data/runs/ragas_input.jsonlretrieved_contexts 非空比例合理。
  • data/reports/ragas_scores.csv 至少有一项指标列。
  • data/reports/summary.md 可读。

7. 常见故障

Python 版本过低

现象:

Could not find a version that satisfies the requirement setuptools>=68

原因:当前虚拟环境是 Python 3.6。项目要求 Python 3.10+。

处理:

rm -rf .venv
python3.11 -m venv .venv
source .venv/bin/activate
pip install -U pip setuptools wheel
pip install -e ".[pdf]"

模型 endpoint 填错

vLLM 和 Infinity 都要填 OpenAI-compatible /v1 地址,例如:

RAGAS_LLM_BASE_URL=http://localhost:8000/v1
RAGAS_EMBEDDING_BASE_URL=http://localhost:7997/v1

不要填 Ollama 原生 /api 或服务根路径。

Embedding 报 invalid input type

项目已经在 ragas_runner.py 中设置:

tiktoken_enabled=False
check_embedding_ctx_length=False

如果仍报错,优先用 scripts/00_check_models.py 确认 Infinity endpoint 是否兼容 OpenAI embeddings API。

Ragas 指标超时或 NaN

本地或小模型 judge 可能无法稳定输出 Ragas 需要的结构化结果。先缩小指标集,例如只保留:

metrics:
  - response_relevancy

确认链路通后,再逐个打开:

  - faithfulness
  - context_precision
  - context_recall
  - factual_correctness

也可以调大:

timeout_seconds: 600
max_workers: 1
max_tokens: 4096

如果 05_generate_testset.py 在生成 QA 时出现 LLMDidNotFinishException,优先不要继续盲目调大 ragas.max_tokens05 有独立的生成预算和输入长度:

TESTSET_RAGAS_MODE=direct
TESTSET_GENERATOR_MAX_TOKENS=4096
TESTSET_MAX_DOCUMENT_CHARS=2000
RAGAS_ENABLE_THINKING=false
RAGAS_HTTP_KEEPALIVE=false
RAGAS_TESTSET_TRANSFORMS=single_hop_entities

TESTSET_RAGAS_MODE 支持三种模式:

  • direct:工程兜底模式。脚本直接把 WeKnora chunks 构造成单跳场景,再调用 Ragas 的 single-hop sample generator 生成 QA。它跳过 Ragas 默认的 HeadlinesExtractorSummaryExtractorNERExtractor、scenario generation 等中间步骤,最稳,但不是完整的 Ragas testset generation 流程。
  • prechunked:Ragas 面向“已经切好 chunk”的标准入口,对应 generate_with_chunks()。这里的 pre-chunked 指输入已经是 WeKnora 导出的 chunk,不需要 Ragas 再从原始文档切分。当前建议配合 RAGAS_TESTSET_TRANSFORMS=single_hop_entities,只做单跳 QA 所需的实体抽取,并限制为 single-hop,避免多个不相关 chunk 被组合成 multi-hop 问题。
  • langchain_docs:Ragas 面向 LangChain Document 的原始文档入口,对应 generate_with_langchain_docs()。它可能触发标题、摘要、拆分等默认文档预处理,不适合作为本项目主路径,只保留给对比实验。

当前推荐先用 direct 跑通评测闭环;需要验证 Ragas 标准 pre-chunked 生成链路时,再切换到 prechunked

如果使用 Qwen thinking 模型,RAGAS_ENABLE_THINKING=false 会只在 RAGAS 请求里附加 chat_template_kwargs.enable_thinking=false,避免 RAGAS 的 JSON/Pydantic 结构化输出被 Thinking Process 前缀破坏;WeKnora 本身的检索问答链路不经过这些脚本,不会受影响。

如果 prechunked 模式在本地 vLLM 上出现 Event loop is closedAPIConnectionError,保持 RAGAS_HTTP_KEEPALIVE=false。如果想验证 Ragas 默认 prechunked transforms,可临时设置 RAGAS_TESTSET_TRANSFORMS=default,但它会重新启用 summary/filter/theme/relationship 等更重的中间步骤。

如果 vLLM 仍然报生成未完成,先把 TESTSET_SIZE 降到 3,再把 TESTSET_MAX_DOCUMENT_CHARS 调到 1000-1500 验证链路;ragas.max_tokens 主要用于后续评测阶段,不应该拿来无限放大测试集生成阶段的输出长度。

WeKnora 问答没有 retrieved_contexts

检查:

python scripts/03_export_chunks.py
python scripts/07_run_weknora_qa.py

重点看:

  • 知识库是否解析完成。
  • chunks 是否导出非空。
  • WeKnora agent-chat 问答 SSE 是否返回 references 事件。
  • .envWEKNORA_AGENT_ID 是否为 builtin-quick-answer,且 WEKNORA_AGENT_ENABLED=false
  • data/runs/failed_requests.jsonl 中是否记录 empty_retrieval

8. 扩大样本规模

首轮 10 条样本通过后,再扩大:

TESTSET_SIZE=50

再逐步扩大到 100-300 条。每次扩大前先确认:

  • Ragas judge 延迟可接受。
  • failed_requests.jsonl 中失败比例低。
  • summary.md 中检索失败样本可解释。
  • QA 集经过人工审核或抽样审核。