|
2 | 2 | # |
3 | 3 | # SPDX-License-Identifier: Apache-2.0 |
4 | 4 |
|
| 5 | +from typing import Annotated |
| 6 | + |
5 | 7 | import pytest |
6 | 8 |
|
7 | | -from haystack.dataclasses import ChatMessage, FileContent, ImageContent, TextContent, ToolCall |
8 | | -from haystack.token_counters.utils import _render_message, _rendered_conversation, _tool_result_text |
| 9 | +from haystack.dataclasses import ChatMessage, FileContent, ImageContent, ReasoningContent, TextContent, ToolCall |
| 10 | +from haystack.token_counters.utils import ( |
| 11 | + _non_text_placeholder, |
| 12 | + _render_message, |
| 13 | + _rendered_conversation, |
| 14 | + _rendered_tools, |
| 15 | + _tool_result_text, |
| 16 | +) |
| 17 | +from haystack.tools import tool |
9 | 18 |
|
10 | 19 | IMAGE = ImageContent(base64_image="Zm9v", mime_type="image/png") |
11 | 20 | FILE = FileContent(base64_data="Zm9v", mime_type="application/pdf", filename="report.pdf") |
@@ -65,3 +74,39 @@ def test_joins_messages_with_newlines(self): |
65 | 74 |
|
66 | 75 | def test_empty_conversation(self): |
67 | 76 | assert _rendered_conversation([]) == "" |
| 77 | + |
| 78 | + |
| 79 | +@tool |
| 80 | +def search(query: Annotated[str, "the search query"]) -> str: |
| 81 | + """Search the web for a query.""" |
| 82 | + return "result" |
| 83 | + |
| 84 | + |
| 85 | +class TestNonTextPlaceholder: |
| 86 | + @pytest.mark.parametrize( |
| 87 | + ("content", "expected"), |
| 88 | + [ |
| 89 | + pytest.param(IMAGE, "<image>", id="image"), |
| 90 | + pytest.param(FILE, "<file: report.pdf>", id="file-with-name"), |
| 91 | + pytest.param( |
| 92 | + FileContent(base64_data="Zm9v", mime_type="application/pdf"), "<file: unnamed>", id="file-unnamed" |
| 93 | + ), |
| 94 | + # Anything else falls back to naming its type, so an unexpected block still shows up in the text. |
| 95 | + pytest.param(ReasoningContent(reasoning_text="thinking"), "<ReasoningContent>", id="unknown-type"), |
| 96 | + ], |
| 97 | + ) |
| 98 | + def test_placeholder(self, content, expected): |
| 99 | + assert _non_text_placeholder(content) == expected |
| 100 | + |
| 101 | + |
| 102 | +class TestRenderedTools: |
| 103 | + def test_no_tools_renders_nothing(self): |
| 104 | + assert _rendered_tools(None) == "" |
| 105 | + assert _rendered_tools([]) == "" |
| 106 | + |
| 107 | + def test_renders_the_schema_a_provider_would_be_sent(self): |
| 108 | + rendered = _rendered_tools([search]) |
| 109 | + |
| 110 | + assert "search" in rendered |
| 111 | + assert "Search the web for a query." in rendered |
| 112 | + assert "the search query" in rendered |
0 commit comments