Skip to content

Commit e442acf

Browse files
committed
use responses api
1 parent dc838e1 commit e442acf

File tree

8 files changed

+206
-298
lines changed

8 files changed

+206
-298
lines changed

README.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ A smart qa bot that can answer questions based on existing documents.
77
### Prerequisites
88

99
1. Java 17+
10-
2. Milvus 2.2.0+
1110

1211
### Installation
1312

@@ -21,27 +20,24 @@ A smart qa bot that can answer questions based on existing documents.
2120

2221
1. Config the `markdown.files.location` to the directory of the markdown files
2322
2. Config the `markdown.files.scheduleEnabled` to `true` if you want to auto update the markdown files
24-
3. Config the `milvus.host` and `milvus.port` to the Milvus server
25-
4. Config the `milvus.useZillzCloud`, `milvus.zillizCloudUri` and `milvus.zillizCloudToken` if you are using Zilliz Cloud
26-
5. Config other parameters as needed
23+
3. Config other parameters as needed
2724

2825
#### Edit the `qa-bot.conf`
2926

3027
1. Config the `OPENAI_API_KEY` to the OpenAI API key
31-
2. Config the `HTTP_PROXY` to the proxy server if needed
28+
2. Config the `OPENAI_API_BASE_URL` to a different server if needed
3229

3330
```bash
3431
export OPENAI_API_KEY=sk-************************************************
35-
export HTTP_PROXY=http{s}://${username}:${password}@${url}:${port}
32+
export OPENAI_API_BASE_URL=https://gateway.ai.cloudflare.com/v1/xxx/ai-gateway/openai/v1/
3633
```
3734

3835
### Usage
3936

4037
1. Start the service: `./scripts/startup.sh`
4138
2. Stop the service: `./scripts/shutdown.sh`
4239
3. Check the logs: `tail -f /opt/logs/qa-bot.log`
43-
4. Manually trigger the markdown files processing: `curl http://${your-server-url}:9090/markdown/load`
44-
5. Test the QA bot via browser: `http://${your-server-url}:9090`
40+
4. Test the QA bot via browser: `http://${your-server-url}:9090`
4541

4642
#### Integrate the QA bot with your website
4743

pom.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
<description>a smart qa bot</description>
1717
<properties>
1818
<java.version>17</java.version>
19-
<openai-gpt3-java.version>0.22.2</openai-gpt3-java.version>
19+
<openai-gpt3-java.version>0.22.92</openai-gpt3-java.version>
20+
<openai-java.version>3.0.1</openai-java.version>
2021
<guava.version>33.2.1-jre</guava.version>
2122
<flexmark.version>0.64.8</flexmark.version>
2223
<milvus.version>2.4.2</milvus.version>
@@ -29,6 +30,11 @@
2930
<artifactId>service</artifactId>
3031
<version>${openai-gpt3-java.version}</version>
3132
</dependency>
33+
<dependency>
34+
<groupId>com.openai</groupId>
35+
<artifactId>openai-java</artifactId>
36+
<version>${openai-java.version}</version>
37+
</dependency>
3238
<dependency>
3339
<groupId>com.google.guava</groupId>
3440
<artifactId>guava</artifactId>
@@ -64,6 +70,10 @@
6470
<groupId>io.github.lambdua</groupId>
6571
<artifactId>service</artifactId>
6672
</dependency>
73+
<dependency>
74+
<groupId>com.openai</groupId>
75+
<artifactId>openai-java</artifactId>
76+
</dependency>
6777
<dependency>
6878
<groupId>com.google.guava</groupId>
6979
<artifactId>guava</artifactId>

src/main/java/com/apolloconfig/apollo/ai/qabot/controller/QAWithAssistantsController.java

