mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-10-19 15:33:54 +00:00
refactor: unify embedding calls behind batch entry point
Expose embed(inputs) on both embedding wrappers and route the existing LangChain query and document methods through it. This removes duplicate transport logic while allowing provider-ready text and media payloads to use the same extension-friendly path. Add focused regression coverage and document the wrapper contract.
This commit is contained in:
parent
091368be9f
commit
4d10f601d7
3 changed files with 62 additions and 27 deletions
|
|
@ -30,6 +30,7 @@
|
|||
- When a live Dockerized Agent Zero target is explicitly named, verify that exact runtime instead of assuming a fixed localhost port.
|
||||
- Message-loop completion flows through a response tool with `break_loop`; plain or malformed Chat Completions text enters repair, and native Responses output text is normalized through the same response-tool path.
|
||||
- Reuse the startup-preloaded local embedding model for matching runtime configurations; wrappers retain their own rate-limit configuration while sharing the underlying inference model.
|
||||
- Embedding wrappers expose batch-shaped `embed(inputs)` for provider-ready inputs; keep `embed_documents` and `embed_query` as LangChain compatibility adapters.
|
||||
- Prompt Markdown may retain fenced JSON examples for readability; final system-prompt rendering removes only their JSON fence markers before model calls and preserves non-JSON fences.
|
||||
- Copy live core-plugin changes back into tracked source under `plugins/`.
|
||||
- Develop new custom plugins under ignored `usr/plugins/`; tracked bundled plugins live under `plugins/`.
|
||||
|
|
|
|||
42
models.py
42
models.py
|
|
@ -800,15 +800,14 @@ class LiteLLMEmbeddingWrapper(Embeddings):
|
|||
self.model_name = f"{provider}/{model}"
|
||||
self.kwargs = kwargs
|
||||
self.a0_model_conf = model_config
|
||||
|
||||
def embed_documents(self, texts: List[str]) -> List[List[float]]:
|
||||
def embed(self, inputs: List[str]) -> List[List[float]]:
|
||||
"""Embed provider-ready inputs without assuming a text modality."""
|
||||
configure_litellm()
|
||||
# Apply rate limiting if configured
|
||||
apply_rate_limiter_sync(self.a0_model_conf, " ".join(texts))
|
||||
apply_rate_limiter_sync(self.a0_model_conf, " ".join(inputs))
|
||||
|
||||
resp = embedding(
|
||||
model=self.model_name,
|
||||
input=texts,
|
||||
input=inputs,
|
||||
**_merge_litellm_call_kwargs(self.kwargs),
|
||||
)
|
||||
return [
|
||||
|
|
@ -816,18 +815,11 @@ class LiteLLMEmbeddingWrapper(Embeddings):
|
|||
for item in resp.data # type: ignore
|
||||
]
|
||||
|
||||
def embed_query(self, text: str) -> List[float]:
|
||||
configure_litellm()
|
||||
# Apply rate limiting if configured
|
||||
apply_rate_limiter_sync(self.a0_model_conf, text)
|
||||
def embed_documents(self, texts: List[str]) -> List[List[float]]:
|
||||
return self.embed(texts)
|
||||
|
||||
resp = embedding(
|
||||
model=self.model_name,
|
||||
input=[text],
|
||||
**_merge_litellm_call_kwargs(self.kwargs),
|
||||
)
|
||||
item = resp.data[0] # type: ignore
|
||||
return item.get("embedding") if isinstance(item, dict) else item.embedding # type: ignore
|
||||
def embed_query(self, text: str) -> List[float]:
|
||||
return self.embed([text])[0]
|
||||
|
||||
|
||||
_LOCAL_EMBEDDING_MODELS: dict[tuple[str, str], SentenceTransformer] = {}
|
||||
|
|
@ -879,22 +871,18 @@ class LocalSentenceTransformerWrapper(Embeddings):
|
|||
self.model_name = model
|
||||
self.a0_model_conf = model_config
|
||||
|
||||
def embed_documents(self, texts: List[str]) -> List[List[float]]:
|
||||
def embed(self, inputs: List[str]) -> List[List[float]]:
|
||||
# Apply rate limiting if configured
|
||||
apply_rate_limiter_sync(self.a0_model_conf, " ".join(texts))
|
||||
apply_rate_limiter_sync(self.a0_model_conf, " ".join(inputs))
|
||||
|
||||
embeddings = self.model.encode(texts, convert_to_tensor=False) # type: ignore
|
||||
embeddings = self.model.encode(inputs, convert_to_tensor=False) # type: ignore
|
||||
return embeddings.tolist() if hasattr(embeddings, "tolist") else embeddings # type: ignore
|
||||
|
||||
def embed_query(self, text: str) -> List[float]:
|
||||
# Apply rate limiting if configured
|
||||
apply_rate_limiter_sync(self.a0_model_conf, text)
|
||||
def embed_documents(self, texts: List[str]) -> List[List[float]]:
|
||||
return self.embed(texts)
|
||||
|
||||
embedding = self.model.encode([text], convert_to_tensor=False) # type: ignore
|
||||
result = (
|
||||
embedding[0].tolist() if hasattr(embedding[0], "tolist") else embedding[0]
|
||||
)
|
||||
return result # type: ignore
|
||||
def embed_query(self, text: str) -> List[float]:
|
||||
return self.embed([text])[0]
|
||||
|
||||
|
||||
def _get_litellm_chat(
|
||||
|
|
|
|||
46
tests/test_multimodal_embeddings.py
Normal file
46
tests/test_multimodal_embeddings.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
from types import SimpleNamespace
|
||||
|
||||
import models
|
||||
|
||||
|
||||
def test_embed_forwards_provider_ready_inputs(monkeypatch):
|
||||
calls: list[dict] = []
|
||||
|
||||
def fake_embedding(**kwargs):
|
||||
calls.append(kwargs)
|
||||
return SimpleNamespace(
|
||||
data=[
|
||||
{"embedding": [float(index)]}
|
||||
for index, _ in enumerate(kwargs["input"])
|
||||
]
|
||||
)
|
||||
|
||||
monkeypatch.setattr(models, "embedding", fake_embedding)
|
||||
monkeypatch.setattr(models, "configure_litellm", lambda: None)
|
||||
monkeypatch.setattr(models, "_merge_litellm_call_kwargs", lambda kwargs: kwargs)
|
||||
monkeypatch.setattr(models, "apply_rate_limiter_sync", lambda *_args: None)
|
||||
wrapper = models.LiteLLMEmbeddingWrapper("gemini-embedding-2", "gemini")
|
||||
inputs = [
|
||||
"plain text",
|
||||
"data:image/png;base64,image",
|
||||
"data:audio/wav;base64,audio",
|
||||
"data:video/mp4;base64,video",
|
||||
]
|
||||
|
||||
assert wrapper.embed(inputs) == [[0.0], [1.0], [2.0], [3.0]]
|
||||
assert calls == [{"model": "gemini/gemini-embedding-2", "input": inputs}]
|
||||
|
||||
|
||||
def test_langchain_embedding_methods_use_embed_entry_point():
|
||||
wrapper = models.LiteLLMEmbeddingWrapper("model", "provider")
|
||||
calls: list[list[str]] = []
|
||||
|
||||
def fake_embed(inputs: list[str]) -> list[list[float]]:
|
||||
calls.append(inputs)
|
||||
return [[float(index)] for index, _ in enumerate(inputs)]
|
||||
|
||||
wrapper.embed = fake_embed # type: ignore[method-assign]
|
||||
|
||||
assert wrapper.embed_query("query") == [0.0]
|
||||
assert wrapper.embed_documents(["first", "second"]) == [[0.0], [1.0]]
|
||||
assert calls == [["query"], ["first", "second"]]
|
||||
Loading…
Add table
Add a link
Reference in a new issue