feat: 增加 Agent Excel 批量测试

This commit is contained in:
2026-08-12 17:00:50 +08:00
parent c4231f268b
commit 3faecab6ac
26 changed files with 1327 additions and 6 deletions

View File

@@ -13,6 +13,7 @@ def test_super_admin_has_all_permissions() -> None:
admin = Admin(id=1, username="root", password="unused", name="root", status=1, is_super_admin=1)
assert permissions_for(admin) == ALL_PERMISSION_CODES
assert {"feedback.view", "feedback.detail", "feedback.export", "feedback.delete"} <= ALL_PERMISSION_CODES
assert "prompt.batch" in ALL_PERMISSION_CODES
def test_role_permissions_are_restricted_to_catalog() -> None:

View File

@@ -0,0 +1,125 @@
from io import BytesIO
import json
import pytest
from fastapi import HTTPException, UploadFile
from openpyxl import Workbook, load_workbook
from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session
from sqlalchemy.pool import StaticPool
from app.models import Base
from app.models.admin import Admin
from app.models.agent_batch import AgentBatchTestItem
from app.models.ai_config import ModelConfig
from app.services.agent_batch_test_service import AgentBatchTestService, MAX_BATCH_QUESTIONS
def _database() -> Session:
engine = create_engine(
"sqlite:///:memory:",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
Base.metadata.create_all(engine)
return Session(engine)
def _admin() -> Admin:
return Admin(id=1, username="admin", password="hash", name="系统管理员", status=1)
def _model() -> ModelConfig:
return ModelConfig(
id=1,
provider="mock",
display_name="批量测试模型",
api_type="openai_compatible",
model_name="batch-model",
api_url="",
api_key="",
auth_type="bearer",
enabled=1,
)
def test_template_can_be_downloaded_and_imported() -> None:
stream = AgentBatchTestService.template_workbook()
workbook = load_workbook(stream, data_only=True)
assert workbook.sheetnames == ["批量测试问题", "填写说明"]
assert [cell.value for cell in workbook["批量测试问题"][1]] == ["序号", "问题"]
assert workbook["填写说明"]["B3"].value == f"最多 {MAX_BATCH_QUESTIONS} 个问题"
upload = UploadFile(filename="批量测试.xlsx", file=BytesIO(stream.getvalue()))
rows = AgentBatchTestService.parse_questions(upload)
assert len(rows) == 2
assert rows[0]["externalNo"] == "1"
assert "测试的问题" in rows[0]["question"]
def test_create_job_snapshots_config_and_export_keeps_failed_rows() -> None:
with _database() as db:
admin = _admin()
model = _model()
db.add_all([admin, model])
db.commit()
job = AgentBatchTestService.create_job(
db,
admin=admin,
filename="回归问题.xlsx",
rows=[
{"rowNumber": 2, "externalNo": "Q-1", "question": "第一个问题"},
{"rowNumber": 3, "externalNo": "Q-2", "question": "第二个问题"},
],
config={
"name": "提示词回归测试",
"promptContent": "只根据知识库回答",
"modelId": model.id,
"knowledgeIds": [],
"temperature": 0.2,
"maxToken": 8192,
"responseDepth": 35,
},
)
items = list(db.scalars(select(AgentBatchTestItem).order_by(AgentBatchTestItem.row_number)))
items[0].status = "success"
items[0].answer = "第一个答案"
items[0].model_name = "批量测试模型"
items[0].retrieve_count = 3
items[0].duration_ms = 1250
items[1].status = "failed"
items[1].error_message = "供应商超时"
job.status = "completed_with_errors"
job.processed_count = 2
job.success_count = 1
job.failed_count = 1
db.commit()
assert json.loads(job.generation_config)["maxToken"] == 8192
assert json.loads(job.knowledge_names) == ["全部正式开放知识库"]
exported = AgentBatchTestService.export_workbook(job, items)
workbook = load_workbook(exported, data_only=True)
sheet = workbook["批量测试结果"]
assert sheet["C2"].value == "第一个答案"
assert sheet["D2"].value == "成功"
assert sheet["D3"].value == "失败"
assert sheet["E3"].value == "供应商超时"
assert sheet.freeze_panes == "A2"
def test_import_rejects_excel_formula_question() -> None:
workbook = Workbook()
sheet = workbook.active
sheet.append(["序号", "问题"])
sheet.append([1, '=HYPERLINK("https://example.com","问题")'])
stream = BytesIO()
workbook.save(stream)
stream.seek(0)
with pytest.raises(HTTPException) as exc:
AgentBatchTestService.parse_questions(UploadFile(filename="危险问题.xlsx", file=stream))
assert exc.value.status_code == 400
assert "不能使用 Excel 公式" in exc.value.detail