5656import org .springframework .context .annotation .Bean ;
5757import org .springframework .core .convert .support .DefaultConversionService ;
5858import org .springframework .core .io .Resource ;
59+ import org .springframework .http .ResponseEntity ;
60+ import org .springframework .util .StringUtils ;
5961
6062import static org .assertj .core .api .Assertions .assertThat ;
6163
7072 */
7173@ SpringBootTest (classes = DeepSeekWithOpenAiChatModelIT .Config .class )
7274@ EnabledIfEnvironmentVariable (named = "DEEPSEEK_API_KEY" , matches = ".+" )
73- @ Disabled ("Requires DeepSeek credits" )
7475class DeepSeekWithOpenAiChatModelIT {
7576
7677 private static final Logger logger = LoggerFactory .getLogger (DeepSeekWithOpenAiChatModelIT .class );
@@ -82,6 +83,9 @@ class DeepSeekWithOpenAiChatModelIT {
8283 @ Value ("classpath:/prompts/system-message.st" )
8384 private Resource systemResource ;
8485
86+ @ Autowired
87+ private OpenAiApi openAiApi ;
88+
8589 @ Autowired
8690 private OpenAiChatModel chatModel ;
8791
@@ -128,9 +132,9 @@ void streamingWithTokenUsage() {
128132 var streamingTokenUsage = this .chatModel .stream (prompt ).blockLast ().getMetadata ().getUsage ();
129133 var referenceTokenUsage = this .chatModel .call (prompt ).getMetadata ().getUsage ();
130134
131- assertThat (streamingTokenUsage .getPromptTokens ()).isGreaterThan ( 0 );
132- assertThat (streamingTokenUsage .getCompletionTokens ()).isGreaterThan ( 0 );
133- assertThat (streamingTokenUsage .getTotalTokens ()).isGreaterThan ( 0 );
135+ assertThat (streamingTokenUsage .getPromptTokens ()).isPositive ( );
136+ assertThat (streamingTokenUsage .getCompletionTokens ()).isPositive ( );
137+ assertThat (streamingTokenUsage .getTotalTokens ()).isPositive ( );
134138
135139 assertThat (streamingTokenUsage .getPromptTokens ()).isEqualTo (referenceTokenUsage .getPromptTokens ());
136140 assertThat (streamingTokenUsage .getCompletionTokens ()).isEqualTo (referenceTokenUsage .getCompletionTokens ());
@@ -325,6 +329,56 @@ record ActorsFilmsRecord(String actor, List<String> movies) {
325329
326330 }
327331
332+ @ Test
333+ void chatCompletionEntityWithReasoning () {
334+ OpenAiApi .ChatCompletionMessage chatCompletionMessage = new OpenAiApi .ChatCompletionMessage (
335+ "Explain the theory of relativity" , OpenAiApi .ChatCompletionMessage .Role .USER );
336+ OpenAiApi .ChatCompletionRequest request = new OpenAiApi .ChatCompletionRequest (List .of (chatCompletionMessage ),
337+ "deepseek-reasoner" , 0.8 , false );
338+ ResponseEntity <OpenAiApi .ChatCompletion > response = this .openAiApi .chatCompletionEntity (request );
339+
340+ assertThat (response ).isNotNull ();
341+ assertThat (response .getBody ().choices ().get (0 ).message ().reasoningContent ()).isNotBlank ();
342+ }
343+
344+ @ Test
345+ void chatCompletionStreamWithReasoning () {
346+ OpenAiApi .ChatCompletionMessage chatCompletionMessage = new OpenAiApi .ChatCompletionMessage (
347+ "Explain the theory of relativity" , OpenAiApi .ChatCompletionMessage .Role .USER );
348+ OpenAiApi .ChatCompletionRequest request = new OpenAiApi .ChatCompletionRequest (List .of (chatCompletionMessage ),
349+ "deepseek-reasoner" , 0.8 , true );
350+ Flux <OpenAiApi .ChatCompletionChunk > response = this .openAiApi .chatCompletionStream (request );
351+
352+ assertThat (response ).isNotNull ();
353+ List <OpenAiApi .ChatCompletionChunk > chunks = response .collectList ().block ();
354+ assertThat (chunks ).isNotNull ();
355+ assertThat (chunks .stream ().anyMatch (chunk -> !chunk .choices ().get (0 ).delta ().reasoningContent ().isBlank ()))
356+ .isTrue ();
357+ }
358+
359+ @ Test
360+ void chatModelCallWithReasoning () {
361+ OpenAiChatModel deepReasoner = new OpenAiChatModel (this .openAiApi ,
362+ OpenAiChatOptions .builder ().model ("deepseek-reasoner" ).build ());
363+ ChatResponse chatResponse = deepReasoner .call (new Prompt ("Explain the theory of relativity" ));
364+ assertThat (chatResponse .getResults ()).isNotEmpty ();
365+ assertThat (chatResponse .getResults ().get (0 ).getOutput ().getMetadata ().get ("reasoningContent" ).toString ())
366+ .isNotBlank ();
367+ }
368+
369+ @ Test
370+ void chatModelStreamWithReasoning () {
371+ OpenAiChatModel deepReasoner = new OpenAiChatModel (this .openAiApi ,
372+ OpenAiChatOptions .builder ().model ("deepseek-reasoner" ).build ());
373+ Flux <ChatResponse > flux = deepReasoner .stream (new Prompt ("Explain the theory of relativity" ));
374+ List <ChatResponse > responses = flux .collectList ().block ();
375+ assertThat (responses ).isNotEmpty ();
376+ assertThat (responses .stream ()
377+ .flatMap (response -> response .getResults ().stream ())
378+ .map (result -> result .getOutput ().getMetadata ().get ("reasoningContent" ).toString ())
379+ .anyMatch (StringUtils ::hasText )).isTrue ();
380+ }
381+
328382 @ SpringBootConfiguration
329383 static class Config {
330384
0 commit comments