feat: strip extra_body on the embedding and OCR paths with a warning
Stripping is load-bearing, not tidying: those transports never send the value, so leaving it would make telemetry record a parameter never sent.
This commit is contained in:
@@ -4,11 +4,13 @@
|
||||
VT adapters/embedding.py(归一化);库裁决见设计 §7.3 表。
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
import dataclasses
|
||||
import json
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
from loguru import logger
|
||||
|
||||
from polygateway.errors import (
|
||||
RequestRejectedError,
|
||||
@@ -350,6 +352,48 @@ class TestEmbedTelemetry:
|
||||
assert len(rec.rows[1]["messages"]) < 1000 # 长文本截断后入库
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _captured_warnings():
|
||||
"""捕获库发出的 WARNING;loguru 不经标准 logging,pytest 的 caplog 抓不到。"""
|
||||
messages: list[str] = []
|
||||
sink_id = logger.add(messages.append, level="WARNING")
|
||||
try:
|
||||
yield messages
|
||||
finally:
|
||||
logger.remove(sink_id)
|
||||
|
||||
|
||||
class TestExtraBodyStripped:
|
||||
"""issue #4 决策 G: embedding 路径不消费 extra_body,剥离并 warning。"""
|
||||
|
||||
async def test_stripped_with_warning_but_assembly_succeeds(self):
|
||||
"""报错会让下游整个装配起不来,而这条路径本无采样语义(人类拍板)。"""
|
||||
with _captured_warnings() as warnings:
|
||||
client, _ = _embed_client([_src(extra_body={"temperature": 0})], ["ok"])
|
||||
assert client._sources[0].extra_body == {}
|
||||
assert any("extra_body" in m for m in warnings)
|
||||
assert any("dimensions" in m for m in warnings) # 文案须指路,不能只说不支持
|
||||
await client.embed(["hi"]) # 装配后可正常工作
|
||||
|
||||
async def test_telemetry_never_records_a_parameter_that_was_not_sent(self):
|
||||
"""剥离的真正理由: embed payload 硬编码 {model, input},不剥离则审计表
|
||||
|
||||
会显示这次调用带了 temperature=0——那是数据造假,比参数失效更坏。
|
||||
"""
|
||||
rec = _MemoryRecorder()
|
||||
client, _ = _embed_client(
|
||||
[_src(extra_body={"temperature": 0})], ["ok"], telemetry=rec
|
||||
)
|
||||
await client.embed(["hi"])
|
||||
assert rec.rows[0]["sampling"] is None
|
||||
|
||||
async def test_no_warning_without_extra_body(self):
|
||||
with _captured_warnings() as warnings:
|
||||
client, _ = _embed_client([_src()], ["ok"])
|
||||
assert client._sources[0].extra_body == {}
|
||||
assert not [m for m in warnings if "extra_body" in m]
|
||||
|
||||
|
||||
class TestEmbeddingSettings:
|
||||
_ENV = {
|
||||
"EMBED__QWEN__1__BASE_URL": "https://gw.example/v1",
|
||||
|
||||
@@ -7,6 +7,7 @@ retry_exhausted/circuit_open/stalled 三组断言即设计 §6 ③ 的 G1 契约
|
||||
import asyncio
|
||||
|
||||
import pytest
|
||||
from loguru import logger
|
||||
|
||||
from polygateway.backends.memory.breaker import InMemoryGate
|
||||
from polygateway.backends.memory.limiter import InMemoryLimiter
|
||||
@@ -377,6 +378,29 @@ class TestCheckHealth:
|
||||
await task
|
||||
|
||||
|
||||
class TestExtraBodyStripped:
|
||||
"""issue #4 决策 G: OCR 路径只发 multipart 表单,剥离 extra_body 并 warning。"""
|
||||
|
||||
def test_stripped_with_warning_but_assembly_succeeds(self):
|
||||
messages: list[str] = []
|
||||
sink_id = logger.add(messages.append, level="WARNING")
|
||||
try:
|
||||
client, _, _ = _client([_src(extra_body={"temperature": 0})], ["text"])
|
||||
finally:
|
||||
logger.remove(sink_id)
|
||||
assert client._sources[0].extra_body == {}
|
||||
assert any("extra_body" in m for m in messages)
|
||||
|
||||
async def test_telemetry_never_records_a_parameter_that_was_not_sent(self):
|
||||
"""不剥离则审计表会显示这次 OCR 带了 temperature=0——数据造假。"""
|
||||
recorder = _MemoryRecorder()
|
||||
client, _, _ = _client(
|
||||
[_src(extra_body={"temperature": 0})], ["text"], telemetry=recorder
|
||||
)
|
||||
await client.recognize_text(b"IMG")
|
||||
assert recorder.rows[0]["sampling"] is None
|
||||
|
||||
|
||||
class TestTelemetry:
|
||||
async def test_success_and_failure_recorded_without_image_bytes(self):
|
||||
recorder = _MemoryRecorder()
|
||||
|
||||
Reference in New Issue
Block a user