Skip to content

Commit 5406522

Browse files
committed
support continuous dialogue
1 parent e680983 commit 5406522

File tree

2 files changed

+70
-55
lines changed

2 files changed

+70
-55
lines changed

app.js

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ dotenv.config();
66

77
if (!process.env.DIFY_API_URL) throw new Error("DIFY API URL is required.");
88
function generateId() {
9-
let result = '';
10-
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
9+
let result = "";
10+
const characters =
11+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1112
for (let i = 0; i < 29; i++) {
1213
result += characters.charAt(Math.floor(Math.random() * characters.length));
1314
}
@@ -35,7 +36,10 @@ app.post("/v1/chat/completions", async (req, res) => {
3536
}
3637
try {
3738
const data = req.body;
38-
const queryString = data.messages[data.messages.length - 1].content;
39+
const messages = data.messages;
40+
const queryString = messages
41+
.map((message) => `${message.role}: ${message.content}`)
42+
.join('\n');
3943
const stream = data.stream !== undefined ? data.stream : false;
4044
const resp = await fetch(process.env.DIFY_API_URL + "/chat-messages", {
4145
method: "POST",
@@ -56,6 +60,7 @@ app.post("/v1/chat/completions", async (req, res) => {
5660
res.setHeader("Content-Type", "text/event-stream");
5761
const stream = resp.body;
5862
let buffer = "";
63+
let isFirstChunk = true;
5964

6065
stream.on("data", (chunk) => {
6166
buffer += chunk.toString();
@@ -79,56 +84,65 @@ app.post("/v1/chat/completions", async (req, res) => {
7984
}
8085

8186
if (chunkObj.event === "message") {
82-
const chunkContent = JSON.parse(
83-
`"${chunkObj.answer.replace(
84-
/[\u0000-\u001F\u007F-\u009F]/g,
85-
""
86-
)}"`
87-
);
88-
const chunkId = `chatcmpl-${Date.now()}`;
89-
const chunkCreated = chunkObj.created_at;
90-
res.write(
91-
"data: " +
92-
JSON.stringify({
93-
id: chunkId,
94-
object: "chat.completion.chunk",
95-
created: chunkCreated,
96-
model: data.model,
97-
choices: [
98-
{
99-
index: 0,
100-
delta: {
101-
content: chunkContent,
87+
let chunkContent = chunkObj.answer;
88+
89+
if (isFirstChunk) {
90+
chunkContent = chunkContent.trimStart();
91+
isFirstChunk = false;
92+
}
93+
if (chunkContent !== "") {
94+
const chunkId = `chatcmpl-${Date.now()}`;
95+
const chunkCreated = chunkObj.created_at;
96+
res.write(
97+
"data: " +
98+
JSON.stringify({
99+
id: chunkId,
100+
object: "chat.completion.chunk",
101+
created: chunkCreated,
102+
model: data.model,
103+
choices: [
104+
{
105+
index: 0,
106+
delta: {
107+
content: escapedContent,
108+
},
109+
finish_reason: null,
102110
},
103-
finish_reason: null,
104-
},
105-
],
106-
}) +
107-
"\n\n"
108-
);
111+
],
112+
}) +
113+
"\n\n"
114+
);
115+
}
109116
} else if (chunkObj.event === "agent_message") {
110-
const chunkContent = chunkObj.answer;
111-
const chunkId = `chatcmpl-${Date.now()}`;
112-
const chunkCreated = chunkObj.created_at;
113-
res.write(
114-
"data: " +
115-
JSON.stringify({
116-
id: chunkId,
117-
object: "chat.completion.chunk",
118-
created: chunkCreated,
119-
model: data.model,
120-
choices: [
121-
{
122-
index: 0,
123-
delta: {
124-
content: chunkContent,
117+
let chunkContent = chunkObj.answer;
118+
119+
if (isFirstChunk) {
120+
chunkContent = chunkContent.trimStart();
121+
isFirstChunk = false;
122+
}
123+
if (chunkContent !== "") {
124+
const chunkId = `chatcmpl-${Date.now()}`;
125+
const chunkCreated = chunkObj.created_at;
126+
res.write(
127+
"data: " +
128+
JSON.stringify({
129+
id: chunkId,
130+
object: "chat.completion.chunk",
131+
created: chunkCreated,
132+
model: data.model,
133+
choices: [
134+
{
135+
index: 0,
136+
delta: {
137+
content: chunkContent,
138+
},
139+
finish_reason: null,
125140
},
126-
finish_reason: null,
127-
},
128-
],
129-
}) +
130-
"\n\n"
131-
);
141+
],
142+
}) +
143+
"\n\n"
144+
);
145+
}
132146
} else if (chunkObj.event === "message_end") {
133147
const chunkId = `chatcmpl-${Date.now()}`;
134148
const chunkCreated = chunkObj.created_at;
@@ -204,7 +218,8 @@ app.post("/v1/chat/completions", async (req, res) => {
204218
messageEnded = true;
205219
usageData = {
206220
prompt_tokens: chunkObj.metadata.usage.prompt_tokens || 100,
207-
completion_tokens: chunkObj.metadata.usage.completion_tokens || 10,
221+
completion_tokens:
222+
chunkObj.metadata.usage.completion_tokens || 10,
208223
total_tokens: chunkObj.metadata.usage.total_tokens || 110,
209224
};
210225
} else if (chunkObj.event === "agent_thought") {

readme.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ This project converts the Dify API to the OpenAI API format, giving you access t
66

77
## Features
88
- Convert Dify API into an OpenAI API
9-
- Support streaming
10-
- Support Agent bot
11-
- Support Chat bot
9+
- Support streaming and blocking
10+
- Support Agent bots API on dify
11+
- Support Chat bots API on dify
1212

1313
## Deployment
1414
### Zeabur
@@ -59,14 +59,14 @@ console.log(data);
5959

6060
## Roadmap
6161
**Coming Soon**
62-
* Continuous dialogue
6362
* Workflow integration
6463
* Image support
6564
* Audio-to-text
6665
* Text-to-audio
6766
* Docker support
6867

6968
**Available Now**
69+
* Continuous dialogue
7070
* Zeabur & Vercel deployment
7171
* Streaming & Blocking
7272
* Agent & Chat bots

0 commit comments

Comments
 (0)