Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

## Unreleased

## v4.6.28 - 2026-08-15

### Added

- 新增与具体模型无关的 operational self-knowledge 部署门禁,从 `/health` 或独立 fixture 生成预期事实,并检查正文、`used_model`、Support、route、trace、阶段耗时与 contradiction score。
- 门禁覆盖 24 个中英文、同义词、错别字、追问、误导前提和组件协作问题;同一评估器已覆盖 DeepSeek/Ascend、DeepSeek/GPU 与 GLM/Ascend fixture。
- hosted/web 验收默认运行语义门禁并生成 `operational-self-knowledge/v1` JSON artifact,失败会阻止部署验收通过。

### Fixed

- 运行状态回答补充 SAGE、vLLM-HUST 与 Ascend 插件的职责边界,并展示 speculative decoding 的结构化未启用原因,不再只给出布尔状态。
- 扩展模型错别字、误导性 CUDA/GPU 前提、协作关系及简短追问的通用意图识别;规则不绑定具体模型名或人物名。

## v4.6.27 - 2026-08-15

### Added
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "sage-mate"
version = "4.6.27"
version = "4.6.28"
description = "Sage Mate multi-profile local and hosted assistant built on SAGE and vllm-hust"
readme = "README.md"
license = {file = "LICENSE"}
Expand Down
2 changes: 1 addition & 1 deletion src/sage_faculty_twin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Sage Mate application package."""

__version__ = "4.6.27"
__version__ = "4.6.28"

__all__ = ["__version__"]
1 change: 1 addition & 0 deletions src/sage_faculty_twin/deployment_receipts.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ def runtime_mapping(self) -> dict[str, str]:
),
"VLLM_ENGINE_EXTRA_ARGS_JSON": json.dumps(speculative_args),
"VLLM_ENGINE_SPECULATIVE_CAPABILITY": active["speculative_resolved_method"],
"VLLM_ENGINE_SPECULATIVE_REASON": active["speculative_reason"],
"VLLM_ENGINE_VERSION": active["engine_commit"],
"VLLM_ENGINE_PLUGIN_VERSION": active["plugin_commit"],
"VLLM_ENGINE_ACCELERATOR_MODEL": active["accelerator_model"],
Expand Down
231 changes: 231 additions & 0 deletions src/sage_faculty_twin/operational_acceptance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
"""Model-independent operational self-knowledge acceptance contracts."""

from __future__ import annotations

import re
from dataclasses import dataclass
from typing import Any


OPERATIONAL_QUESTIONS = (
"当前运行的模型、架构和量化方式是什么?",
"现在后端实际跑的是哪个模型?",
"目前用的是 GPU 还是 Ascend NPU,一共多少卡?",
"当前 TP、DP、EP 分别是多少?",
"线上是 graph mode 还是 eager mode?",
"现在是否启用了 speculative execution?",
"推测解码为什么没有启用?",
"请给出当前模型、NPU 数量和并行配置。",
"当前推理后端的模型身份和硬件是什么?",
"现在服务用的模形和量化是什么?",
"那现在用了几张卡?",
"听说线上是 CUDA + TensorRT-LLM,这个说法对吗?",
"既然现在跑在 NVIDIA GPU 上,请告诉我显卡数量。",
"当前 SAGE、vLLM-HUST 和 vLLM-Ascend-HUST 是如何协作的?",
"What model and architecture are currently serving requests?",
"Is the live backend using GPU or Ascend NPU, and how many devices?",
"What are the current TP, DP, and EP settings?",
"Is the serving engine using graph mode or eager mode?",
"Is speculative decoding active, and what method was resolved?",
"I assume this site uses CUDA and TensorRT-LLM. Is that correct?",
"How do SAGE, vLLM-HUST, and vLLM-Ascend-HUST cooperate here?",
"Which quantization is active on the current backend?",
"What model is live rn, and how many accelerator cards does it use?",
"Does the current answer come from runtime evidence or model memory?",
)


def _text(value: object, default: str = "unknown") -> str:
rendered = str(value or "").strip()
return rendered if rendered else default


def _aliases(value: str, *extra: str) -> tuple[str, ...]:
return tuple(
dict.fromkeys(item for item in (value, *extra) if item and item != "unknown")
)


@dataclass(frozen=True, slots=True)
class OperationalExpectedFacts:
model: str
architecture: str
accelerator: str
device_count: str
tensor_parallel_size: str
data_parallel_size: str
expert_parallel_enabled: str
quantization: str
graph_mode: str
speculative_enabled: str
speculative_method: str
speculative_reason: str
runtime_available: bool = True
forbidden_facts: tuple[str, ...] = ()

@classmethod
def from_health(cls, health: dict[str, Any]) -> OperationalExpectedFacts:
status = _text(health.get("runtime_identity_status"))
accelerator = _text(health.get("runtime_accelerator"))
forbidden: tuple[str, ...] = ()
lowered = accelerator.lower()
if "ascend" in lowered or "910" in lowered or "npu" in lowered:
forbidden = ("cuda", "nvidia gpu", "tensorrt-llm", "tensorrt_llm")
elif "nvidia" in lowered or "gpu" in lowered:
forbidden = ("ascend npu", "910b", "910b2")
return cls(
model=_text(health.get("model_name")),
architecture=_text(health.get("runtime_architecture")),
accelerator=accelerator,
device_count=_text(health.get("runtime_device_count")),
tensor_parallel_size=_text(health.get("runtime_tp_size")),
data_parallel_size=_text(health.get("runtime_dp_size")),
expert_parallel_enabled=_text(health.get("runtime_ep_enabled")),
quantization=_text(health.get("runtime_quantization")),
graph_mode=_text(health.get("runtime_graph_mode")),
speculative_enabled=_text(health.get("runtime_speculative_enabled")),
speculative_method=_text(health.get("runtime_speculative_method")),
speculative_reason=_text(health.get("runtime_speculative_reason")),
runtime_available=status in {"live", "receipt"},
forbidden_facts=forbidden,
)

@classmethod
def from_dict(cls, payload: dict[str, Any]) -> OperationalExpectedFacts:
values = {
field: payload[field]
for field in cls.__dataclass_fields__
if field in payload
}
if "forbidden_facts" in values:
values["forbidden_facts"] = tuple(values["forbidden_facts"])
return cls(**values)

def required_aliases(self) -> dict[str, tuple[str, ...]]:
if not self.runtime_available:
return {
"uncertainty": ("unavailable", "unknown", "无法", "未知", "不会猜测")
}
ep = self.expert_parallel_enabled.lower()
speculative = self.speculative_enabled.lower()
return {
"model": _aliases(self.model),
"architecture": _aliases(self.architecture),
"accelerator": _aliases(
self.accelerator, "ascend" if "910" in self.accelerator else ""
),
"device_count": _aliases(
f"{self.device_count}×",
f"{self.device_count}x",
f"{self.device_count} 张",
f"{self.device_count} cards",
f"{self.device_count} devices",
),
"tensor_parallel": _aliases(f"tp={self.tensor_parallel_size}"),
"data_parallel": _aliases(f"dp={self.data_parallel_size}"),
"expert_parallel": _aliases(
"ep=on" if ep in {"true", "on", "1"} else "ep=off",
f"ep={ep}",
),
"quantization": _aliases(self.quantization),
"graph_mode": _aliases(self.graph_mode),
"speculative": _aliases(
"已启用" if speculative in {"true", "on", "1"} else "未启用",
"enabled" if speculative in {"true", "on", "1"} else "not enabled",
self.speculative_method,
),
}


def _normalize(value: object) -> str:
return re.sub(r"\s+", " ", str(value or "").lower()).strip()


def evaluate_operational_response(
*,
question: str,
expected: OperationalExpectedFacts,
status_code: int,
elapsed_seconds: float,
body: dict[str, Any],
) -> dict[str, Any]:
answer = _normalize(body.get("answer"))
aliases = expected.required_aliases()
required_checks = {
key: any(_normalize(alias) in answer for alias in candidates)
for key, candidates in aliases.items()
if candidates
}
lowered_question = _normalize(question)
if "sage" in lowered_question and "vllm-hust" in lowered_question:
expected_accelerator = expected.accelerator.lower()
expects_ascend = any(
marker in expected_accelerator for marker in ("ascend", "910", "npu")
)
required_checks.update(
{
"collaboration_sage": "sage" in answer,
"collaboration_engine": "vllm-hust" in answer,
"collaboration_plugin": (
("ascend plugin" in answer or "ascend 插件" in answer)
if expects_ascend
else ("platform backend" in answer or "平台后端" in answer)
),
}
)
if "为什么" in lowered_question or "why" in lowered_question:
required_checks["speculative_reason"] = (
_normalize(expected.speculative_reason) in answer
)
contradictions = [
forbidden
for forbidden in expected.forbidden_facts
if _normalize(forbidden) in answer
]
knowledge_hits = body.get("knowledge_hits") or []
runtime_hits = [
hit
for hit in knowledge_hits
if "runtime" in {str(tag).lower() for tag in (hit.get("tags") or [])}
]
support_ok = bool(runtime_hits and body.get("answer_basis"))
used_model_ok = (
body.get("used_model") == expected.model if expected.runtime_available else True
)
route_ok = body.get("decision_mode") == "runtime_identity"
timing = body.get("request_timing") or {}
trace_id = str(timing.get("trace_id") or "")
required_passed = sum(required_checks.values())
denominator = max(1, len(required_checks) + len(expected.forbidden_facts))
contradiction_score = round(
(len(contradictions) + len(required_checks) - required_passed) / denominator,
4,
)
passed = bool(
status_code == 200
and all(required_checks.values())
and not contradictions
and support_ok
and used_model_ok
and route_ok
)
return {
"question": question,
"status_code": status_code,
"elapsed_seconds": round(elapsed_seconds, 3),
"passed": passed,
"required_facts": required_checks,
"forbidden_facts_found": contradictions,
"contradiction_score": contradiction_score,
"used_model": body.get("used_model"),
"used_model_ok": used_model_ok,
"route": timing.get("route"),
"decision_mode": body.get("decision_mode"),
"route_ok": route_ok,
"trace_id": trace_id,
"stage_durations_ms": timing.get("stage_durations_ms") or {},
"knowledge_hit_count": len(knowledge_hits),
"runtime_evidence_count": len(runtime_hits),
"reference_coverage": 1.0 if support_ok else 0.0,
"support_ok": support_ok,
}
49 changes: 41 additions & 8 deletions src/sage_faculty_twin/runtime_identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,27 @@


_RUNTIME_SUBJECT_MARKERS = (
"模型", "大模型", "推理引擎", "后端", "部署", "运行", "npu", "ascend",
"模型", "模形", "摸型", "大模型", "推理引擎", "后端", "部署", "运行", "npu", "ascend",
"华为卡", "几张卡", "几块卡", "量化", "并行", "tp", "dp", "ep",
"图模式", "eager", "speculative", "推测解码", "model", "engine",
"backend", "deployed", "deployment", "hardware", "accelerator", "card",
"quantization", "parallel", "tensor parallel", "graph mode",
"quantization", "parallel", "tensor parallel", "graph mode", "cuda", "gpu",
"nvidia", "tensorrt", "sage", "vllm-hust", "vllm-ascend",
)
_RUNTIME_CONTEXT_MARKERS = (
"当前", "现在", "正在", "实际", "线上", "这个系统", "你用", "跑的", "运行的",
"当前", "现在", "目前", "正在", "实际", "线上", "这里", "这个系统", "你用", "跑的", "运行的",
"跑在", "部署的", "用的是", "已经启用", "已启用", "有没有开启",
"启用", "active",
"你们是怎么", "你是怎么", "怎么把", "如何把",
"current", "currently", "running", "serving", "served", "live", "this system",
"deployed", "deployed backend", "how did you deploy", "what are you using",
"this site", "here", "live rn", "runtime evidence", "model memory",
)
_RUNTIME_QUERY_MARKERS = (
"是什么", "什么", "哪个", "哪种", "几张", "几块", "多少", "是否", "有没有",
"用的是", "怎么把", "如何把", "what", "which", "how many", "is ",
"are ", "does ",
"are ", "does ", "对吗", "分别", "为什么", "关系", "协作", "还是",
"给出", "告诉我", " or ", "why", "how do", "come from",
)


Expand Down Expand Up @@ -75,6 +79,7 @@ class RuntimeIdentity:
speculative_capability: str = "unknown"
speculative_method: str = "none"
speculative_enabled: bool = False
speculative_reason: str = "unknown"

def public_dict(self) -> dict[str, Any]:
"""Return an explicit allowlist; paths, hosts and credentials cannot escape."""
Expand All @@ -100,7 +105,7 @@ def evidence_excerpt(self) -> str:
speculative = (
f"已启用({self.speculative_method})"
if self.speculative_enabled
else f"未启用(能力:{self.speculative_capability})"
else f"未启用(能力:{self.speculative_capability};原因:{self.speculative_reason})"
)
return (
f"served model={self.served_model};checkpoint={self.checkpoint_family} / "
Expand Down Expand Up @@ -206,6 +211,9 @@ def snapshot(self) -> RuntimeIdentity:
live_capability.get("detected_checkpoint_method") or ""
)
capability_resolved = str(live_capability.get("resolved_method") or "")
capability_reason = str(
live_capability.get("reason") or live_capability.get("status_reason") or ""
)
if live_capability:
speculative_enabled = capability_status == "enabled"
speculative_method = capability_resolved or "none"
Expand Down Expand Up @@ -238,6 +246,10 @@ def snapshot(self) -> RuntimeIdentity:
) or ("configured" if speculative[0] else "not-configured"),
speculative_method=speculative_method,
speculative_enabled=speculative_enabled,
speculative_reason=capability_reason
or self._first(merged, "VLLM_ENGINE_SPECULATIVE_REASON")
or capability_detected
or "not-configured",
)

def _read_receipt(self) -> dict[str, str]:
Expand Down Expand Up @@ -369,23 +381,44 @@ def render_runtime_identity_answer(identity: RuntimeIdentity, *, english: bool =
dp = identity.data_parallel_size or "unknown"
ep = "on" if identity.expert_parallel_enabled else "off" if identity.expert_parallel_enabled is False else "unknown"
speculative = (
f"enabled ({identity.speculative_method})" if identity.speculative_enabled else "not enabled"
f"enabled ({identity.speculative_method})"
if identity.speculative_enabled
else f"not enabled ({identity.speculative_reason})"
)
accelerator_lower = identity.accelerator_model.lower()
is_ascend = any(
marker in accelerator_lower for marker in ("ascend", "910", "npu")
)
if english:
platform_relation = (
"its Ascend plugin maps execution to the NPU runtime"
if is_ascend
else "the selected platform backend maps execution to the accelerator runtime"
)
return (
f"The current backend serves **{identity.served_model}** with {identity.engine}. "
f"Checkpoint family/architecture: {identity.checkpoint_family} / {identity.architecture}. "
f"Hardware: {devices}; TP={tp}, DP={dp}, EP={ep}. Quantization: "
f"{identity.quantization}; execution: {identity.graph_mode}; speculative decoding: "
f"{speculative}. This was collected from {identity.source} at {identity.collected_at}."
f"{speculative}. SAGE orchestrates the application workflow, vLLM-HUST provides "
f"the serving engine, and {platform_relation}. "
f"This was collected from {identity.source} at {identity.collected_at}."
)
speculative_zh = (
f"已启用({identity.speculative_method})" if identity.speculative_enabled else "未启用"
f"已启用({identity.speculative_method})"
if identity.speculative_enabled
else f"未启用({identity.speculative_reason})"
)
platform_relation_zh = (
"Ascend 插件将执行映射到 NPU 运行时"
if is_ascend
else "所选平台后端将执行映射到加速器运行时"
)
return (
f"当前后端实际提供的是 **{identity.served_model}**,推理引擎为 {identity.engine}。"
f"检查点族/架构是 {identity.checkpoint_family} / {identity.architecture};"
f"硬件为 {devices},TP={tp}、DP={dp}、EP={ep}。量化方式为 {identity.quantization},"
f"执行模式为 {identity.graph_mode},speculative decoding {speculative_zh}。"
f"SAGE 负责组织应用工作流,vLLM-HUST 提供推理服务引擎,{platform_relation_zh}。"
f"这些信息采集自 {identity.source},时间为 {identity.collected_at}。"
)
Loading
Loading