@@ -1905,3 +1905,185 @@ async def test_streaming_redacted_thinking_block_preserved_in_final():
19051905
19061906 text_part = final .content .parts [1 ]
19071907 assert text_part .text == "Done."
1908+
1909+
1910+
1911+
1912+ # --- Tests for generation config parameter forwarding ---
1913+
1914+
1915+ def _make_minimal_stream (text = "Hi" ):
1916+ """Minimal streaming event sequence for param-forwarding tests."""
1917+ return [
1918+ MagicMock (
1919+ type = "message_start" ,
1920+ message = MagicMock (usage = MagicMock (input_tokens = 5 , output_tokens = 0 )),
1921+ ),
1922+ MagicMock (
1923+ type = "content_block_start" ,
1924+ index = 0 ,
1925+ content_block = anthropic_types .TextBlock (text = "" , type = "text" ),
1926+ ),
1927+ MagicMock (
1928+ type = "content_block_delta" ,
1929+ index = 0 ,
1930+ delta = anthropic_types .TextDelta (text = text , type = "text_delta" ),
1931+ ),
1932+ MagicMock (type = "content_block_stop" , index = 0 ),
1933+ MagicMock (
1934+ type = "message_delta" ,
1935+ delta = MagicMock (stop_reason = "end_turn" ),
1936+ usage = MagicMock (output_tokens = 1 ),
1937+ ),
1938+ MagicMock (type = "message_stop" ),
1939+ ]
1940+
1941+
1942+ @pytest .mark .asyncio
1943+ async def test_non_streaming_forwards_generation_params ():
1944+ """temperature, top_p, top_k, stop_sequences forwarded to messages.create."""
1945+ from anthropic import NOT_GIVEN
1946+
1947+ llm = AnthropicLlm (model = "claude-sonnet-4-20250514" )
1948+ mock_message = anthropic_types .Message (
1949+ id = "msg_test" ,
1950+ content = [anthropic_types .TextBlock (text = "Hi" , type = "text" , citations = None )],
1951+ model = "claude-sonnet-4-20250514" ,
1952+ role = "assistant" ,
1953+ stop_reason = "end_turn" ,
1954+ stop_sequence = None ,
1955+ type = "message" ,
1956+ usage = anthropic_types .Usage (
1957+ input_tokens = 5 ,
1958+ output_tokens = 2 ,
1959+ cache_creation_input_tokens = 0 ,
1960+ cache_read_input_tokens = 0 ,
1961+ server_tool_use = None ,
1962+ service_tier = None ,
1963+ ),
1964+ )
1965+ mock_client = MagicMock ()
1966+ mock_client .messages .create = AsyncMock (return_value = mock_message )
1967+
1968+ llm_request = LlmRequest (
1969+ model = "claude-sonnet-4-20250514" ,
1970+ contents = [Content (role = "user" , parts = [Part .from_text (text = "Hi" )])],
1971+ config = types .GenerateContentConfig (
1972+ system_instruction = "Test" ,
1973+ temperature = 0.7 ,
1974+ top_p = 0.9 ,
1975+ top_k = 40 ,
1976+ stop_sequences = ["STOP" , "END" ],
1977+ ),
1978+ )
1979+
1980+ with mock .patch .object (llm , "_anthropic_client" , mock_client ):
1981+ _ = [r async for r in llm .generate_content_async (llm_request , stream = False )]
1982+
1983+ _ , kwargs = mock_client .messages .create .call_args
1984+ assert kwargs ["temperature" ] == 0.7
1985+ assert kwargs ["top_p" ] == 0.9
1986+ assert kwargs ["top_k" ] == 40
1987+ assert kwargs ["stop_sequences" ] == ["STOP" , "END" ]
1988+
1989+
1990+ @pytest .mark .asyncio
1991+ async def test_non_streaming_omits_unset_generation_params ():
1992+ """Unset generation params should be NOT_GIVEN, not None."""
1993+ from anthropic import NOT_GIVEN
1994+
1995+ llm = AnthropicLlm (model = "claude-sonnet-4-20250514" )
1996+ mock_message = anthropic_types .Message (
1997+ id = "msg_test" ,
1998+ content = [anthropic_types .TextBlock (text = "Hi" , type = "text" , citations = None )],
1999+ model = "claude-sonnet-4-20250514" ,
2000+ role = "assistant" ,
2001+ stop_reason = "end_turn" ,
2002+ stop_sequence = None ,
2003+ type = "message" ,
2004+ usage = anthropic_types .Usage (
2005+ input_tokens = 5 ,
2006+ output_tokens = 2 ,
2007+ cache_creation_input_tokens = 0 ,
2008+ cache_read_input_tokens = 0 ,
2009+ server_tool_use = None ,
2010+ service_tier = None ,
2011+ ),
2012+ )
2013+ mock_client = MagicMock ()
2014+ mock_client .messages .create = AsyncMock (return_value = mock_message )
2015+
2016+ llm_request = LlmRequest (
2017+ model = "claude-sonnet-4-20250514" ,
2018+ contents = [Content (role = "user" , parts = [Part .from_text (text = "Hi" )])],
2019+ config = types .GenerateContentConfig (system_instruction = "Test" ),
2020+ )
2021+
2022+ with mock .patch .object (llm , "_anthropic_client" , mock_client ):
2023+ _ = [r async for r in llm .generate_content_async (llm_request , stream = False )]
2024+
2025+ _ , kwargs = mock_client .messages .create .call_args
2026+ assert kwargs ["temperature" ] is NOT_GIVEN
2027+ assert kwargs ["top_p" ] is NOT_GIVEN
2028+ assert kwargs ["top_k" ] is NOT_GIVEN
2029+ assert kwargs ["stop_sequences" ] is NOT_GIVEN
2030+
2031+
2032+ @pytest .mark .asyncio
2033+ async def test_streaming_forwards_generation_params ():
2034+ """temperature, top_p, top_k, stop_sequences forwarded in streaming path."""
2035+ from anthropic import NOT_GIVEN
2036+
2037+ llm = AnthropicLlm (model = "claude-sonnet-4-20250514" )
2038+ mock_client = MagicMock ()
2039+ mock_client .messages .create = AsyncMock (
2040+ return_value = _make_mock_stream_events (_make_minimal_stream ())
2041+ )
2042+
2043+ llm_request = LlmRequest (
2044+ model = "claude-sonnet-4-20250514" ,
2045+ contents = [Content (role = "user" , parts = [Part .from_text (text = "Hi" )])],
2046+ config = types .GenerateContentConfig (
2047+ system_instruction = "Test" ,
2048+ temperature = 0.5 ,
2049+ top_p = 0.8 ,
2050+ top_k = 20 ,
2051+ stop_sequences = ["DONE" ],
2052+ ),
2053+ )
2054+
2055+ with mock .patch .object (llm , "_anthropic_client" , mock_client ):
2056+ _ = [r async for r in llm .generate_content_async (llm_request , stream = True )]
2057+
2058+ _ , kwargs = mock_client .messages .create .call_args
2059+ assert kwargs ["temperature" ] == 0.5
2060+ assert kwargs ["top_p" ] == 0.8
2061+ assert kwargs ["top_k" ] == 20
2062+ assert kwargs ["stop_sequences" ] == ["DONE" ]
2063+
2064+
2065+ @pytest .mark .asyncio
2066+ async def test_streaming_omits_unset_generation_params ():
2067+ """Unset generation params should be NOT_GIVEN in streaming path."""
2068+ from anthropic import NOT_GIVEN
2069+
2070+ llm = AnthropicLlm (model = "claude-sonnet-4-20250514" )
2071+ mock_client = MagicMock ()
2072+ mock_client .messages .create = AsyncMock (
2073+ return_value = _make_mock_stream_events (_make_minimal_stream ())
2074+ )
2075+
2076+ llm_request = LlmRequest (
2077+ model = "claude-sonnet-4-20250514" ,
2078+ contents = [Content (role = "user" , parts = [Part .from_text (text = "Hi" )])],
2079+ config = types .GenerateContentConfig (system_instruction = "Test" ),
2080+ )
2081+
2082+ with mock .patch .object (llm , "_anthropic_client" , mock_client ):
2083+ _ = [r async for r in llm .generate_content_async (llm_request , stream = True )]
2084+
2085+ _ , kwargs = mock_client .messages .create .call_args
2086+ assert kwargs ["temperature" ] is NOT_GIVEN
2087+ assert kwargs ["top_p" ] is NOT_GIVEN
2088+ assert kwargs ["top_k" ] is NOT_GIVEN
2089+ assert kwargs ["stop_sequences" ] is NOT_GIVEN
0 commit comments