feat(search): __init__.py 公开 API + 修复 OCR 测试 asyncio 兼容性
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
"""搜索 Agent 装配层 — prompt 管理、skill 注册、工具分发、LLM 摘要、视觉观察。"""
|
||||||
|
|
||||||
|
from app.search.prompt import PromptManager
|
||||||
|
from app.search.skills import SkillRegistry, discover_skills
|
||||||
|
from app.search.tools import SearchToolDispatcher, get_tool_descriptions
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"PromptManager",
|
||||||
|
"SkillRegistry",
|
||||||
|
"SearchToolDispatcher",
|
||||||
|
"discover_skills",
|
||||||
|
"get_tool_descriptions",
|
||||||
|
]
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class TestCheckHealth:
|
|||||||
url = "http://10.0.0.1:7866"
|
url = "http://10.0.0.1:7866"
|
||||||
responses.add(responses.GET, f"{url}/health", status=200)
|
responses.add(responses.GET, f"{url}/health", status=200)
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
asyncio.get_event_loop().run_until_complete(client.check_health())
|
asyncio.run(client.check_health())
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
def test_unhealthy_endpoint_raises(self) -> None:
|
def test_unhealthy_endpoint_raises(self) -> None:
|
||||||
@@ -76,7 +76,7 @@ class TestCheckHealth:
|
|||||||
responses.add(responses.GET, f"{url}/health", status=500)
|
responses.add(responses.GET, f"{url}/health", status=500)
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
with pytest.raises(RuntimeError, match="健康检查失败"):
|
with pytest.raises(RuntimeError, match="健康检查失败"):
|
||||||
asyncio.get_event_loop().run_until_complete(client.check_health())
|
asyncio.run(client.check_health())
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
def test_unreachable_endpoint_raises(self) -> None:
|
def test_unreachable_endpoint_raises(self) -> None:
|
||||||
@@ -89,7 +89,7 @@ class TestCheckHealth:
|
|||||||
)
|
)
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
with pytest.raises(RuntimeError, match="端点不可达"):
|
with pytest.raises(RuntimeError, match="端点不可达"):
|
||||||
asyncio.get_event_loop().run_until_complete(client.check_health())
|
asyncio.run(client.check_health())
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
def test_multiple_endpoints_all_checked(self) -> None:
|
def test_multiple_endpoints_all_checked(self) -> None:
|
||||||
@@ -100,7 +100,7 @@ class TestCheckHealth:
|
|||||||
responses.add(responses.GET, f"{url_b}/health", status=503)
|
responses.add(responses.GET, f"{url_b}/health", status=503)
|
||||||
client = MonkeyOCRClient(urls=[url_a, url_b])
|
client = MonkeyOCRClient(urls=[url_a, url_b])
|
||||||
with pytest.raises(RuntimeError, match="健康检查失败"):
|
with pytest.raises(RuntimeError, match="健康检查失败"):
|
||||||
asyncio.get_event_loop().run_until_complete(client.check_health())
|
asyncio.run(client.check_health())
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -124,7 +124,7 @@ class TestTranscribeFrames:
|
|||||||
frame = tmp_path / "frame_001.jpg"
|
frame = tmp_path / "frame_001.jpg"
|
||||||
frame.write_bytes(b"\xff\xd8\xff\xe0fake")
|
frame.write_bytes(b"\xff\xd8\xff\xe0fake")
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames([frame]))
|
result = asyncio.run(client.transcribe_frames([frame]))
|
||||||
assert result == "帧1: Hello World | OCR Test"
|
assert result == "帧1: Hello World | OCR Test"
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
@@ -149,7 +149,7 @@ class TestTranscribeFrames:
|
|||||||
f.write_bytes(b"\xff\xd8data")
|
f.write_bytes(b"\xff\xd8data")
|
||||||
frames.append(f)
|
frames.append(f)
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames(frames))
|
result = asyncio.run(client.transcribe_frames(frames))
|
||||||
assert "帧1: Line A" in result
|
assert "帧1: Line A" in result
|
||||||
assert "帧2: Line B" in result
|
assert "帧2: Line B" in result
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ class TestTranscribeFrames:
|
|||||||
def test_empty_frames_returns_empty(self) -> None:
|
def test_empty_frames_returns_empty(self) -> None:
|
||||||
"""空帧列表 → 空串。"""
|
"""空帧列表 → 空串。"""
|
||||||
client = MonkeyOCRClient(urls=["http://ocr:7866"])
|
client = MonkeyOCRClient(urls=["http://ocr:7866"])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames([]))
|
result = asyncio.run(client.transcribe_frames([]))
|
||||||
assert result == ""
|
assert result == ""
|
||||||
|
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ class TestFailureDegradation:
|
|||||||
frame = tmp_path / "frame.jpg"
|
frame = tmp_path / "frame.jpg"
|
||||||
frame.write_bytes(b"\xff\xd8data")
|
frame.write_bytes(b"\xff\xd8data")
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames([frame]))
|
result = asyncio.run(client.transcribe_frames([frame]))
|
||||||
assert result == ""
|
assert result == ""
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
@@ -197,7 +197,7 @@ class TestFailureDegradation:
|
|||||||
f.write_bytes(b"\xff\xd8data")
|
f.write_bytes(b"\xff\xd8data")
|
||||||
frames.append(f)
|
frames.append(f)
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames(frames))
|
result = asyncio.run(client.transcribe_frames(frames))
|
||||||
# 帧1 失败被跳过,帧2 成功但输出为 "帧2: Good"
|
# 帧1 失败被跳过,帧2 成功但输出为 "帧2: Good"
|
||||||
assert "帧1" not in result
|
assert "帧1" not in result
|
||||||
assert "帧2: Good" in result
|
assert "帧2: Good" in result
|
||||||
@@ -224,7 +224,7 @@ class TestLineDedup:
|
|||||||
frame = tmp_path / "frame.jpg"
|
frame = tmp_path / "frame.jpg"
|
||||||
frame.write_bytes(b"\xff\xd8data")
|
frame.write_bytes(b"\xff\xd8data")
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames([frame]))
|
result = asyncio.run(client.transcribe_frames([frame]))
|
||||||
assert result == "帧1: 重复行 | 不同行"
|
assert result == "帧1: 重复行 | 不同行"
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
@@ -240,7 +240,7 @@ class TestLineDedup:
|
|||||||
frame = tmp_path / "frame.jpg"
|
frame = tmp_path / "frame.jpg"
|
||||||
frame.write_bytes(b"\xff\xd8data")
|
frame.write_bytes(b"\xff\xd8data")
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames([frame]))
|
result = asyncio.run(client.transcribe_frames([frame]))
|
||||||
# "A" 和 "." 被过滤(长度 <= 1),保留 "AB" 和 "CD"
|
# "A" 和 "." 被过滤(长度 <= 1),保留 "AB" 和 "CD"
|
||||||
assert result == "帧1: AB | CD"
|
assert result == "帧1: AB | CD"
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ class TestLineDedup:
|
|||||||
frame = tmp_path / "frame.jpg"
|
frame = tmp_path / "frame.jpg"
|
||||||
frame.write_bytes(b"\xff\xd8data")
|
frame.write_bytes(b"\xff\xd8data")
|
||||||
client = MonkeyOCRClient(urls=[url])
|
client = MonkeyOCRClient(urls=[url])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames([frame]))
|
result = asyncio.run(client.transcribe_frames([frame]))
|
||||||
assert result == ""
|
assert result == ""
|
||||||
|
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ class TestRoundRobin:
|
|||||||
f.write_bytes(b"\xff\xd8data")
|
f.write_bytes(b"\xff\xd8data")
|
||||||
frames.append(f)
|
frames.append(f)
|
||||||
client = MonkeyOCRClient(urls=[url_a, url_b])
|
client = MonkeyOCRClient(urls=[url_a, url_b])
|
||||||
result = asyncio.get_event_loop().run_until_complete(client.transcribe_frames(frames))
|
result = asyncio.run(client.transcribe_frames(frames))
|
||||||
assert "帧1: From A" in result
|
assert "帧1: From A" in result
|
||||||
assert "帧2: From B" in result
|
assert "帧2: From B" in result
|
||||||
# 验证两个端点都被调用
|
# 验证两个端点都被调用
|
||||||
|
|||||||
Reference in New Issue
Block a user