Skip to content

Commit

Permalink
feat:
Browse files Browse the repository at this point in the history
1、对话新增文档模式与联网模式。联网模式实现了百度网页搜索、bing搜索、google搜索。
2、新增支持kimi大模型。
refactor:
1、优化对话页面布局,将部分按钮移至右侧面板。
  • Loading branch information
hkh1012 committed Apr 3, 2024
1 parent 966758d commit 6b962b4
Show file tree
Hide file tree
Showing 35 changed files with 1,442 additions and 69 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@
| openai | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| 百度(文心) | 支持 | 支持 | - | 支持 | 支持 | - | 支持 |
| 智谱(GLM-4) | 支持 | 支持 | - | 支持 | 支持 | 支持 | 支持 |
| kimi | 支持 | 支持 | - | - | - | - | - |
| chatglm2 | 支持 | 支持 | - | - | - | - | - |
| ... ... | - | - | - | - | - | - |- |

## 功能路线图
已完成本地知识库上传及完成openaichatglm2百度智谱GLM-4四个LLMs模型流式聊天功能未来计划会接入更多大语言模型以满足更多需求场景
已完成本地知识库上传及完成openaichatglm2百度智谱GLM-4kimi五个LLMs模型流式聊天功能未来计划会接入更多大语言模型以满足更多需求场景
- [ ] Langchain 知识库
- [x] 接入非结构化文档已支持 mdpdfdocxtxtcsv 等文件格式
- [ ] 搜索引擎接入
- [x] 搜索引擎接入
- [ ] 结构化数据接入如ExcelSQL
- [ ] 知识图谱/图数据库接入
- [ ] 系统功能
Expand All @@ -49,7 +50,7 @@
- [x] 语音输入输出
- [x] 会话管理
- [x] 知识库管理
- [ ] 支持搜索引擎问答
- [x] 支持搜索引擎问答
- [ ] prompts相关功能
- [x] 摘要
- [x] 翻译
Expand Down
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<artifactId>langchain-springboot</artifactId>
<version>1.0.0</version>
<name>langchain-springboot</name>
<packaging>jar</packaging>
<description>SpringBoot整合AI模型</description>
<properties>
<java.version>17</java.version>
Expand Down Expand Up @@ -211,6 +212,11 @@
<artifactId>pinyin4j</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>me.zhyd.oauth</groupId>-->
<!-- <artifactId>JustAuth</artifactId>-->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.hkh.ai.chain.llm.capabilities.generation;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* Kimi 工具类
* @author huangkh
*/
@Component
@Slf4j
public class KimiAiUtil {

@Value("${chain.llm.kimi.model}")
private String completionModel;

@Value("${kimi.ai.token}")
private String appKey;

public String getCompletionModel(){
return this.completionModel;
}

public String getAppKey(){
return this.appKey;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.hkh.ai.chain.llm.capabilities.generation;

/**
* Kimi AI相关 API
*/
public interface KimiApis {

String COMPLETION_TEXT = "https://api.moonshot.cn/v1/chat/completions";


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.hkh.ai.chain.llm.capabilities.generation.text.baidu.BaiduQianFanTextChatService;
import com.hkh.ai.chain.llm.capabilities.generation.text.chatglm2.Chatglm2TextChatService;
import com.hkh.ai.chain.llm.capabilities.generation.text.kimi.KimiTextChatService;
import com.hkh.ai.chain.llm.capabilities.generation.text.openai.OpenAiTextChatService;
import com.hkh.ai.chain.llm.capabilities.generation.text.zhipu.ZhipuTextChatService;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -19,16 +20,19 @@ public class TextChatServiceFactory {
private final Chatglm2TextChatService chatglm2TextChatService;
private final BaiduQianFanTextChatService baiduQianFanTextChatService;
private final ZhipuTextChatService zhipuTextChatService;
private final KimiTextChatService kimiTextChatService;

public TextChatServiceFactory(
OpenAiTextChatService openAiTextChatService,
Chatglm2TextChatService chatglm2TextChatService,
BaiduQianFanTextChatService baiduQianFanTextChatService,
ZhipuTextChatService zhipuTextChatService) {
ZhipuTextChatService zhipuTextChatService,
KimiTextChatService kimiTextChatService) {
this.openAiTextChatService = openAiTextChatService;
this.chatglm2TextChatService = chatglm2TextChatService;
this.baiduQianFanTextChatService = baiduQianFanTextChatService;
this.zhipuTextChatService = zhipuTextChatService;
this.kimiTextChatService = kimiTextChatService;
}

public TextChatService getTextChatService(){
Expand All @@ -40,6 +44,8 @@ public TextChatService getTextChatService(){
return baiduQianFanTextChatService;
}else if("zhipu".equals(type)){
return zhipuTextChatService;
}else if("kimi".equals(type)){
return kimiTextChatService;
}else {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public void bizProcess(String item){
this.getSseEmitter().send(content);
}
} catch (IOException e) {
log.error("ZhipuCompletionBizProcessor--->>bizProcess异常", e);
log.error("KimiCompletionBizProcessor--->>bizProcess异常", e);
throw new RuntimeException(e);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.hkh.ai.chain.llm.capabilities.generation.text.kimi;

import com.alibaba.fastjson2.JSONObject;
import lombok.Data;

import java.util.List;

@Data
public class BlockCompletionResult {

private String id;

private String model;

private Long created;

private List<BlockCompletionResultChoice> choices;

private BlockCompletionResultUsage usage;

@Data
public class BlockCompletionResultUsage{
private int prompt_tokens;
private int completion_tokens;
private int total_tokens;
}

@Data
public class BlockCompletionResultChoice{
private int index;
private String finish_reason;

private BlockCompletionResultChoiceMessage message;
}

@Data
public class BlockCompletionResultChoiceMessage{
private String role;
private String content;

private List<BlockCompletionResultChoiceMessageToolCall> tool_calls;
}

@Data
public class BlockCompletionResultChoiceMessageToolCall{
private String id;
private String type;

private BlockCompletionResultChoiceMessageToolCallFunction function;
}

@Data
public class BlockCompletionResultChoiceMessageToolCallFunction{
private String name;
private JSONObject arguments;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.hkh.ai.chain.llm.capabilities.generation.text.kimi;

import com.alibaba.fastjson2.JSONObject;
import com.hkh.ai.domain.CustomChatMessage;
import com.hkh.ai.domain.SysUser;
import com.hkh.ai.service.ConversationService;
import com.knuddels.jtokkit.api.Encoding;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.List;

/**
* 百度千帆业务处理器
* @author huangkh
*/
@Builder
@Data
@AllArgsConstructor
@Slf4j
public class KimiCompletionBizProcessor {

private final ConversationService conversationService;

private final SysUser sysUser;

private final CustomChatMessage request;

private final SseEmitter sseEmitter;

private final StringBuilder sb;

private final Encoding enc;

private final List<Integer> promptTokens;

public void bizProcess(String item){
System.out.println("智普流式输出:" +item);
if (!"[DONE]".equals(item)){
StreamCompletionResult resultObj = JSONObject.parseObject(item, StreamCompletionResult.class);
String content = resultObj.getChoices().get(0).getDelta().getContent();
try {
if (StringUtils.isNotBlank(resultObj.getChoices().get(0).getFinish_reason())) {
this.getSseEmitter().send("[END]");
String fullContent = this.getSb().toString();
List<Integer> completionToken = this.getEnc().encode(fullContent);
System.out.println("total token costs: " + (this.getPromptTokens().size() + completionToken.size()));
this.getConversationService().saveConversation(this.getSysUser().getId(), this.getRequest().getSessionId(), this.getSb().toString(), "A");
} else {
if (content.contains("\n") || content.contains("\r")) {
content = content.replaceAll("\n", "<br>");
content = content.replaceAll("\r", "<br>");
}
if (content.contains(" ")) {
content = content.replaceAll(" ", "&nbsp;");
}
this.getSb().append(content);
this.getSseEmitter().send(content);
}
} catch (IOException e) {
log.error("KimiCompletionBizProcessor--->>bizProcess异常", e);
throw new RuntimeException(e);
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.hkh.ai.chain.llm.capabilities.generation.text.kimi;

import com.alibaba.fastjson2.JSONObject;
import com.hkh.ai.chain.llm.capabilities.generation.KimiAiUtil;
import com.hkh.ai.chain.llm.capabilities.generation.KimiApis;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Flux;

/**
* 智普AI web client
* @author huangkh
*/
@Slf4j
@Component
public class KimiCompletionWebClient {
private WebClient webClient;

@Autowired
private KimiAiUtil kimiAiUtil;

@PostConstruct
public void init(){
log.info("kimi ai api web client init...");
this.webClient = WebClient.builder()
.defaultHeader("content-type", "application/json")
.build();
}

public Flux<String> streamChatCompletion(JSONObject requestBody){
log.info("streamChatCompletion 参数:{}",requestBody);
String accessToken = kimiAiUtil.getAppKey();
return webClient.post()
.uri(KimiApis.COMPLETION_TEXT)
.bodyValue(requestBody)
.header("Authorization","Bearer " + accessToken)
.retrieve()
.bodyToFlux(String.class)
.onErrorResume(WebClientResponseException.class, ex -> {
ex.printStackTrace();
HttpStatusCode statusCode = ex.getStatusCode();
String res = ex.getResponseBodyAsString();
log.error("Kimi AI API error: {} {}", statusCode, res);
return Flux.error(new RuntimeException(res));
});

}

public Flux<JSONObject> createFlux(JSONObject requestBody, KimiCompletionBizProcessor kimiCompletionBizProcessor){
log.info("createFlux 参数:{}",requestBody);
Flux<JSONObject> flux = Flux.create(emitter -> {
emitter.next(requestBody);
emitter.complete();
});

flux.subscribe(
jsonObject -> {
Flux<String> stringFlux = streamChatCompletion(requestBody);
stringFlux.subscribe(kimiCompletionBizProcessor::bizProcess);
},
System.err::println,
() -> System.out.println("emitter completed")
);
return flux;
}

}
Loading

0 comments on commit 6b962b4

Please sign in to comment.