Lines changed: 0 additions & 134 deletions
This file was deleted.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.apolloconfig.apollo.ai.qabot.controller;
2+
3+
import com.apolloconfig.apollo.ai.qabot.entity.Answer;
4+
import com.apolloconfig.apollo.ai.qabot.openai.OpenAiResponseService;
5+
import com.google.common.base.Strings;
6+
import com.openai.models.responses.ResponseCompletedEvent;
7+
import com.openai.models.responses.ResponseStreamEvent;
8+
import com.openai.models.responses.ResponseTextDeltaEvent;
9+
import java.util.Collections;
10+
import java.util.Set;
11+
import java.util.regex.Pattern;
12+
import java.util.stream.Collectors;
13+
import org.jetbrains.annotations.NotNull;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
16+
import org.springframework.http.MediaType;
17+
import org.springframework.web.bind.annotation.GetMapping;
18+
import org.springframework.web.bind.annotation.RequestMapping;
19+
import org.springframework.web.bind.annotation.RequestParam;
20+
import org.springframework.web.bind.annotation.RestController;
21+
import reactor.core.publisher.Flux;
22+
23+
@RestController
24+
@RequestMapping("/qa")
25+
public class QAWithResponseController {
26+
27+
private static final Logger LOGGER = LoggerFactory.getLogger(QAWithResponseController.class);
28+
private static final String END_SYMBOL = "$END$";
29+
30+
private final OpenAiResponseService aiService;
31+
32+
public QAWithResponseController(OpenAiResponseService aiService) {
33+
this.aiService = aiService;
34+
}
35+
36+
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
37+
public Flux<Answer> qa(@RequestParam String question,
38+
@RequestParam(required = false, defaultValue = "") String threadId) {
39+
question = question.trim();
40+
if (Strings.isNullOrEmpty(question)) {
41+
return Flux.just(Answer.EMPTY);
42+
}
43+
44+
try {
45+
return doQA(threadId, question);
46+
} catch (Throwable exception) {
47+
LOGGER.error("Error while calling Assistants API", exception);
48+
return Flux.just(Answer.ERROR);
49+
}
50+
}
51+
52+
private Flux<Answer> doQA(String threadId, String question) {
53+
if (LOGGER.isDebugEnabled()) {
54+
LOGGER.debug("\nPrompt message: {}", question);
55+
}
56+
57+
Flux<ResponseStreamEvent> result = aiService.getResponseMessage(threadId, question);
58+
59+
return result.filter(
60+
responseStreamEvent -> responseStreamEvent.isOutputTextDelta()
61+
|| responseStreamEvent.isCompleted())
62+
.map(responseStreamEvent -> {
63+
if (LOGGER.isDebugEnabled()) {
64+
LOGGER.debug("responseStreamEvent: {}", responseStreamEvent);
65+
}
66+
if (responseStreamEvent.isOutputTextDelta() && responseStreamEvent.outputTextDelta()
67+
.isPresent()) {
68+
return getAnswerFromOutputTextDelta(responseStreamEvent.outputTextDelta().get());
69+
} else if (responseStreamEvent.isCompleted() && responseStreamEvent.completed()
70+
.isPresent()) {
71+
return getAnswerFromCompleted(responseStreamEvent.completed().get());
72+
}
73+
return Answer.EMPTY;
74+
}).onErrorReturn(Answer.ERROR);
75+
}
76+
77+
private @NotNull Answer getAnswerFromCompleted(ResponseCompletedEvent responseCompletedEvent) {
78+
Set<String> relatedFiles = responseCompletedEvent.response().output().stream()
79+
.filter(responseOutputItem -> responseOutputItem.isMessage()
80+
&& responseOutputItem.message().isPresent())
81+
.flatMap(responseOutputItem -> responseOutputItem.message().stream())
82+
.flatMap(message -> message.content().stream())
83+
.filter(content -> content.isOutputText() && content.outputText().isPresent())
84+
.flatMap(content -> content.outputText().stream())
85+
.flatMap(outputText -> outputText.annotations().stream())
86+
.filter(annotation ->
87+
annotation.isFileCitation() && annotation.fileCitation().isPresent())
88+
.map(annotation -> {
89+
String fileName = annotation.fileCitation().get().filename();
90+
if (fileName.endsWith(".md")) {
91+
fileName = fileName.substring(0, fileName.length() - 3);
92+
}
93+
return fileName;
94+
})
95+
.collect(Collectors.toSet());
96+
return new Answer(END_SYMBOL, responseCompletedEvent.response().id(), relatedFiles);
97+
}
98+
99+
private @NotNull Answer getAnswerFromOutputTextDelta(
100+
ResponseTextDeltaEvent responseTextDeltaEvent) {
101+
String text = responseTextDeltaEvent.delta();
102+
return new Answer(text, "", Collections.emptySet());
103+
}
104+
}

src/main/java/com/apolloconfig/apollo/ai/qabot/markdown/MarkdownProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import com.apolloconfig.apollo.ai.qabot.config.MarkdownFilesConfig;
44
import com.apolloconfig.apollo.ai.qabot.config.MarkdownProcessorRetryConfig;
5-
import com.apolloconfig.apollo.ai.qabot.openai.OpenAiAssistantsService;
5+
import com.apolloconfig.apollo.ai.qabot.openai.OpenAiResponseService;
66
import com.google.common.collect.Maps;
77
import java.io.IOException;
88
import java.nio.file.Files;
@@ -29,14 +29,14 @@ public class MarkdownProcessor {
2929

3030
private static final Logger LOGGER = LoggerFactory.getLogger(MarkdownProcessor.class);
3131

32-
private final OpenAiAssistantsService aiService;
32+
private final OpenAiResponseService aiService;
3333
private final MarkdownFilesConfig markdownFilesConfig;
3434
private final MarkdownProcessorRetryConfig markdownProcessorRetryConfig;
3535
private final BackOff backOff;
3636
private final Map<String, String> fileHashValues;
3737
private final Map<String, String> fileIds;
3838

39-
public MarkdownProcessor(OpenAiAssistantsService aiService,
39+
public MarkdownProcessor(OpenAiResponseService aiService,
4040
MarkdownFilesConfig markdownFilesConfig,
4141
MarkdownProcessorRetryConfig markdownProcessorRetryConfig) {
4242
this.aiService = aiService;

0 commit comments

Comments
 (0)