mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-08 13:12:08 +00:00
fix(yuanbao): skip resource resolve on cache hits
This commit is contained in:
parent
5a5e7e2a46
commit
9d2ff58f5f
2 changed files with 119 additions and 0 deletions
|
|
@ -2618,6 +2618,27 @@ class MediaResolveMiddleware(InboundMiddleware):
|
|||
cls._resource_cache.pop(k, None)
|
||||
cls._resource_cache[resource_id] = (local_path, mime, time.time())
|
||||
|
||||
@classmethod
|
||||
def _append_cached_resource(
|
||||
cls,
|
||||
adapter,
|
||||
resource_id: str,
|
||||
media_paths: List[str],
|
||||
mimes: List[str],
|
||||
) -> bool:
|
||||
"""Append a cached resource to output lists when available."""
|
||||
hit = cls._get_cached_resource(resource_id)
|
||||
if hit is None:
|
||||
return False
|
||||
local_path, mime = hit
|
||||
logger.debug(
|
||||
"[%s] resource cache hit: rid=%s path=%s",
|
||||
adapter.name, resource_id, local_path,
|
||||
)
|
||||
media_paths.append(local_path)
|
||||
mimes.append(mime)
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _guess_image_ext_from_url(url: str) -> str:
|
||||
"""Guess image extension from URL path."""
|
||||
|
|
@ -2805,6 +2826,8 @@ class MediaResolveMiddleware(InboundMiddleware):
|
|||
|
||||
# Extract resourceId from the placeholder URL for cache dedup.
|
||||
rid = ExtractContentMiddleware._parse_resource_id(url)
|
||||
if rid and cls._append_cached_resource(adapter, rid, media_urls, media_types):
|
||||
continue
|
||||
|
||||
try:
|
||||
fetch_url = await cls._resolve_download_url(adapter, url)
|
||||
|
|
@ -2846,6 +2869,8 @@ class MediaResolveMiddleware(InboundMiddleware):
|
|||
for rid, kind, filename in refs:
|
||||
if kind not in _RESOLVABLE_MEDIA_KINDS:
|
||||
continue
|
||||
if cls._append_cached_resource(adapter, rid, media_paths, mimes):
|
||||
continue
|
||||
try:
|
||||
fresh_url = await cls._fetch_resource_url(adapter, rid)
|
||||
except Exception as exc:
|
||||
|
|
|
|||
|
|
@ -1505,6 +1505,100 @@ class TestResolveYbresRefs:
|
|||
assert paths == []
|
||||
assert mimes == []
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cache_hit_skips_resource_url_resolve(self, tmp_path):
|
||||
"""A resourceId cache hit must not await ``_fetch_resource_url`` at all."""
|
||||
adapter = make_adapter()
|
||||
cached_file = tmp_path / "rid-cached.jpg"
|
||||
cached_file.write_bytes(b"cached-image")
|
||||
MediaResolveMiddleware._resource_cache.clear()
|
||||
try:
|
||||
MediaResolveMiddleware._put_cached_resource(
|
||||
"rid-cached", str(cached_file), "image/jpeg",
|
||||
)
|
||||
|
||||
with patch.object(
|
||||
MediaResolveMiddleware, "_fetch_resource_url",
|
||||
new=AsyncMock(return_value="https://fresh/never"),
|
||||
) as p_fetch:
|
||||
paths, mimes = await MediaResolveMiddleware._resolve_ybres_refs(
|
||||
adapter, [("rid-cached", "image", "")], log_prefix="test",
|
||||
)
|
||||
|
||||
assert paths == [str(cached_file)]
|
||||
assert mimes == ["image/jpeg"]
|
||||
p_fetch.assert_not_awaited()
|
||||
finally:
|
||||
MediaResolveMiddleware._resource_cache.clear()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cache_miss_still_resolves(self, tmp_path):
|
||||
"""Uncached refs still pay the resolve; cached ones are served in place."""
|
||||
adapter = make_adapter()
|
||||
cached_file = tmp_path / "rid-cached.jpg"
|
||||
cached_file.write_bytes(b"cached-image")
|
||||
MediaResolveMiddleware._resource_cache.clear()
|
||||
try:
|
||||
MediaResolveMiddleware._put_cached_resource(
|
||||
"rid-cached", str(cached_file), "image/jpeg",
|
||||
)
|
||||
|
||||
with patch.object(
|
||||
MediaResolveMiddleware, "_fetch_resource_url",
|
||||
new=AsyncMock(return_value="https://fresh/new"),
|
||||
) as p_fetch, patch.object(
|
||||
MediaResolveMiddleware, "_download_and_cache",
|
||||
new=AsyncMock(return_value=("/cache/new.jpg", "image/jpeg")),
|
||||
):
|
||||
paths, mimes = await MediaResolveMiddleware._resolve_ybres_refs(
|
||||
adapter,
|
||||
[("rid-cached", "image", ""), ("rid-new", "image", "")],
|
||||
log_prefix="test",
|
||||
)
|
||||
|
||||
assert paths == [str(cached_file), "/cache/new.jpg"]
|
||||
assert mimes == ["image/jpeg", "image/jpeg"]
|
||||
p_fetch.assert_awaited_once()
|
||||
finally:
|
||||
MediaResolveMiddleware._resource_cache.clear()
|
||||
|
||||
|
||||
class TestResolveMediaUrlsCacheHit:
|
||||
"""Current-message media cache hits must skip the download-URL resolve."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cache_hit_skips_resolve_download_url(self, tmp_path):
|
||||
adapter = make_adapter()
|
||||
cached_file = tmp_path / "rid-cached.jpg"
|
||||
cached_file.write_bytes(b"cached-image")
|
||||
MediaResolveMiddleware._resource_cache.clear()
|
||||
try:
|
||||
MediaResolveMiddleware._put_cached_resource(
|
||||
"rid-cached", str(cached_file), "image/jpeg",
|
||||
)
|
||||
|
||||
with patch.object(
|
||||
MediaResolveMiddleware, "_resolve_download_url",
|
||||
new=AsyncMock(return_value="https://fresh/never"),
|
||||
) as p_resolve, patch.object(
|
||||
MediaResolveMiddleware, "_fetch_resource_url",
|
||||
new=AsyncMock(return_value="https://fresh/never"),
|
||||
) as p_fetch:
|
||||
paths, mimes = await MediaResolveMiddleware._resolve_media_urls(
|
||||
adapter,
|
||||
[{
|
||||
"kind": "image",
|
||||
"url": "https://hunyuan.tencent.com/api/resource/download?resourceId=rid-cached",
|
||||
}],
|
||||
)
|
||||
|
||||
assert paths == [str(cached_file)]
|
||||
assert mimes == ["image/jpeg"]
|
||||
p_resolve.assert_not_awaited()
|
||||
p_fetch.assert_not_awaited()
|
||||
finally:
|
||||
MediaResolveMiddleware._resource_cache.clear()
|
||||
|
||||
|
||||
class TestMediaResolveMiddlewareRouting:
|
||||
"""Branch-routing tests for MediaResolveMiddleware.handle()."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue