智谱文档:智谱AI开放平台
注意:springboot版本要在3.0以上,pom.xml要配置下载的源。
pml文件如下
建议使用下科学上网~~~
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>ai-puzhi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ai-puzhi</name>
<description>ai-puzhi</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<fastjson2.version>2.0.52</fastjson2.version>
<java.version>17</java.version>
<spring-ai.version>1.0.3</spring-ai.version>
<testcontainers.version>1.20.1</testcontainers.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-M1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- For Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- For Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- For Caffeine -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<!-- For FastJson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson2.version}</version>
</dependency>
<dependency>
<groupId>io.springboot.ai</groupId>
<artifactId>spring-ai-zhipu-ai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>cn.bigmodel.openapi</groupId>
<artifactId>oapi-java-sdk</artifactId>
<version>release-V4-2.0.2</version>
<scope>test</scope>
</dependency>
<!-- For Web Server -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 配置下载地址-->
<!-- 设定远程主仓库,按设定顺序进行查找。 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>central</id>
<name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
yml配置文件
spring:
application:
name: ai-puzhi
ai:
zhipuai:
api-key: 82770a63b944ae2789b679332cf32
# model: glm-4-plus
model: codegeex-4
retry:
backoff:
max-interval: 3000
multiplier: 2
initial-interval: 2000
server:
port: 9090
获取key地址:智谱AI开放平台
主要代码
@RestController
@CrossOrigin
public class ChatController {
private final ZhipuAiChatClient chatClient;
@Autowired
public ChatController(ZhipuAiChatClient chatClient) {
this.chatClient = chatClient;
}
@GetMapping(value = "/v1/generate", produces = "application/json")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
String call = chatClient.call(message);
System.out.println(call);
return Map.of("generation", call);
}
@GetMapping("/v1/prompt")
public List<Generation> prompt(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
PromptTemplate promptTemplate = new PromptTemplate("Tell me a {adjective} joke about {topic}");
Prompt prompt = promptTemplate.create(Map.of("adjective", "funny", "topic", "cats"));
return chatClient.call(prompt).getResults();
}
@GetMapping("/v1/chat/completions")
public Flux<ChatResponse> chatCompletions(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
Prompt prompt = new Prompt(new UserMessage(message));
return chatClient.stream(prompt);
}
@GetMapping("/v1/chat/completionsTow")
public SseEmitter chatCompletionsTow(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
SseEmitter emitter = new SseEmitter();
Prompt prompt = new Prompt(new UserMessage(message));
// 订阅Flux并处理数据
chatClient.stream(prompt).subscribe(
data -> {
try {
emitter.send(data);
} catch (IOException e) {
emitter.completeWithError(e);
}
},
emitter::completeWithError,
emitter::complete
);
return emitter;
}
@PostMapping("/v1/chat/completionsPost")
public Flux<ChatResponse> completionsPost(@RequestBody Message msg) {
Prompt prompt = new Prompt(new UserMessage(msg.getMsg()));
return chatClient.stream(prompt);
}
@PostMapping(value = "/completionsPost", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public void completionsPost(@RequestBody Message msg, HttpServletResponse response) throws IOException {
Prompt prompt = new Prompt(new UserMessage(msg.getMsg()));
// 获取 SSE 的 flux 流
Flux<ChatResponse> flux = chatClient.stream(prompt);
// 设置必要的 SSE 头部
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Connection", "keep-alive");
response.setHeader("Content-Type", "text/event-stream");
// 获取响应输出流
PrintWriter writer = response.getWriter();
flux.doOnNext(chatResponse -> {
try {
// 将 ChatResponse 转换为 SSE 格式并写入响应流
Generation result = chatResponse.getResult();
AssistantMessage output = result.getOutput();
String content = output.getContent();
System.out.println("content: " + content);
writer.write("data: " + content + "\n\n");
writer.flush();
} catch (Exception e) {
// 处理异常
e.printStackTrace();
}
})
.doOnError(throwable -> {
try {
// 在出现错误时关闭响应流
writer.write("event: error\ndata: " + throwable.getMessage() + "\n\n");
writer.flush();
writer.close();
} catch (Exception e) {
// 处理异常
e.printStackTrace();
}
})
.doOnComplete(() -> {
try {
// 在流完成时关闭响应流
writer.write("event: complete\ndata: Stream completed\n\n");
writer.flush();
writer.close();
} catch (Exception e) {
// 处理异常
e.printStackTrace();
}
})
.subscribe(); // 订阅以启动流
}
@PostMapping(value = "/completionsPostNew", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter completionsPostNew(@RequestBody Message msg, HttpServletResponse response) {
SseEmitter emitter = new SseEmitter();
UserMessage userMessage = new UserMessage(msg.getMsg());
SystemMessage systemMessage = new SystemMessage("你是一位智能编程助手,你叫CSBlogAi。你会为用户回答关于编程、代码、计算机方面的任何问题," +
"并提供格式规范、可以执行、准确安全的代码,并在必要时提供详细的解释。" +
"任务:请为输入代码提供格式规范的注释,包含多行注释和单行注释," +
"请注意不要改动原始代码,只需要添加注释。 请用中文回答。");
List<org.springframework.ai.chat.messages.Message> messages = List.of(userMessage, systemMessage);
Prompt prompt = new Prompt(messages);
// 设置响应头
response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE);
// 订阅Flux并处理数据
chatClient.stream(prompt).subscribe(
data -> {
try {
// 发送 JSON 格式的 SSE 事件
emitter.send(data);
} catch (IOException e) {
emitter.completeWithError(e);
}
},
emitter::completeWithError,
emitter::complete
);
return emitter;
}
}
前端主要代码
//get使用
getChatCompletions() {
// 关闭之前的SSE连接(如果存在)
if (this.eventSource) {
this.eventSource.close();
}
let msg = this.userInput.replace(/\s+/g, '')
let url = `http://localhost:9090/v1/chat/completionsTow?message=${msg}`
// // 创建一个新的EventSource连接
this.eventSource = new EventSource(url);
let user = this.$store.state.UserInfo
let userObj = {
user: {
userName: user.nickname,
avatar: user.avatar,
content: this.userInput
},
chat: {
avatar: "https://blog-chen.oss-cn-shanghai.aliyuncs.com/favicon.ico",
aiName: "CsBlog-Ai",
content: []
}
}
this.chatResponses.push(userObj)
this.userInput = ''; // 清空输入框
// 监听消息事件
this.eventSource.onmessage = event => {
const chatResponse = JSON.parse(event.data);
if (chatResponse.result.output.content.trim() != '') {
// 获取最后有的数组
let length = this.chatResponses.length
this.chatResponses[length - 1].chat.content.push(chatResponse.result.output.content)
// this.chatResponses.push(chatResponse.result.output.content);
this.$nextTick(() => {
prism.highlightAll();// 全局代码高亮
// 滚动到底部
this.observeContentChanges()
});
}
};
// 监听错误事件
this.eventSource.onerror = error => {
// 将chatResponses添加到localStorage中
console.log("关闭eventSource");
if (this.chatResponses.length != 0) {
localStorage.setItem(user.id, JSON.stringify(this.chatResponses))
}
this.eventSource.close();
};
},
//post使用
SendAi() {
this.abortController = new AbortController();
const signal = this.abortController.signal;
console.log(signal);
// 添加到数组中
let user = this.$store.state.UserInfo
let userObj = {
user: {
userName: user.nickname,
avatar: user.avatar,
content: this.userInput
},
chat: {
avatar: "https://blog-c",
aiName: "CsBlog-Ai",
content: []
}
}
this.chatResponses.push(userObj)
let sendMsg = this.userInput.replace(/\s+/g, '')
this.userInput = ''; // 清空输入框
fetchEventSource('http://localhost:9090/completionsPostNew', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
},
body: JSON.stringify({ msg: sendMsg }),
onmessage: (event) => {
const chatResponse = JSON.parse(event.data);
if (chatResponse.result.output.content.trim() != '') {
// 获取最后有的数组
let length = this.chatResponses.length
this.chatResponses[length - 1].chat.content.push(chatResponse.result.output.content)
this.$nextTick(() => {
prism.highlightAll();// 全局代码高亮
// 滚动到底部
this.observeContentChanges()
});
}
},
onopen: async (response) => {
if (response.ok && response.headers.get('content-type') === 'text/event-stream') {
return; // 连接成功
} else if (response.status >= 400 && response.status < 500 && response.status === 429) {
this.abortController.abort();
throw new Error('Client-side error');
} else {
this.abortController.abort();
throw new Error('Retriable error');
}
},
onerror: (event) => {
if (event.target.readyState === EventSource.CLOSED) {
console.error('Connection was closed by the server.');
} else {
console.error('Error occurred:', event);
}
},
onclose: () => {
if (this.chatResponses.length != 0) {
localStorage.setItem(user.id, JSON.stringify(this.chatResponses))
}
console.log('Connection closed.');
},
signal: signal
});
}
},
beforeDestroy() {
this.abortController.abort();
},
需要源码的私信~~~