Open I-am-DJ opened 1 month ago
我尝试修改了下com.theokanning.openai.service.OpenAiService#mapStreamToAccumulator和com.theokanning.openai.service.ChatFunctionCallArgumentsSerializerAndDeserializer.Deserializer#deserialize代码:
public static class Deserializer extends JsonDeserializer<JsonNode> {
private Deserializer() {
}
@Override
public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String json = p.getValueAsString();
if (json == null || p.currentToken() == JsonToken.VALUE_NULL) {
return null;
}
// ADDED
json = MAPPER.writeValueAsString(json);
// END ADDED
try {
JsonNode node = null;
try {
node = MAPPER.readTree(json);
} catch (JsonParseException ignored) {
}
if (node == null || node.getNodeType() == JsonNodeType.MISSING) {
node = MAPPER.readTree(p);
}
return node;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}
public Flowable<ChatMessageAccumulator> mapStreamToAccumulator(Flowable<ChatCompletionChunk> flowable) {
ChatFunctionCall functionCall = new ChatFunctionCall(null, null);
ChatMessage accumulatedMessage = new ChatMessage(ChatMessageRole.ASSISTANT.value(), null);
return flowable.map(chunk -> {
ChatMessage messageChunk = chunk.getChoices().get(0).getMessage();
ChatFunctionCall chunkFunctionCall = new ChatFunctionCall(null, null);
if (messageChunk.getFunctionCall() != null) {
if (messageChunk.getFunctionCall().getName() != null) {
String namePart = messageChunk.getFunctionCall().getName();
chunkFunctionCall.setName((functionCall.getName() == null ? "" : functionCall.getName()) + namePart);
}
if (messageChunk.getFunctionCall().getArguments() != null) {
String argumentsPart = messageChunk.getFunctionCall().getArguments().asText();
chunkFunctionCall.setArguments(new TextNode((functionCall.getArguments() == null ? "" : functionCall.getArguments().asText()) + argumentsPart));
}
accumulatedMessage.setFunctionCall(functionCall);
} else {
accumulatedMessage.setContent((accumulatedMessage.getContent() == null ? "" : accumulatedMessage.getContent()) + (messageChunk.getContent() == null ? "" : messageChunk.getContent()));
}
if (chunk.getChoices().get(0).getFinishReason() != null) { // last
if (chunkFunctionCall.getArguments() != null) {
functionCall.setName(chunkFunctionCall.getName());
functionCall.setArguments(mapper.readTree(chunkFunctionCall.getArguments().asText()));
accumulatedMessage.setFunctionCall(functionCall);
}
}
return new ChatMessageAccumulator(messageChunk, accumulatedMessage);
});
修改mapStreamToAccumulator的主要原因是flow会返回两次带有finishReason的情况,第一次存在functioncall,第二次没有,导致原有代码会进入两次last注释下的代码,原有的readTree函数返回的Node类型为ObjectNode,再次进入后调用asText()函数会导致数据为空字符串,所以采用chunkFunctionCall局部变量的方式fix该问题
这个是我的示例代码:
对应的报错信息,在String location = functionCall.getArguments().get("location").asText();该行报错
debug代码查看 com.theokanning.openai.service.OpenAiService#mapStreamToAccumulator方法中messageChunk中的arguments类型为objectNode,从而导致asText()方法返回的结果为""
请问我可以用什么简单的方法在不修改源代码的情况下来解决这个问题,非常感谢!