diff --git a/app/ports.py b/app/ports.py index 89ac1a7..147f109 100644 --- a/app/ports.py +++ b/app/ports.py @@ -7,6 +7,9 @@ from typing import TYPE_CHECKING, Protocol, runtime_checkable if TYPE_CHECKING: import numpy as np + from app.tree.index import TreeIndex + from core.types import GeneratedQuestion + @runtime_checkable class EmbeddingProvider(Protocol): @@ -29,3 +32,27 @@ class EmbeddingProvider(Protocol): [N, D] ndarray,每行 L2 范数为 1.0。 """ ... + + +@runtime_checkable +class QuestionGenerator(Protocol): + """LLM 驱动的题目生成端口(预留接口)。 + + 参数: + video_id: 视频标识。 + task_type: 题型。 + tree: 视频树索引,提供锚节点上下文。 + exemplars: 风格示例题目列表。 + + 返回: + 生成的单条题目。 + """ + + async def generate( + self, + video_id: str, + task_type: str, + tree: TreeIndex, + *, + exemplars: list[GeneratedQuestion], + ) -> GeneratedQuestion: ... diff --git a/app/question_gen/__init__.py b/app/question_gen/__init__.py index e69de29..9867a7d 100644 --- a/app/question_gen/__init__.py +++ b/app/question_gen/__init__.py @@ -0,0 +1,5 @@ +"""出题模块 — benchmark 加载与分层采样。""" + +from app.question_gen.loader import load_benchmark, stratified_sample + +__all__ = ["load_benchmark", "stratified_sample"] diff --git a/tests/unit/test_question_gen_api.py b/tests/unit/test_question_gen_api.py new file mode 100644 index 0000000..5a4a8f0 --- /dev/null +++ b/tests/unit/test_question_gen_api.py @@ -0,0 +1,40 @@ +"""app/ports.py QuestionGenerator Protocol 与 app/question_gen 公开 API 测试。""" + +from __future__ import annotations + +import importlib + +from app.ports import QuestionGenerator + + +class TestQuestionGeneratorProtocol: + def test_importable(self) -> None: + """QuestionGenerator 可从 app.ports 导入。""" + assert QuestionGenerator is not None + + def test_is_runtime_checkable(self) -> None: + """QuestionGenerator 是 runtime_checkable Protocol。""" + assert hasattr(QuestionGenerator, "__protocol_attrs__") or hasattr( + QuestionGenerator, "__abstractmethods__" + ) + + def test_generate_method_exists(self) -> None: + """Protocol 定义了 generate 方法。""" + assert hasattr(QuestionGenerator, "generate") + + +class TestQuestionGenPublicAPI: + def test_load_benchmark_importable_from_package(self) -> None: + """load_benchmark 可从 app.question_gen 直接导入。""" + mod = importlib.import_module("app.question_gen") + assert hasattr(mod, "load_benchmark") + + def test_stratified_sample_importable_from_package(self) -> None: + """stratified_sample 可从 app.question_gen 直接导入。""" + mod = importlib.import_module("app.question_gen") + assert hasattr(mod, "stratified_sample") + + def test_all_exports(self) -> None: + """__all__ 包含预期的公开 API。""" + mod = importlib.import_module("app.question_gen") + assert set(mod.__all__) == {"load_benchmark", "stratified_sample"}