File size: 5,277 Bytes
447ebeb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
from abc import ABC, abstractmethod

import anthropic
import pytest


class BaseAnthropicMessagesTest(ABC):
    """
    Abstract base test class that enforces a common test across all test classes.
    """

    @abstractmethod
    def get_client(self):
        return anthropic.Anthropic()

    def test_anthropic_basic_completion(self):
        print("making basic completion request to anthropic passthrough")
        client = self.get_client()
        response = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1024,
            messages=[{"role": "user", "content": "Say 'hello test' and nothing else"}],
            extra_body={
                "litellm_metadata": {
                    "tags": ["test-tag-1", "test-tag-2"],
                }
            },
        )
        print(response)

    def test_anthropic_streaming(self):
        print("making streaming request to anthropic passthrough")
        collected_output = []
        client = self.get_client()
        with client.messages.stream(
            max_tokens=10,
            messages=[
                {"role": "user", "content": "Say 'hello stream test' and nothing else"}
            ],
            model="claude-3-5-sonnet-20241022",
            extra_body={
                "litellm_metadata": {
                    "tags": ["test-tag-stream-1", "test-tag-stream-2"],
                }
            },
        ) as stream:
            for text in stream.text_stream:
                collected_output.append(text)

        full_response = "".join(collected_output)
        print(full_response)

    def test_anthropic_messages_with_thinking(self):
        print("making request to anthropic passthrough with thinking")
        client = self.get_client()
        response = client.messages.create(
            model="claude-3-7-sonnet-20250219",
            max_tokens=20000,
            thinking={"type": "enabled", "budget_tokens": 16000},
            messages=[
                {"role": "user", "content": "Just pinging with thinking enabled"}
            ],
        )

        print(response)

        # Verify the first content block is a thinking block
        response_thinking = response.content[0].thinking
        assert response_thinking is not None
        assert len(response_thinking) > 0

    def test_anthropic_streaming_with_thinking(self):
        print("making streaming request to anthropic passthrough with thinking enabled")
        collected_thinking = []
        collected_response = []
        client = self.get_client()
        with client.messages.stream(
            model="claude-3-7-sonnet-20250219",
            max_tokens=20000,
            thinking={"type": "enabled", "budget_tokens": 16000},
            messages=[
                {"role": "user", "content": "Just pinging with thinking enabled"}
            ],
        ) as stream:
            for event in stream:
                if event.type == "content_block_delta":
                    if event.delta.type == "thinking_delta":
                        collected_thinking.append(event.delta.thinking)
                    elif event.delta.type == "text_delta":
                        collected_response.append(event.delta.text)

        full_thinking = "".join(collected_thinking)
        full_response = "".join(collected_response)

        print(
            f"Thinking Response: {full_thinking[:100]}..."
        )  # Print first 100 chars of thinking
        print(f"Response: {full_response}")

        # Verify we received thinking content
        assert len(collected_thinking) > 0
        assert len(full_thinking) > 0

        # Verify we also received a response
        assert len(collected_response) > 0
        assert len(full_response) > 0

    def test_bad_request_error_handling_streaming(self):
        print("making request to anthropic passthrough with bad request")
        try:
            client = self.get_client()
            response = client.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=10,
                stream=True,
                messages=["hi"],
            )
            print(response)
            assert pytest.fail("Expected BadRequestError")
        except anthropic.BadRequestError as e:
            print("Got BadRequestError from anthropic, e=", e)
            print(e.__cause__)
            print(e.status_code)
            print(e.response)
        except Exception as e:
            pytest.fail(f"Got unexpected exception: {e}")

    def test_bad_request_error_handling_non_streaming(self):
        print("making request to anthropic passthrough with bad request")
        try:
            client = self.get_client()
            response = client.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=10,
                messages=["hi"],
            )
            print(response)
            assert pytest.fail("Expected BadRequestError")
        except anthropic.BadRequestError as e:
            print("Got BadRequestError from anthropic, e=", e)
            print(e.__cause__)
            print(e.status_code)
            print(e.response)
        except Exception as e:
            pytest.fail(f"Got unexpected exception: {e}")