diff --git a/backend/app/services/embedding.py b/backend/app/services/embedding.py index 5ecd5d4..e6cead2 100644 --- a/backend/app/services/embedding.py +++ b/backend/app/services/embedding.py @@ -34,7 +34,11 @@ class EmbeddingSpec: or self.token_limit < 2 ): raise EmbeddingError("向量维度和 token 上限无效") - if not self.model or not isinstance(self.query_instruction, str): + if ( + not isinstance(self.model, str) + or not self.model + or not isinstance(self.query_instruction, str) + ): raise EmbeddingError("模型名称或查询指令无效") if self.checkpoint_format not in {"safetensors", "pytorch-weights-only"}: raise EmbeddingError("不支持的权重格式") @@ -138,7 +142,7 @@ class LocalEmbeddingProvider: raise EmbeddingError("模型 tokenizer 上限与配置不一致") def encode(self, texts: list[str], *, query: bool = False) -> list[list[float]]: - if any( + if not isinstance(texts, list) or any( not isinstance(text, str) or not text.strip() or len(text) > 10_000 for text in texts ): raise EmbeddingError("每条输入须为非空文本且最多 10000 字符") diff --git a/backend/tests/test_embedding.py b/backend/tests/test_embedding.py index 418dcbb..69a9dce 100644 --- a/backend/tests/test_embedding.py +++ b/backend/tests/test_embedding.py @@ -118,3 +118,10 @@ def test_invalid_resource_options_fail_without_loading_optional_dependencies(opt def test_unsupported_checkpoint_format_is_rejected(checkpoint): with pytest.raises(EmbeddingError): replace(SMALL_ZH, checkpoint_format=checkpoint) + + +@pytest.mark.parametrize("texts", [None, "不能逐字编码的字符串", ("占位",), [None], [" "]]) +def test_input_shape_and_text_are_validated_before_encoding(texts): + provider = object.__new__(LocalEmbeddingProvider) + with pytest.raises(EmbeddingError): + provider.encode(texts) diff --git a/docs/TASKS.md b/docs/TASKS.md index af10c54..33ee24d 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -54,4 +54,4 @@ - 固定配置、完整指标定义、输入哈希、复现命令和限制见 [本地模型评估](LOCAL_EMBEDDING_EVALUATION.md)。原始运行报告、权重、虚拟环境只保存在本机 Git 元数据目录,不入库。 - 向量数据库/空间隔离、索引构建、向量/RRF 检索、真实已核验问题集和浏览器/部署验收仍待后续推进;本轮没有把这些标记为完成。 -- 本独立分支实际验证:`ruff check .`、`ruff format --check .` 通过;`pytest -q` **44 passed**,包含当前 dev 的 PostgreSQL/HTTP 基线与新增轻量契约/指标用例。small/base 另由独立模型环境真实执行;可选依赖在新建空环境中完成 CPU wheel 安装与后续依赖解析验证。先前 #7/#8 的 70/91 项结果属于各自分支,不混同为本独立分支的测试计数。 +- 本独立分支实际验证:`ruff check .`、`ruff format --check .` 通过;`pytest -q` **49 passed**,包含当前 dev 的 PostgreSQL/HTTP 基线与新增轻量契约/指标用例。small/base 另由独立模型环境真实执行;可选依赖在新建空环境中完成 CPU wheel 安装与后续依赖解析验证。先前 #7/#8 的 70/91 项结果属于各自分支,不混同为本独立分支的测试计数。