ForcePilot/backend/test/test_manual_eval.py
Wenjie Zhang 410dd47c14 refactor: 将后端代码迁移至 backend 目录
- 将 server/, src/, scripts/, test/ 等目录移动到 backend/ 目录下
- 使用 git rename 保留文件历史记录
- 更新 docker-compose.yml 和 api.Dockerfile 配置

WIP: 项目结构重构进行中
2026-03-24 11:08:12 +08:00

213 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import requests
import json
import time
import sys
import os
# 添加评估指标测试功能
def test_evaluation_metrics():
"""测试评估指标计算"""
print("\n" + "=" * 50)
print("测试评估指标计算")
print("=" * 50)
try:
from yuxi.utils.evaluation_metrics import EvaluationMetricsCalculator
# 测试检索指标
retrieved_chunks = [
{"content": "test1", "metadata": {"chunk_id": "file_bbb147_chunk_0"}},
{"content": "test2", "metadata": {"chunk_id": "file_bbb147_chunk_1"}},
{"content": "test3", "metadata": {"chunk_id": "file_bbb147_chunk_2"}},
]
gold_chunk_ids = ["file_bbb147_chunk_0", "file_bbb147_chunk_2"]
print("测试检索指标...")
retrieval_metrics = EvaluationMetricsCalculator.calculate_retrieval_metrics(retrieved_chunks, gold_chunk_ids)
print(f"检索指标结果: {retrieval_metrics}")
# 测试答案指标
# generated_answer = "该研究以数据语义化—知识结构化—可信推理的技术主线"
# gold_answer = "该研究以数据语义化—知识结构化—可信推理的技术主线,遵循数据—知识—推理—应用的演化逻辑"
print("\n测试答案指标需要Judge LLM跳过实际LLM调用...")
# 由于需要judge_llm这里只测试检索指标
print("跳过答案指标测试需要配置Judge LLM")
print("评估指标计算测试完成!")
return True
except Exception as e:
print(f"评估指标测试失败: {e}")
return False
BASE_URL = "http://localhost:5050"
USERNAME = "zwj"
PASSWORD = "zwj12138"
DB_ID = "kb_5e343066eb4713959698ae6ca16843a0"
def get_token():
try:
resp = requests.post(f"{BASE_URL}/api/auth/token", data={"username": USERNAME, "password": PASSWORD})
if resp.status_code != 200:
print(f"Login failed: {resp.text}")
return None
return resp.json()["access_token"]
except Exception as e:
print(f"Connection failed: {e}")
return None
def main():
# 首先测试评估指标计算
test_evaluation_metrics()
token = get_token()
if not token:
sys.exit(1)
headers = {"Authorization": f"Bearer {token}"}
print(f"\n1. Trying to retrieve a real chunk from {DB_ID}...")
chunk_content = "This is a fallback test query."
chunk_id = "unknown"
try:
# 尝试查询 (Fixed payload structure)
resp = requests.post(
f"{BASE_URL}/api/knowledge/databases/{DB_ID}/query",
headers=headers,
json={"query": "人工智能", "meta": {"top_k": 5}},
)
if resp.status_code == 200:
data = resp.json()
# 结果在 result 字段中
results = data.get("result", [])
first_chunk = None
if isinstance(results, list) and len(results) > 0:
first_chunk = results[0]
elif isinstance(results, dict) and "retrieved_chunks" in results:
if results["retrieved_chunks"]:
first_chunk = results["retrieved_chunks"][0]
if first_chunk:
print(f"Found chunk: {str(first_chunk.get('content', ''))[:50]}...")
chunk_content = first_chunk.get("content", chunk_content)
chunk_id = first_chunk.get("chunk_id", chunk_id) or first_chunk.get("id", chunk_id)
else:
print("No chunks found in retrieval results. Using fallback.")
print(f"Raw results: {results}")
else:
print(f"Query failed: {resp.text}")
except Exception as e:
print(f"Query Exception: {e}")
print(f"\n2. Creating benchmark with query based on chunk: {chunk_id}")
# 构造 Benchmark 数据
benchmark_data = {
"query": chunk_content, # 使用 Chunk 内容作为查询,理论上应该能召回它自己
"gold_chunk_ids": [str(chunk_id)], # Ensure string
"gold_answer": "This is a gold answer.",
}
# 生成临时文件
with open("temp_benchmark.jsonl", "w") as f:
f.write(json.dumps(benchmark_data, ensure_ascii=False) + "\n")
print("\n3. Uploading benchmark...")
try:
files = {"file": ("temp_benchmark.jsonl", open("temp_benchmark.jsonl", "rb"), "application/jsonlines")}
# Fixed: use params for name/description
params = {"name": "Manual Eval Test", "description": "Test generated from script"}
resp = requests.post(
f"{BASE_URL}/api/evaluation/databases/{DB_ID}/benchmarks/upload",
headers=headers,
params=params,
files=files,
)
if resp.status_code != 200:
print(f"Upload failed: {resp.text}")
sys.exit(1)
benchmark = resp.json()
# Benchmark response format depends on Service impl.
# My filesystem impl returns the metadata dict directly.
# But wait, KnowledgeRouter might wrap it?
# router returns: return {"message": "上传成功", "data": result} (Assume standard wrapper)
# Let's check router impl.
# From router code read earlier:
# result = await service.upload_benchmark(...)
# return {"message": "上传成功", "data": result}
benchmark_id = benchmark["data"]["benchmark_id"]
print(f"Benchmark uploaded: {benchmark_id}")
except Exception as e:
print(f"Upload Exception: {e}")
sys.exit(1)
print("\n4. Running evaluation...")
try:
payload = {"benchmark_id": benchmark_id, "retrieval_config": {"top_k": 5}}
resp = requests.post(f"{BASE_URL}/api/evaluation/databases/{DB_ID}/run", headers=headers, json=payload)
if resp.status_code != 200:
print(f"Run evaluation failed: {resp.text}")
sys.exit(1)
task_id = resp.json()["data"]["task_id"]
print(f"Evaluation task started: {task_id}")
# 轮询状态
while True:
resp = requests.get(f"{BASE_URL}/api/evaluation/{task_id}/progress", headers=headers)
if resp.status_code != 200:
print(f"Get progress failed: {resp.text}")
break
progress = resp.json()
# The progress endpoint returns {task_id, status, ...} based on my service impl?
# Router wrapper: return {"message": "success", "data": result}
data = progress.get("data", progress) # Handle wrapper if exists
status = data["status"]
current_progress = data.get("progress", 0)
print(f"Status: {status}, Progress: {current_progress}%")
if status in ["completed", "failed"]:
break
time.sleep(2)
if status == "completed":
print("\nEvaluation Completed!")
# 获取结果
resp = requests.get(f"{BASE_URL}/api/evaluation/{task_id}/results", headers=headers)
print(json.dumps(resp.json(), indent=2, ensure_ascii=False))
else:
print("\nEvaluation Failed!")
except Exception as e:
print(f"Evaluation Exception: {e}")
# 清理
if os.path.exists("temp_benchmark.jsonl"):
os.remove("temp_benchmark.jsonl")
if __name__ == "__main__":
main()