Spaces:
Sleeping
Sleeping
Update main.go
Browse files
main.go
CHANGED
@@ -5,19 +5,11 @@ import (
|
|
5 |
"bytes"
|
6 |
"encoding/json"
|
7 |
"io"
|
8 |
-
"log"
|
9 |
"net/http"
|
10 |
-
"time"
|
11 |
|
12 |
"github.com/gin-gonic/gin"
|
13 |
)
|
14 |
|
15 |
-
const (
|
16 |
-
statusURL = "https://duckduckgo.com/duckchat/v1/status"
|
17 |
-
chatURL = "https://duckduckgo.com/duckchat/v1/chat"
|
18 |
-
userAgent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0"
|
19 |
-
)
|
20 |
-
|
21 |
type OpenAIRequest struct {
|
22 |
Model string `json:"model"`
|
23 |
Messages []struct {
|
@@ -74,58 +66,77 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
|
|
74 |
Role string `json:"role"`
|
75 |
Content string `json:"content"`
|
76 |
}, stream bool) {
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
-
//
|
80 |
req, err := http.NewRequest("GET", statusURL, nil)
|
81 |
if err != nil {
|
82 |
-
|
83 |
-
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create request"})
|
84 |
return
|
85 |
}
|
|
|
86 |
req.Header.Set("x-vqd-accept", "1")
|
87 |
-
|
|
|
|
|
88 |
|
89 |
-
resp, err :=
|
90 |
if err != nil {
|
91 |
-
|
92 |
-
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get vqd_4"})
|
93 |
return
|
94 |
}
|
95 |
defer resp.Body.Close()
|
96 |
|
97 |
vqd4 := resp.Header.Get("x-vqd-4")
|
98 |
|
99 |
-
// Send chat request
|
100 |
payload := map[string]interface{}{
|
101 |
"model": "gpt-3.5-turbo-0125",
|
102 |
"messages": messages,
|
103 |
}
|
|
|
104 |
payloadBytes, err := json.Marshal(payload)
|
105 |
if err != nil {
|
106 |
-
|
107 |
-
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to marshal payload"})
|
108 |
return
|
109 |
}
|
110 |
|
111 |
req, err = http.NewRequest("POST", chatURL, bytes.NewBuffer(payloadBytes))
|
112 |
if err != nil {
|
113 |
-
|
114 |
-
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create request"})
|
115 |
return
|
116 |
}
|
|
|
117 |
req.Header.Set("x-vqd-4", vqd4)
|
118 |
-
|
|
|
|
|
119 |
|
120 |
-
resp, err =
|
121 |
if err != nil {
|
122 |
-
|
123 |
-
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to send chat request"})
|
124 |
return
|
125 |
}
|
126 |
defer resp.Body.Close()
|
127 |
|
128 |
-
// Process response
|
129 |
reader := bufio.NewReader(resp.Body)
|
130 |
c.Header("Content-Type", "text/event-stream")
|
131 |
c.Header("Cache-Control", "no-cache")
|
@@ -135,7 +146,9 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
|
|
135 |
flusher, _ := c.Writer.(http.Flusher)
|
136 |
|
137 |
var response OpenAIResponse
|
|
|
138 |
response.Choices = make([]OpenAIChoice, 1)
|
|
|
139 |
|
140 |
var responseContent string
|
141 |
|
@@ -153,12 +166,36 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
|
|
153 |
chunk := line[6:]
|
154 |
|
155 |
if bytes.HasPrefix(chunk, []byte("[DONE]")) {
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
}
|
163 |
|
164 |
var data DuckDuckGoResponse
|
@@ -174,6 +211,10 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
|
|
174 |
response.Object = "chat.completion"
|
175 |
response.Created = data.Created
|
176 |
response.Model = data.Model
|
|
|
|
|
|
|
|
|
177 |
responseContent += data.Message
|
178 |
|
179 |
if stream {
|
@@ -195,21 +236,8 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
|
|
195 |
}
|
196 |
}
|
197 |
|
198 |
-
func
|
199 |
-
|
200 |
-
req.Header.Set("Accept", "text/event-stream")
|
201 |
-
req.Header.Set("Accept-Language", "de,en-US;q=0.7,en;q=0.3")
|
202 |
-
req.Header.Set("Accept-Encoding", "gzip, deflate, br")
|
203 |
-
req.Header.Set("Referer", "https://duckduckgo.com/")
|
204 |
-
req.Header.Set("Content-Type", "application/json")
|
205 |
-
req.Header.Set("Origin", "https://duckduckgo.com")
|
206 |
-
req.Header.Set("Connection", "keep-alive")
|
207 |
-
req.Header.Set("Cookie", "dcm=1")
|
208 |
-
req.Header.Set("Sec-Fetch-Dest", "empty")
|
209 |
-
req.Header.Set("Sec-Fetch-Mode", "cors")
|
210 |
-
req.Header.Set("Sec-Fetch-Site", "same-origin")
|
211 |
-
req.Header.Set("Pragma", "no-cache")
|
212 |
-
req.Header.Set("TE", "trailers")
|
213 |
}
|
214 |
|
215 |
func main() {
|
@@ -221,13 +249,13 @@ func main() {
|
|
221 |
"message": "Hello! Thank you for using FreeDuckDuckGo. Made by Vincent Yang. Repo: https://github.com/missuo/FreeDuckDuckGo",
|
222 |
})
|
223 |
})
|
224 |
-
|
225 |
r.OPTIONS("/v1/chat/completions", func(c *gin.Context) {
|
226 |
-
c.
|
227 |
-
|
228 |
-
|
229 |
-
c.Status(http.StatusOK)
|
230 |
})
|
|
|
231 |
|
232 |
r.POST("/v1/chat/completions", func(c *gin.Context) {
|
233 |
var req OpenAIRequest
|
|
|
5 |
"bytes"
|
6 |
"encoding/json"
|
7 |
"io"
|
|
|
8 |
"net/http"
|
|
|
9 |
|
10 |
"github.com/gin-gonic/gin"
|
11 |
)
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
type OpenAIRequest struct {
|
14 |
Model string `json:"model"`
|
15 |
Messages []struct {
|
|
|
66 |
Role string `json:"role"`
|
67 |
Content string `json:"content"`
|
68 |
}, stream bool) {
|
69 |
+
userAgent := "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0"
|
70 |
+
headers := map[string]string{
|
71 |
+
"User-Agent": userAgent,
|
72 |
+
"Accept": "text/event-stream",
|
73 |
+
"Accept-Language": "de,en-US;q=0.7,en;q=0.3",
|
74 |
+
"Accept-Encoding": "gzip, deflate, br",
|
75 |
+
"Referer": "https://duckduckgo.com/",
|
76 |
+
"Content-Type": "application/json",
|
77 |
+
"Origin": "https://duckduckgo.com",
|
78 |
+
"Connection": "keep-alive",
|
79 |
+
"Cookie": "dcm=1",
|
80 |
+
"Sec-Fetch-Dest": "empty",
|
81 |
+
"Sec-Fetch-Mode": "cors",
|
82 |
+
"Sec-Fetch-Site": "same-origin",
|
83 |
+
"Pragma": "no-cache",
|
84 |
+
"TE": "trailers",
|
85 |
+
}
|
86 |
+
|
87 |
+
statusURL := "https://duckduckgo.com/duckchat/v1/status"
|
88 |
+
chatURL := "https://duckduckgo.com/duckchat/v1/chat"
|
89 |
|
90 |
+
// get vqd_4
|
91 |
req, err := http.NewRequest("GET", statusURL, nil)
|
92 |
if err != nil {
|
93 |
+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
94 |
return
|
95 |
}
|
96 |
+
|
97 |
req.Header.Set("x-vqd-accept", "1")
|
98 |
+
for key, value := range headers {
|
99 |
+
req.Header.Set(key, value)
|
100 |
+
}
|
101 |
|
102 |
+
resp, err := http.DefaultClient.Do(req)
|
103 |
if err != nil {
|
104 |
+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
105 |
return
|
106 |
}
|
107 |
defer resp.Body.Close()
|
108 |
|
109 |
vqd4 := resp.Header.Get("x-vqd-4")
|
110 |
|
|
|
111 |
payload := map[string]interface{}{
|
112 |
"model": "gpt-3.5-turbo-0125",
|
113 |
"messages": messages,
|
114 |
}
|
115 |
+
|
116 |
payloadBytes, err := json.Marshal(payload)
|
117 |
if err != nil {
|
118 |
+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
119 |
return
|
120 |
}
|
121 |
|
122 |
req, err = http.NewRequest("POST", chatURL, bytes.NewBuffer(payloadBytes))
|
123 |
if err != nil {
|
124 |
+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
125 |
return
|
126 |
}
|
127 |
+
|
128 |
req.Header.Set("x-vqd-4", vqd4)
|
129 |
+
for key, value := range headers {
|
130 |
+
req.Header.Set(key, value)
|
131 |
+
}
|
132 |
|
133 |
+
resp, err = http.DefaultClient.Do(req)
|
134 |
if err != nil {
|
135 |
+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
136 |
return
|
137 |
}
|
138 |
defer resp.Body.Close()
|
139 |
|
|
|
140 |
reader := bufio.NewReader(resp.Body)
|
141 |
c.Header("Content-Type", "text/event-stream")
|
142 |
c.Header("Cache-Control", "no-cache")
|
|
|
146 |
flusher, _ := c.Writer.(http.Flusher)
|
147 |
|
148 |
var response OpenAIResponse
|
149 |
+
var nonStreamResponse OpenAINonStreamResponse
|
150 |
response.Choices = make([]OpenAIChoice, 1)
|
151 |
+
nonStreamResponse.Choices = make([]OpenAINonStreamChoice, 1)
|
152 |
|
153 |
var responseContent string
|
154 |
|
|
|
166 |
chunk := line[6:]
|
167 |
|
168 |
if bytes.HasPrefix(chunk, []byte("[DONE]")) {
|
169 |
+
if !stream {
|
170 |
+
nonStreamResponse.Choices[0].Message.Content = responseContent
|
171 |
+
nonStreamResponse.Choices[0].Message.Role = "assistant"
|
172 |
+
nonStreamResponse.Choices[0].FinishReason = new(string)
|
173 |
+
*nonStreamResponse.Choices[0].FinishReason = "stop"
|
174 |
+
c.JSON(http.StatusOK, nonStreamResponse)
|
175 |
+
return
|
176 |
+
} else {
|
177 |
+
stopData := OpenAIResponse{
|
178 |
+
ID: "chatcmpl-9HOzx2PhnYCLPxQ3Dpa2OKoqR2lgl",
|
179 |
+
Object: "chat.completion",
|
180 |
+
Created: 1713934697,
|
181 |
+
Model: "gpt-3.5-turbo-0125",
|
182 |
+
Choices: []OpenAIChoice{
|
183 |
+
{
|
184 |
+
Index: 0,
|
185 |
+
FinishReason: stringPtr("stop"),
|
186 |
+
},
|
187 |
+
},
|
188 |
+
}
|
189 |
+
stopDataBytes, _ := json.Marshal(stopData)
|
190 |
+
c.Data(http.StatusOK, "application/json", []byte("data: "))
|
191 |
+
c.Data(http.StatusOK, "application/json", stopDataBytes)
|
192 |
+
c.Data(http.StatusOK, "application/json", []byte("\n\n"))
|
193 |
+
flusher.Flush()
|
194 |
+
|
195 |
+
c.Data(http.StatusOK, "application/json", []byte("data: [DONE]\n\n"))
|
196 |
+
flusher.Flush()
|
197 |
+
return
|
198 |
+
}
|
199 |
}
|
200 |
|
201 |
var data DuckDuckGoResponse
|
|
|
211 |
response.Object = "chat.completion"
|
212 |
response.Created = data.Created
|
213 |
response.Model = data.Model
|
214 |
+
nonStreamResponse.ID = data.ID
|
215 |
+
nonStreamResponse.Object = "chat.completion"
|
216 |
+
nonStreamResponse.Created = data.Created
|
217 |
+
nonStreamResponse.Model = data.Model
|
218 |
responseContent += data.Message
|
219 |
|
220 |
if stream {
|
|
|
236 |
}
|
237 |
}
|
238 |
|
239 |
+
func stringPtr(s string) *string {
|
240 |
+
return &s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
}
|
242 |
|
243 |
func main() {
|
|
|
249 |
"message": "Hello! Thank you for using FreeDuckDuckGo. Made by Vincent Yang. Repo: https://github.com/missuo/FreeDuckDuckGo",
|
250 |
})
|
251 |
})
|
252 |
+
|
253 |
r.OPTIONS("/v1/chat/completions", func(c *gin.Context) {
|
254 |
+
c.JSON(http.StatusOK, gin.H{
|
255 |
+
"message": "ok",
|
256 |
+
})
|
|
|
257 |
})
|
258 |
+
|
259 |
|
260 |
r.POST("/v1/chat/completions", func(c *gin.Context) {
|
261 |
var req OpenAIRequest
|