@@ -1912,6 +1912,67 @@ def _get_value(key: str) -> int:
19121912 "total_tokens" : _get_value ("total_tokens" ),
19131913 }
19141914
1915+ @staticmethod
1916+ def _get_response_field (obj : Any , key : str ) -> Any :
1917+ """Read a field from dict-like or object-like LiteLLM payloads."""
1918+ if isinstance (obj , dict ):
1919+ return obj .get (key )
1920+ return getattr (obj , key , None )
1921+
1922+ def _extract_text_blocks (self , blocks : Any ) -> str :
1923+ """Extract text from OpenAI-compatible content block lists."""
1924+ if not blocks :
1925+ return ""
1926+
1927+ parts : List [str ] = []
1928+ for block in blocks :
1929+ if isinstance (block , str ):
1930+ parts .append (block )
1931+ continue
1932+
1933+ text = None
1934+ if isinstance (block , dict ):
1935+ text = block .get ("text" )
1936+ if text is None :
1937+ text = block .get ("content" )
1938+ else :
1939+ text = getattr (block , "text" , None )
1940+ if text is None :
1941+ text = getattr (block , "content" , None )
1942+
1943+ if isinstance (text , str ) and text :
1944+ parts .append (text )
1945+
1946+ return "" .join (parts ).strip ()
1947+
1948+ def _extract_completion_text (self , response : Any ) -> str :
1949+ """Extract text from non-stream LiteLLM completion responses."""
1950+ choices = self ._get_response_field (response , "choices" )
1951+ if not choices :
1952+ return ""
1953+
1954+ choice = choices [0 ]
1955+ message = self ._get_response_field (choice , "message" )
1956+
1957+ content_blocks = self ._get_response_field (choice , "content_blocks" )
1958+ if content_blocks is None and message is not None :
1959+ content_blocks = self ._get_response_field (message , "content_blocks" )
1960+ block_text = self ._extract_text_blocks (content_blocks )
1961+ if block_text :
1962+ return block_text
1963+
1964+ content = None
1965+ if message is not None :
1966+ content = self ._get_response_field (message , "content" )
1967+ if content is None :
1968+ content = self ._get_response_field (choice , "content" )
1969+
1970+ if isinstance (content , list ):
1971+ return self ._extract_text_blocks (content )
1972+ if isinstance (content , str ):
1973+ return content .strip ()
1974+ return str (content ).strip () if content is not None else ""
1975+
19151976 def _extract_stream_text (self , chunk : Any ) -> str :
19161977 """Extract provider-agnostic text delta from a LiteLLM streaming chunk."""
19171978 choices = chunk .get ("choices" ) if isinstance (chunk , dict ) else getattr (chunk , "choices" , None )
@@ -2120,8 +2181,8 @@ def _call_litellm(
21202181 router_model_names = router_model_names ,
21212182 )
21222183
2123- if response and response . choices and response . choices [ 0 ]. message . content :
2124- content = response . choices [ 0 ]. message . content
2184+ content = self . _extract_completion_text ( response )
2185+ if content :
21252186 usage = self ._normalize_usage (getattr (response , "usage" , None ))
21262187 last_response_text = content
21272188 last_model = model
0 commit comments