-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(llama-index): capture tool calls from anthropic chat response (#1177
- Loading branch information
1 parent
8ca8826
commit e1ba6a5
Showing
10 changed files
with
178 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
...nce/instrumentation/llama_index/cassettes/TestToolCallsInChatResponse.test_anthropic.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
interactions: | ||
- request: | ||
body: '{"max_tokens":512,"messages":[{"role":"user","content":[{"text":"what''s | ||
the weather in San Francisco?","type":"text"}]}],"model":"claude-3-5-haiku-20241022","stream":false,"system":"","temperature":0.1,"tools":[{"name":"get_weather","description":"get_weather(location: | ||
str) -> str\nUseful for getting the weather for a given location.","input_schema":{"properties":{"location":{"title":"Location","type":"string"}},"required":["location"],"type":"object"}}]}' | ||
headers: {} | ||
method: POST | ||
uri: https://api.anthropic.com/v1/messages | ||
response: | ||
body: | ||
string: '{"id":"msg_011UbtsepYnQzWFNg8fDmFZ2","type":"message","role":"assistant","model":"claude-3-5-haiku-20241022","content":[{"type":"text","text":"I''ll | ||
help you check the weather in San Francisco right away."},{"type":"tool_use","id":"toolu_01P7dMjNQjMNZK8BB8sKP25k","name":"get_weather","input":{"location":"San | ||
Francisco"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":355,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":68}}' | ||
headers: {} | ||
status: | ||
code: 200 | ||
message: OK | ||
version: 1 |
29 changes: 29 additions & 0 deletions
29
...erence/instrumentation/llama_index/cassettes/TestToolCallsInChatResponse.test_openai.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
interactions: | ||
- request: | ||
body: '{"messages":[{"role":"user","content":"what''s the weather in San Francisco?"}],"model":"gpt-4o-mini","stream":false,"temperature":0.1,"tool_choice":"auto","tools":[{"type":"function","function":{"name":"get_weather","description":"get_weather(location: | ||
str) -> str\nUseful for getting the weather for a given location.","parameters":{"properties":{"location":{"title":"Location","type":"string"}},"required":["location"],"type":"object","additionalProperties":false},"strict":false}}]}' | ||
headers: {} | ||
method: POST | ||
uri: https://api.openai.com/v1/chat/completions | ||
response: | ||
body: | ||
string: "{\n \"id\": \"chatcmpl-AgcDNYhR5NPYhy2hmtnkm6CP8GFAN\",\n \"object\": | ||
\"chat.completion\",\n \"created\": 1734720037,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n | ||
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": | ||
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n | ||
\ \"id\": \"call_FjpIANozIfaXzuQQnmhK0yD3\",\n \"type\": | ||
\"function\",\n \"function\": {\n \"name\": \"get_weather\",\n | ||
\ \"arguments\": \"{\\\"location\\\":\\\"San Francisco\\\"}\"\n | ||
\ }\n }\n ],\n \"refusal\": null\n },\n | ||
\ \"logprobs\": null,\n \"finish_reason\": \"tool_calls\"\n }\n | ||
\ ],\n \"usage\": {\n \"prompt_tokens\": 68,\n \"completion_tokens\": | ||
16,\n \"total_tokens\": 84,\n \"prompt_tokens_details\": {\n \"cached_tokens\": | ||
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": | ||
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": | ||
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"system_fingerprint\": | ||
\"fp_0aa8d3e20b\"\n}\n" | ||
headers: {} | ||
status: | ||
code: 200 | ||
message: OK | ||
version: 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
...n-llama-index/tests/openinference/instrumentation/llama_index/test_tool_calls_response.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
from importlib.metadata import version | ||
from json import loads | ||
from typing import Iterator, Tuple, cast | ||
|
||
import pytest | ||
from llama_index.core.llms.function_calling import FunctionCallingLLM | ||
from llama_index.core.tools import FunctionTool | ||
from llama_index.llms.anthropic import Anthropic | ||
from llama_index.llms.openai import OpenAI | ||
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter | ||
from opentelemetry.trace import TracerProvider | ||
|
||
from openinference.instrumentation.llama_index import LlamaIndexInstrumentor | ||
from openinference.semconv.trace import MessageAttributes, SpanAttributes, ToolCallAttributes | ||
|
||
LLAMA_INDEX_LLMS_OPENAI_VERSION = cast( | ||
Tuple[int, int], tuple(map(int, version("llama_index.llms.openai").split(".")[:2])) | ||
) | ||
LLAMA_INDEX_LLMS_ANTHROPIC_VERSION = cast( | ||
Tuple[int, int], tuple(map(int, version("llama_index.llms.anthropic").split(".")[:2])) | ||
) | ||
|
||
|
||
def get_weather(location: str) -> str: | ||
"""Useful for getting the weather for a given location.""" | ||
raise NotImplementedError | ||
|
||
|
||
TOOL = FunctionTool.from_defaults(get_weather) | ||
|
||
|
||
class TestToolCallsInChatResponse: | ||
@pytest.mark.skipif( | ||
LLAMA_INDEX_LLMS_OPENAI_VERSION < (0, 3), | ||
reason="ignore older versions to simplify test upkeep", | ||
) | ||
@pytest.mark.vcr( | ||
decode_compressed_response=True, | ||
before_record_request=lambda _: _.headers.clear() or _, | ||
before_record_response=lambda _: {**_, "headers": {}}, | ||
) | ||
async def test_openai( | ||
self, | ||
in_memory_span_exporter: InMemorySpanExporter, | ||
) -> None: | ||
llm = OpenAI(model="gpt-4o-mini", api_key="sk-") | ||
await self._test(llm, in_memory_span_exporter) | ||
|
||
@pytest.mark.skipif( | ||
LLAMA_INDEX_LLMS_ANTHROPIC_VERSION < (0, 6), | ||
reason="ignore older versions to simplify test upkeep", | ||
) | ||
@pytest.mark.vcr( | ||
decode_compressed_response=True, | ||
before_record_request=lambda _: _.headers.clear() or _, | ||
before_record_response=lambda _: {**_, "headers": {}}, | ||
) | ||
async def test_anthropic( | ||
self, | ||
in_memory_span_exporter: InMemorySpanExporter, | ||
) -> None: | ||
llm = Anthropic(model="claude-3-5-haiku-20241022", api_key="sk-") | ||
await self._test(llm, in_memory_span_exporter) | ||
|
||
@classmethod | ||
async def _test( | ||
cls, | ||
llm: FunctionCallingLLM, | ||
in_memory_span_exporter: InMemorySpanExporter, | ||
) -> None: | ||
await llm.achat( | ||
**llm._prepare_chat_with_tools([TOOL], "what's the weather in San Francisco?"), | ||
) | ||
spans = in_memory_span_exporter.get_finished_spans() | ||
span = spans[-1] | ||
assert span.attributes | ||
assert span.attributes.get(f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.0.{TOOL_CALL_ID}") | ||
assert ( | ||
span.attributes.get( | ||
f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.0.{TOOL_CALL_FUNCTION_NAME}" | ||
) | ||
== "get_weather" | ||
) | ||
assert isinstance( | ||
arguments := span.attributes.get( | ||
f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.0.{TOOL_CALL_FUNCTION_ARGUMENTS_JSON}" | ||
), | ||
str, | ||
) | ||
assert loads(arguments) == {"location": "San Francisco"} | ||
|
||
|
||
@pytest.fixture(autouse=True) | ||
def instrument( | ||
tracer_provider: TracerProvider, | ||
in_memory_span_exporter: InMemorySpanExporter, | ||
) -> Iterator[None]: | ||
LlamaIndexInstrumentor().instrument(tracer_provider=tracer_provider) | ||
yield | ||
LlamaIndexInstrumentor().uninstrument() | ||
|
||
|
||
LLM_OUTPUT_MESSAGES = SpanAttributes.LLM_OUTPUT_MESSAGES | ||
MESSAGE_TOOL_CALLS = MessageAttributes.MESSAGE_TOOL_CALLS | ||
MESSAGE_TOOL_CALL_ID = MessageAttributes.MESSAGE_TOOL_CALL_ID | ||
TOOL_CALL_ID = ToolCallAttributes.TOOL_CALL_ID | ||
TOOL_CALL_FUNCTION_ARGUMENTS_JSON = ToolCallAttributes.TOOL_CALL_FUNCTION_ARGUMENTS_JSON | ||
TOOL_CALL_FUNCTION_NAME = ToolCallAttributes.TOOL_CALL_FUNCTION_NAME |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters