Skip to content

Commit 27cadd7

Browse files
authored
Merge branch 'main' into cluster_health_main
2 parents 9b53c92 + c0feec0 commit 27cadd7

2 files changed

Lines changed: 152 additions & 74 deletions

File tree

tests/llama_stack/vector_io/test_vector_stores.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,82 @@ def test_vector_stores_search(
171171
LOGGER.info(f"Search mode {search_mode!r}: {len(queries)} queries returned results")
172172

173173
LOGGER.info(f"Successfully tested vector store search across modes: {search_modes}")
174+
175+
@pytest.mark.smoke
176+
def test_response_file_search_tool_invocation(
177+
self,
178+
unprivileged_llama_stack_client: LlamaStackClient,
179+
llama_stack_models: ModelInfo,
180+
vector_store_with_example_docs: VectorStore,
181+
) -> None:
182+
"""
183+
Test that the file_search tool is invoked and returns results via the responses API.
184+
185+
Given: A vector store with pre-uploaded documentation files
186+
When: A question requiring document knowledge is asked with the file_search tool
187+
Then: The response contains a file_search_call output with status 'completed',
188+
results with file_id and filename, and message annotations with file citations
189+
"""
190+
response = unprivileged_llama_stack_client.responses.create(
191+
input=IBM_EARNINGS_SEARCH_QUERIES_BY_MODE["vector"][0],
192+
model=llama_stack_models.model_id,
193+
instructions="Always use the file_search tool to look up information before answering.",
194+
stream=False,
195+
tools=[
196+
{
197+
"type": "file_search",
198+
"vector_store_ids": [vector_store_with_example_docs.id],
199+
}
200+
],
201+
)
202+
203+
# Verify file_search_call output exists (model invoked the file_search tool)
204+
file_search_calls = [item for item in response.output if item.type == "file_search_call"]
205+
assert file_search_calls, (
206+
"Expected a file_search_call output item in the response, indicating the model "
207+
f"invoked the file_search tool. Output types: {[item.type for item in response.output]}"
208+
)
209+
210+
file_search_call = file_search_calls[0]
211+
assert file_search_call.status == "completed", (
212+
f"Expected file_search_call status 'completed', got '{file_search_call.status}'"
213+
)
214+
215+
# Verify file_search returned results with file metadata
216+
assert file_search_call.results, "file_search_call should contain search results"
217+
218+
for result in file_search_call.results:
219+
assert result.file_id, "Search result must include a non-empty file_id"
220+
assert result.filename, "Search result must include a non-empty filename"
221+
assert result.text, "Search result must include non-empty text content"
222+
223+
LOGGER.info(
224+
f"file_search_call returned {len(file_search_call.results)} result(s). "
225+
f"Filenames: {[r.filename for r in file_search_call.results]}"
226+
)
227+
228+
# Verify the message contains file_citation annotations
229+
annotations = []
230+
for item in response.output:
231+
if item.type != "message" or not isinstance(item.content, list):
232+
continue
233+
for content_item in item.content:
234+
if content_item.annotations:
235+
annotations.extend(content_item.annotations)
236+
237+
assert annotations, "Response message should contain file_citation annotations when file_search returns results"
238+
239+
for annotation in annotations:
240+
assert annotation.type == "file_citation", (
241+
f"Expected annotation type 'file_citation', got '{annotation.type}'"
242+
)
243+
assert annotation.file_id, "Annotation must include a non-empty file_id"
244+
assert annotation.filename, "Annotation must include a non-empty filename"
245+
assert annotation.index is not None, "Annotation must include an index"
246+
247+
LOGGER.info(
248+
f"Found {len(annotations)} file_citation annotation(s). "
249+
f"File IDs: {[a.file_id for a in annotations]}. "
250+
f"Filenames: {[a.filename for a in annotations]}. "
251+
f"Indexes: {[a.index for a in annotations]}. "
252+
)

0 commit comments

Comments
 (0)