Skip to content

Commit

Permalink
Solve the problem of occasional incomplete response content. (langcha…
Browse files Browse the repository at this point in the history
…in4j#699)

It is now possible for Qwen models to return messages with content when
finishReason == STOP (but not always). compatible with this situation.

When finishReason != STOP, if the returned message has no content,
NullPointerException will still be thrown.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit


- **New Features**
- Enhanced conversation handling in the application with new methods for
checking and extracting answers.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
jiangsier-xyz authored Mar 11, 2024
1 parent 8fcd192 commit 6c49573
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ static String roleFrom(ChatMessage message) {
}
}

static boolean hasAnswer(GenerationResult result) {
return Optional.of(result)
.map(GenerationResult::getOutput)
.map(GenerationOutput::getChoices)
.filter(choices -> !choices.isEmpty())
.isPresent();
}

static String answerFrom(GenerationResult result) {
return Optional.of(result)
.map(GenerationResult::getOutput)
Expand All @@ -178,6 +186,18 @@ static String answerFrom(GenerationResult result) {
.orElseThrow(NullPointerException::new));
}

static boolean hasAnswer(MultiModalConversationResult result) {
return Optional.of(result)
.map(MultiModalConversationResult::getOutput)
.map(MultiModalConversationOutput::getChoices)
.filter(choices -> !choices.isEmpty())
.map(choices -> choices.get(0))
.map(MultiModalConversationOutput.Choice::getMessage)
.map(MultiModalMessage::getContent)
.filter(contents -> !contents.isEmpty())
.isPresent();
}

static String answerFrom(MultiModalConversationResult result) {
return Optional.of(result)
.map(MultiModalConversationResult::getOutput)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
import dev.langchain4j.model.output.Response;
import dev.langchain4j.model.output.TokenUsage;

import static dev.langchain4j.model.dashscope.QwenHelper.answerFrom;
import static dev.langchain4j.model.dashscope.QwenHelper.finishReasonFrom;
import static dev.langchain4j.model.dashscope.QwenHelper.*;

public class QwenStreamingResponseBuilder {
private final StringBuilder generatedContent = new StringBuilder();
Expand All @@ -37,7 +36,9 @@ public String append(GenerationResult partialResponse) {
FinishReason finishReason = finishReasonFrom(partialResponse);
if (finishReason != null) {
this.finishReason = finishReason;
return null;
if (!hasAnswer(partialResponse)) {
return null;
}
}

String partialContent = answerFrom(partialResponse);
Expand All @@ -60,7 +61,9 @@ public String append(MultiModalConversationResult partialResponse) {
FinishReason finishReason = finishReasonFrom(partialResponse);
if (finishReason != null) {
this.finishReason = finishReason;
return null;
if (!hasAnswer(partialResponse)) {
return null;
}
}

String partialContent = answerFrom(partialResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public void should_send_non_multimodal_messages_and_receive_response(String mode
System.out.println(response);

assertThat(response.content().text()).containsIgnoringCase("rain");
assertThat(response.content().text()).endsWith("That's all!");
}

@ParameterizedTest
Expand All @@ -42,6 +43,7 @@ public void should_send_multimodal_image_url_and_receive_response(String modelNa
System.out.println(response);

assertThat(response.content().text()).containsIgnoringCase("dog");
assertThat(response.content().text()).endsWith("That's all!");
}

@ParameterizedTest
Expand All @@ -57,5 +59,6 @@ public void should_send_multimodal_image_data_and_receive_response(String modelN
System.out.println(response);

assertThat(response.content().text()).containsIgnoringCase("parrot");
assertThat(response.content().text()).endsWith("That's all!");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,14 @@ public class QwenTestHelper {
public static Stream<Arguments> languageModelNameProvider() {
return Stream.of(
Arguments.of(QwenModelName.QWEN_TURBO),
Arguments.of(QwenModelName.QWEN_PLUS),
Arguments.of(QwenModelName.QWEN_7B_CHAT),
Arguments.of(QwenModelName.QWEN_14B_CHAT)
Arguments.of(QwenModelName.QWEN_PLUS)
);
}

public static Stream<Arguments> nonMultimodalChatModelNameProvider() {
return Stream.of(
Arguments.of(QwenModelName.QWEN_TURBO),
Arguments.of(QwenModelName.QWEN_PLUS),
Arguments.of(QwenModelName.QWEN_7B_CHAT),
Arguments.of(QwenModelName.QWEN_14B_CHAT)
Arguments.of(QwenModelName.QWEN_PLUS)
);
}

Expand All @@ -57,9 +53,10 @@ public static List<ChatMessage> chatMessages() {
List<ChatMessage> messages = new LinkedList<>();
messages.add(SystemMessage.from("Your name is Jack." +
" You like to answer other people's questions briefly." +
" It's rainy today."));
" It's rainy today." +
" When you're done, end with \"That's all!\"."));
messages.add(UserMessage.from("Hello. What's your name?"));
messages.add(AiMessage.from("Jack."));
messages.add(AiMessage.from("Jack. That's all!"));
messages.add(UserMessage.from("How about the weather today?"));
return messages;
}
Expand All @@ -69,7 +66,7 @@ public static List<ChatMessage> multimodalChatMessagesWithImageUrl() {
.url("https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg")
.build();
ImageContent imageContent = ImageContent.from(image);
TextContent textContent = TextContent.from("What animal is in the picture?");
TextContent textContent = TextContent.from("What animal is in the picture? When you're done, end with \"That's all!\".");
return Collections.singletonList(UserMessage.from(imageContent, textContent));
}

Expand All @@ -78,7 +75,7 @@ public static List<ChatMessage> multimodalChatMessagesWithImageData() {
.base64Data(multimodalImageData())
.build();
ImageContent imageContent = ImageContent.from(image);
TextContent textContent = TextContent.from("What animal is in the picture?");
TextContent textContent = TextContent.from("What animal is in the picture? When you're done, end with \"That's all!\".");
return Collections.singletonList(UserMessage.from(imageContent, textContent));
}

Expand Down

0 comments on commit 6c49573

Please sign in to comment.