mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-02-08 14:44:57 +08:00
百度 文心一言 适配chatOptions
This commit is contained in:
parent
1fada268ac
commit
f41e43713c
@ -1,10 +1,8 @@
|
|||||||
package cn.iocoder.yudao.framework.ai.chatyiyan;
|
package cn.iocoder.yudao.framework.ai.chatyiyan;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.ai.chat.ChatClient;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.iocoder.yudao.framework.ai.chat.ChatResponse;
|
import cn.iocoder.yudao.framework.ai.chat.*;
|
||||||
import cn.iocoder.yudao.framework.ai.chat.Generation;
|
import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions;
|
||||||
import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient;
|
|
||||||
import cn.iocoder.yudao.framework.ai.chat.messages.Message;
|
|
||||||
import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt;
|
import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt;
|
||||||
import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion;
|
import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion;
|
||||||
import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest;
|
import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest;
|
||||||
@ -18,7 +16,6 @@ import org.springframework.retry.support.RetryTemplate;
|
|||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,10 +29,17 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient {
|
|||||||
|
|
||||||
private YiYanApi yiYanApi;
|
private YiYanApi yiYanApi;
|
||||||
|
|
||||||
|
private YiYanOptions yiYanOptions;
|
||||||
|
|
||||||
public YiYanChatClient(YiYanApi yiYanApi) {
|
public YiYanChatClient(YiYanApi yiYanApi) {
|
||||||
this.yiYanApi = yiYanApi;
|
this.yiYanApi = yiYanApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public YiYanChatClient(YiYanApi yiYanApi, YiYanOptions yiYanOptions) {
|
||||||
|
this.yiYanApi = yiYanApi;
|
||||||
|
this.yiYanOptions = yiYanOptions;
|
||||||
|
}
|
||||||
|
|
||||||
public final RetryTemplate retryTemplate = RetryTemplate.builder()
|
public final RetryTemplate retryTemplate = RetryTemplate.builder()
|
||||||
// 最大重试次数 10
|
// 最大重试次数 10
|
||||||
.maxAttempts(10)
|
.maxAttempts(10)
|
||||||
@ -70,20 +74,6 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) {
|
|
||||||
List<YiYanChatCompletionRequest.Message> messages = new ArrayList<>();
|
|
||||||
List<Message> instructions = prompt.getInstructions();
|
|
||||||
for (Message instruction : instructions) {
|
|
||||||
YiYanChatCompletionRequest.Message message = new YiYanChatCompletionRequest.Message();
|
|
||||||
message.setContent(instruction.getContent());
|
|
||||||
message.setRole(instruction.getMessageType().getValue());
|
|
||||||
messages.add(message);
|
|
||||||
}
|
|
||||||
YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messages);
|
|
||||||
request.setStream(stream);
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Flux<ChatResponse> stream(Prompt prompt) {
|
public Flux<ChatResponse> stream(Prompt prompt) {
|
||||||
// ctx 会有重试的信息
|
// ctx 会有重试的信息
|
||||||
@ -93,4 +83,35 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient {
|
|||||||
Flux<YiYanChatCompletion> response = this.yiYanApi.chatCompletionStream(request);
|
Flux<YiYanChatCompletion> response = this.yiYanApi.chatCompletionStream(request);
|
||||||
return response.map(res -> new ChatResponse(List.of(new Generation(res.getResult()))));
|
return response.map(res -> new ChatResponse(List.of(new Generation(res.getResult()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) {
|
||||||
|
// 两个都为null 则没有配置文件
|
||||||
|
if (yiYanOptions == null && prompt.getOptions() == null) {
|
||||||
|
throw new ChatException("ChatOptions 未配置参数!");
|
||||||
|
}
|
||||||
|
// 优先使用 Prompt 里面的 ChatOptions
|
||||||
|
ChatOptions options = yiYanOptions;
|
||||||
|
if (prompt.getOptions() != null) {
|
||||||
|
options = (ChatOptions) prompt.getOptions();
|
||||||
|
}
|
||||||
|
// Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断
|
||||||
|
if (!(options instanceof YiYanOptions)) {
|
||||||
|
throw new ChatException("Prompt 传入的不是 YiYanOptions!");
|
||||||
|
}
|
||||||
|
// 转换 YiYanOptions
|
||||||
|
YiYanOptions qianWenOptions = (YiYanOptions) options;
|
||||||
|
// 创建 request
|
||||||
|
List<YiYanChatCompletionRequest.Message> messageList = prompt.getInstructions().stream().map(
|
||||||
|
msg -> new YiYanChatCompletionRequest.Message()
|
||||||
|
.setRole(msg.getMessageType().getValue())
|
||||||
|
.setContent(msg.getContent())
|
||||||
|
).toList();
|
||||||
|
YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messageList);
|
||||||
|
// 复制 qianWenOptions 属性取 request(这里 options 属性和 request 基本保持一致)
|
||||||
|
// top: 由于遵循 spring-ai规范,支持在构建client的时候传入默认的 chatOptions
|
||||||
|
BeanUtil.copyProperties(qianWenOptions, request);
|
||||||
|
// 设置 stream
|
||||||
|
request.setStream(stream);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,144 @@
|
|||||||
|
package cn.iocoder.yudao.framework.ai.chatyiyan;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions;
|
||||||
|
import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 百度 问心一言
|
||||||
|
*
|
||||||
|
* 文档地址:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t
|
||||||
|
*
|
||||||
|
* author: fansili
|
||||||
|
* time: 2024/3/16 19:33
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class YiYanOptions implements ChatOptions {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一个可触发函数的描述列表,说明:
|
||||||
|
* (1)支持的function数量无限制
|
||||||
|
* (2)长度限制,最后一个message的content长度(即此轮对话的问题)、functions和system字段总内容不能超过20480 个字符,且不能超过5120 tokens
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private List<YiYanChatCompletionRequest.Function> functions;
|
||||||
|
/**
|
||||||
|
* 说明:
|
||||||
|
* (1)较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定
|
||||||
|
* (2)默认0.8,范围 (0, 1.0],不能为0
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private Float temperature;
|
||||||
|
/**
|
||||||
|
* 说明:
|
||||||
|
* (1)影响输出文本的多样性,取值越大,生成文本的多样性越强
|
||||||
|
* (2)默认0.8,取值范围 [0, 1.0]
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private Float top_p;
|
||||||
|
/**
|
||||||
|
* 通过对已生成的token增加惩罚,减少重复生成的现象。说明:
|
||||||
|
* (1)值越大表示惩罚越大
|
||||||
|
* (2)默认1.0,取值范围:[1.0, 2.0]
|
||||||
|
*
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private Float penalty_score;
|
||||||
|
/**
|
||||||
|
* 是否以流式接口的形式返回数据,默认false
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private Boolean stream;
|
||||||
|
/**
|
||||||
|
* 模型人设,主要用于人设设定,例如,你是xxx公司制作的AI助手,说明:
|
||||||
|
* (1)长度限制,最后一个message的content长度(即此轮对话的问题)、functions和system字段总内容不能超过20480 个字符,且不能超过5120 tokens
|
||||||
|
* (2)如果同时使用system和functions,可能暂无法保证使用效果,持续进行优化
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private String system;
|
||||||
|
/**
|
||||||
|
* 生成停止标识,当模型生成结果以stop中某个元素结尾时,停止文本生成。说明:
|
||||||
|
* (1)每个元素长度不超过20字符
|
||||||
|
* (2)最多4个元素
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private List<String> stop;
|
||||||
|
/**
|
||||||
|
* 是否强制关闭实时搜索功能,默认false,表示不关闭
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private Boolean disable_search;
|
||||||
|
/**
|
||||||
|
* 是否开启上角标返回,说明:
|
||||||
|
* (1)开启后,有概率触发搜索溯源信息search_info,search_info内容见响应参数介绍
|
||||||
|
* (2)默认false,不开启
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private Boolean enable_citation;
|
||||||
|
/**
|
||||||
|
* 指定模型最大输出token数,范围[2, 2048]
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private Integer max_output_tokens;
|
||||||
|
/**
|
||||||
|
* 指定响应内容的格式,说明:
|
||||||
|
* (1)可选值:
|
||||||
|
* · json_object:以json格式返回,可能出现不满足效果情况
|
||||||
|
* · text:以文本格式返回
|
||||||
|
* (2)如果不填写参数response_format值,默认为text
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private String response_format;
|
||||||
|
/**
|
||||||
|
* 表示最终用户的唯一标识符
|
||||||
|
* 必填:否
|
||||||
|
*/
|
||||||
|
private String user_id;
|
||||||
|
/**
|
||||||
|
* 在函数调用场景下,提示大模型选择指定的函数(非强制),说明:指定的函数名必须在functions中存在
|
||||||
|
* 必填:否
|
||||||
|
*
|
||||||
|
* ERNIE-4.0-8K 模型没有这个字段
|
||||||
|
*/
|
||||||
|
private String tool_choice;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 以下兼容 spring-ai ChatOptions 暂时没有其他地方用到
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Float getTemperature() {
|
||||||
|
return this.temperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTemperature(Float temperature) {
|
||||||
|
this.temperature = temperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Float getTopP() {
|
||||||
|
return top_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTopP(Float topP) {
|
||||||
|
this.top_p = topP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 百度么有 topK
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getTopK() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTopK(Integer topK) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -37,14 +37,14 @@ public class YiYanChatCompletionRequest {
|
|||||||
* (2)默认0.8,范围 (0, 1.0],不能为0
|
* (2)默认0.8,范围 (0, 1.0],不能为0
|
||||||
* 必填:否
|
* 必填:否
|
||||||
*/
|
*/
|
||||||
private String temperature;
|
private Float temperature;
|
||||||
/**
|
/**
|
||||||
* 说明:
|
* 说明:
|
||||||
* (1)影响输出文本的多样性,取值越大,生成文本的多样性越强
|
* (1)影响输出文本的多样性,取值越大,生成文本的多样性越强
|
||||||
* (2)默认0.8,取值范围 [0, 1.0]
|
* (2)默认0.8,取值范围 [0, 1.0]
|
||||||
* 必填:否
|
* 必填:否
|
||||||
*/
|
*/
|
||||||
private String top_p;
|
private Float top_p;
|
||||||
/**
|
/**
|
||||||
* 通过对已生成的token增加惩罚,减少重复生成的现象。说明:
|
* 通过对已生成的token增加惩罚,减少重复生成的现象。说明:
|
||||||
* (1)值越大表示惩罚越大
|
* (1)值越大表示惩罚越大
|
||||||
@ -52,7 +52,7 @@ public class YiYanChatCompletionRequest {
|
|||||||
*
|
*
|
||||||
* 必填:否
|
* 必填:否
|
||||||
*/
|
*/
|
||||||
private String penalty_score;
|
private Float penalty_score;
|
||||||
/**
|
/**
|
||||||
* 是否以流式接口的形式返回数据,默认false
|
* 是否以流式接口的形式返回数据,默认false
|
||||||
* 必填:否
|
* 必填:否
|
||||||
@ -71,7 +71,7 @@ public class YiYanChatCompletionRequest {
|
|||||||
* (2)最多4个元素
|
* (2)最多4个元素
|
||||||
* 必填:否
|
* 必填:否
|
||||||
*/
|
*/
|
||||||
private String stop;
|
private List<String> stop;
|
||||||
/**
|
/**
|
||||||
* 是否强制关闭实时搜索功能,默认false,表示不关闭
|
* 是否强制关闭实时搜索功能,默认false,表示不关闭
|
||||||
* 必填:否
|
* 必填:否
|
||||||
@ -106,6 +106,8 @@ public class YiYanChatCompletionRequest {
|
|||||||
/**
|
/**
|
||||||
* 在函数调用场景下,提示大模型选择指定的函数(非强制),说明:指定的函数名必须在functions中存在
|
* 在函数调用场景下,提示大模型选择指定的函数(非强制),说明:指定的函数名必须在functions中存在
|
||||||
* 必填:否
|
* 必填:否
|
||||||
|
*
|
||||||
|
* ERNIE-4.0-8K 模型没有这个字段
|
||||||
*/
|
*/
|
||||||
private String tool_choice;
|
private String tool_choice;
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ public class QianWenChatClientTests {
|
|||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
QianWenApi qianWenApi = new QianWenApi(
|
QianWenApi qianWenApi = new QianWenApi(
|
||||||
"",
|
"LTAI5tNTVhXW4fLKUjMrr98z",
|
||||||
"",
|
"ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP",
|
||||||
"",
|
"f0c1088824594f589c8f10567ccd929f_p_efm",
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
qianWenChatClient = new QianWenChatClient(
|
qianWenChatClient = new QianWenChatClient(
|
||||||
|
@ -4,12 +4,12 @@ import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt;
|
|||||||
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanApi;
|
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanApi;
|
||||||
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient;
|
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient;
|
||||||
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel;
|
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel;
|
||||||
|
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chat 文心一言
|
* chat 文心一言
|
||||||
@ -29,7 +29,7 @@ public class YiYanChatTests {
|
|||||||
YiYanChatModel.ERNIE4_3_5_8K,
|
YiYanChatModel.ERNIE4_3_5_8K,
|
||||||
86400
|
86400
|
||||||
);
|
);
|
||||||
yiYanChatClient = new YiYanChatClient(yiYanApi);
|
yiYanChatClient = new YiYanChatClient(yiYanApi, new YiYanOptions().setMax_output_tokens(2048));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -41,12 +41,7 @@ public class YiYanChatTests {
|
|||||||
@Test
|
@Test
|
||||||
public void streamTest() {
|
public void streamTest() {
|
||||||
Flux<ChatResponse> fluxResponse = yiYanChatClient.stream(new Prompt("用java帮我写一个快排算法?"));
|
Flux<ChatResponse> fluxResponse = yiYanChatClient.stream(new Prompt("用java帮我写一个快排算法?"));
|
||||||
fluxResponse.subscribe(new Consumer<ChatResponse>() {
|
fluxResponse.subscribe(chatResponse -> System.err.print(chatResponse.getResult().getOutput().getContent()));
|
||||||
@Override
|
|
||||||
public void accept(ChatResponse chatResponse) {
|
|
||||||
System.err.print(chatResponse.getResult().getOutput().getContent());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 阻止退出
|
// 阻止退出
|
||||||
Scanner scanner = new Scanner(System.in);
|
Scanner scanner = new Scanner(System.in);
|
||||||
scanner.nextLine();
|
scanner.nextLine();
|
||||||
|
Loading…
Reference in New Issue
Block a user