chore: 修我文件里的 mypy 类型错误(8 处)
源自评审 §1.4「数字不可比」引发的核查,结论比预想更有价值: **mypy 报错的主因不是代码质量,而是本机缺 SQLAlchemy 2.0 的类型信息。** 装上 `sqlalchemy2-stubs` 后 181 → 43(该类存根是 2.0 之前的旧包,会换一批新错: `mapped_column`/`DeclarativeBase` 不存在),卸载后回到 184。**本机 mypy 数字不可作为 质量结论,双方也不可比。** 但那 184 里有 8 个是**我文件里的真实错误**,已修: - `knowledge_retrieval_service`:返回类型 `Mapping` → `dict`(回表后要就地补写 `score`/`intent`,而 `Mapping` 是只读协议);`ids` 显式标注并过滤 `None`; 去掉 3 处已失效的 `type: ignore`(strict 下 unused-ignore 本身是错误) - `knowledge_management`:服务工厂返回类型 `Any` → `KnowledgeManagementService` (`TYPE_CHECKING` 期导入,运行时仍惰性,不引入循环依赖),消掉 3 个 `no-any-return` 未动的:`model_gateway` 2 处 `dict-item`(`ModelEndpointConfig` 实际具备协议要求的 全部字段,属 SQLAlchemy `Mapped[T]` 在缺存根时的消解问题,不是真缺陷,不用 cast 掩盖)。
This commit is contained in:
@@ -223,8 +223,12 @@ class KnowledgeRetrievalService:
|
||||
|
||||
# --- MySQL 二次校验 -------------------------------------------------------
|
||||
|
||||
async def _verify(self, rows: Sequence[Mapping[str, Any]]) -> list[Mapping[str, Any]]:
|
||||
"""按 `knowledge_id` 回表校验:已发布 + active + 在有效期内;并按分数降序保留。"""
|
||||
async def _verify(self, rows: Sequence[Mapping[str, Any]]) -> list[dict[str, Any]]:
|
||||
"""按 `knowledge_id` 回表校验:已发布 + active + 在有效期内;并按分数降序保留。
|
||||
|
||||
返回 `list[dict]` 而不是 `list[Mapping]`:回表后要**就地补写** `score` 与 `intent`
|
||||
两个字段(`Mapping` 是只读协议,写不进去),所以这里的可变性是有意为之。
|
||||
"""
|
||||
if not rows:
|
||||
return []
|
||||
order = {str(row["knowledge_id"]): index for index, row in enumerate(rows)}
|
||||
@@ -234,8 +238,10 @@ class KnowledgeRetrievalService:
|
||||
for row in rows
|
||||
if isinstance(row.get("intent"), str) and str(row["intent"]).strip()
|
||||
}
|
||||
ids = [self._as_int(row["knowledge_id"]) for row in rows]
|
||||
ids = [value for value in ids if value is not None]
|
||||
# 显式标注 `list[int]`:`_as_int` 可能返回 None,下一步过滤掉它们;
|
||||
# 不标注的话 mypy 推断成 `list[int | None]`,与 `_load_by_ids` 的签名不符。
|
||||
raw_ids: list[int | None] = [self._as_int(row["knowledge_id"]) for row in rows]
|
||||
ids: list[int] = [value for value in raw_ids if value is not None]
|
||||
if not ids:
|
||||
return []
|
||||
stored = await self._load_by_ids(ids)
|
||||
@@ -246,10 +252,10 @@ class KnowledgeRetrievalService:
|
||||
]
|
||||
verified.sort(key=lambda row: scores.get(str(row["id"]), 0.0), reverse=True)
|
||||
for row in verified:
|
||||
row["score"] = scores.get(str(row["id"])) # type: ignore[index]
|
||||
row["score"] = scores.get(str(row["id"]))
|
||||
# 显式 intent 标签只存在于 Milvus 侧(MySQL 无该列):随命中一并带过来,
|
||||
# 否则会在回表后被"按集合名推断"覆盖掉,丢掉 chitchat / transfer_human。
|
||||
row["intent"] = intents.get(str(row["id"])) # type: ignore[index]
|
||||
row["intent"] = intents.get(str(row["id"]))
|
||||
return verified
|
||||
|
||||
async def _load_by_ids(self, ids: Sequence[int]) -> list[dict[str, Any]]:
|
||||
@@ -388,7 +394,10 @@ class KnowledgeRetrievalService:
|
||||
"""COSINE 距离即相似度(越大越相似),裁剪到契约要求的 0..1。"""
|
||||
raw = row.get("score", row.get("distance"))
|
||||
try:
|
||||
score = float(raw) # type: ignore[arg-type]
|
||||
# `raw` 来自 Milvus/MySQL 的弱类型字段:显式转 `float`,失败即返回 None。
|
||||
# 这里**不加** `type: ignore`:`float()` 的参数是 `Any`,本环境 mypy 会把它
|
||||
# 报成 unused-ignore(`strict` 下 unused-ignore 本身是一条错误)。
|
||||
score = float(raw)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
return min(1.0, max(0.0, score))
|
||||
|
||||
Reference in New Issue
Block a user