Skip to content
Draft
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
8 changes: 6 additions & 2 deletions agents-api/agents_api/autogen/Docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class HybridDocSearchRequest(BaseDocSearchRequest):
"""
Text to use in the search. In `hybrid` search mode, either `text` or both `text` and `vector` fields are required.
"""
vector: list[float]
vector: list[float] | None = None
"""
Vector to use in the search. Must be the same dimensions as the embedding model or else an error will be thrown.
"""
Expand Down Expand Up @@ -252,10 +252,14 @@ class VectorDocSearchRequest(BaseDocSearchRequest):
"""
The confidence cutoff level
"""
vector: list[float]
vector: list[float] | None = None
"""
Vector to use in the search. Must be the same dimensions as the embedding model or else an error will be thrown.
"""
text: str | None = None
"""
Text to use in the search. If `vector` is not provided, this text will be automatically embedded.
"""
mmr_strength: Annotated[float, Field(ge=0.0, lt=1.0)] = 0.5
"""
MMR Strength (mmr_strength = 1 - mmr_lambda)
Expand Down
37 changes: 36 additions & 1 deletion agents-api/agents_api/routers/docs/search_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from uuid import UUID

import numpy as np
from fastapi import Depends
from fastapi import Depends, HTTPException

from ...autogen.openapi_model import (
DocReference,
Expand All @@ -12,6 +12,7 @@
TextOnlyDocSearchRequest,
VectorDocSearchRequest,
)
from ...clients import litellm
from ...common.utils.get_doc_search import get_search_fn_and_params
from ...common.utils.mmr import apply_mmr_to_docs
from ...dependencies.developer_id import get_developer_id
Expand All @@ -37,6 +38,23 @@ async def search_user_docs(
DocSearchResponse: The search results.
"""

# AIDEV-NOTE: automatically embed text when only raw text is provided
if isinstance(search_params, VectorDocSearchRequest) and search_params.vector is None:
if not search_params.text:
raise HTTPException(status_code=400, detail="text is required for vector search")
[search_params.vector, *_] = await litellm.aembedding(
inputs=search_params.text,
embed_instruction="Represent the query for retrieving supporting documents: ",
user=str(x_developer_id),
)

if isinstance(search_params, HybridDocSearchRequest) and search_params.vector is None:
[search_params.vector, *_] = await litellm.aembedding(
inputs=search_params.text,
embed_instruction="Represent the query for retrieving supporting documents: ",
user=str(x_developer_id),
)
Comment on lines +43 to +56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't the addition of the text field mess up the union type for search_param parameter? By introducing text to the vector search and making vector field optional.

A suggestion would be adding a mode field to all search types to specify what type to use while searching.


# Get the search function and params here
search_fn, params = get_search_fn_and_params(search_params)

Expand Down Expand Up @@ -90,6 +108,23 @@ async def search_agent_docs(
DocSearchResponse: The search results.
"""

# AIDEV-NOTE: automatically embed text when only raw text is provided
if isinstance(search_params, VectorDocSearchRequest) and search_params.vector is None:
if not search_params.text:
raise HTTPException(status_code=400, detail="text is required for vector search")
[search_params.vector, *_] = await litellm.aembedding(
inputs=search_params.text,
embed_instruction="Represent the query for retrieving supporting documents: ",
user=str(x_developer_id),
)

if isinstance(search_params, HybridDocSearchRequest) and search_params.vector is None:
[search_params.vector, *_] = await litellm.aembedding(
inputs=search_params.text,
embed_instruction="Represent the query for retrieving supporting documents: ",
user=str(x_developer_id),
)

# Get the search function and params here
search_fn, params = get_search_fn_and_params(search_params)

Expand Down
48 changes: 48 additions & 0 deletions agents-api/tests/test_docs_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,54 @@ async def _(make_request=make_request, user=test_user, doc=test_user_doc):
assert len(docs) >= 1


@test("route: vector search with text only")
async def _(
make_request=make_request,
agent=test_agent,
doc=test_doc_with_embedding,
mocks=patch_embed_acompletion,
):
(embed, _) = mocks
search_params = {
"text": doc.content[0],
"confidence": 0.8,
"limit": 1,
}

response = make_request(
method="POST",
url=f"/agents/{agent.id}/search",
json=search_params,
)

assert response.status_code == 200
embed.assert_called()


@test("route: hybrid search with text only")
async def _(
make_request=make_request,
agent=test_agent,
doc=test_doc_with_embedding,
mocks=patch_embed_acompletion,
):
(embed, _) = mocks
search_params = {
"text": doc.content[0],
"alpha": 0.6,
"limit": 1,
}

response = make_request(
method="POST",
url=f"/agents/{agent.id}/search",
json=search_params,
)

assert response.status_code == 200
embed.assert_called()


@test("route: search agent docs hybrid with mmr")
async def _(make_request=make_request, agent=test_agent, doc=test_doc_with_embedding):
EMBEDDING_SIZE = 1024
Expand Down
27 changes: 20 additions & 7 deletions typespec/docs/models.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,17 @@ model VectorDocSearchRequest extends BaseDocSearchRequest {
@maxValue(1)
confidence: float = 0.5;

/** Vector to use in the search. Must be the same dimensions as the embedding model or else an error will be thrown. */
vector: float[];

text?: never;
/**
* Vector to use in the search. Must be the same dimensions as the embedding model
* or else an error will be thrown.
*/
vector?: float[];

/**
* Text to use for the search. If provided without `vector`, the server will
* automatically embed the text.
*/
text?: string;

/** MMR Strength (mmr_strength = 1 - mmr_lambda) */
@minValue(0)
Expand Down Expand Up @@ -158,11 +165,17 @@ model HybridDocSearchRequest extends BaseDocSearchRequest {
@maxValue(1)
alpha: float = 0.5;

/** Text to use in the search. In `hybrid` search mode, either `text` or both `text` and `vector` fields are required. */
/**
* Text to use in the search. In `hybrid` search mode, either `text` or both
* `text` and `vector` fields are required.
*/
text: string;

/** Vector to use in the search. Must be the same dimensions as the embedding model or else an error will be thrown. */
vector: float[];
/**
* Vector to use in the search. Must be the same dimensions as the embedding
* model or else an error will be thrown.
*/
vector?: float[];

/** MMR Strength (mmr_strength = 1 - mmr_lambda) */
@minValue(0)
Expand Down
Loading