bobocup commited on
Commit
f118d04
·
verified ·
1 Parent(s): 75ce96d

Update main.go

Browse files
Files changed (1) hide show
  1. main.go +133 -221
main.go CHANGED
@@ -131,51 +131,6 @@ func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
131
  }
132
  }
133
 
134
- // 修改消息转换函数,将所有消息合并为一条
135
- func transformMessages(messages []Message) []struct {
136
- Role string `json:"role"`
137
- Content []struct {
138
- Type string `json:"type"`
139
- Text string `json:"text"`
140
- } `json:"content"`
141
- } {
142
- var allContent []string
143
-
144
- // 遍历所有消息,添加角色前缀
145
- for _, msg := range messages[:len(messages)-1] {
146
- rolePrefix := strings.Title(msg.Role) // System/User/Assistant
147
- allContent = append(allContent, fmt.Sprintf("%s: %s", rolePrefix, msg.Content))
148
- }
149
-
150
- // 获取最后一条消息
151
- lastMsg := messages[len(messages)-1]
152
- rolePrefix := strings.Title(lastMsg.Role)
153
- allContent = append(allContent, fmt.Sprintf("%s: %s", rolePrefix, lastMsg.Content))
154
-
155
- // 将所有内容合并为一条消息
156
- return []struct {
157
- Role string `json:"role"`
158
- Content []struct {
159
- Type string `json:"type"`
160
- Text string `json:"text"`
161
- } `json:"content"`
162
- }{
163
- {
164
- Role: "user",
165
- Content: []struct {
166
- Type string `json:"type"`
167
- Text string `json:"text"`
168
- }{
169
- {
170
- Type: "text",
171
- Text: strings.Join(allContent, "\n\n"), // 使用双换行符分隔不同消息
172
- },
173
- },
174
- },
175
- }
176
- }
177
-
178
- // 修改 forwardToSider 函数中的请求构造部分
179
  func forwardToSider(w http.ResponseWriter, r *http.Request) {
180
  fmt.Printf("收到新请求: %s %s\n", r.Method, r.URL.Path)
181
 
@@ -211,19 +166,24 @@ func forwardToSider(w http.ResponseWriter, r *http.Request) {
211
  return
212
  }
213
 
214
- // 合并所有消息为一个字符串
215
- var allMessages []string
216
- for _, msg := range userReq.Messages {
217
- rolePrefix := strings.Title(msg.Role) // System/User/Assistant
218
- allMessages = append(allMessages, fmt.Sprintf("%s: %s", rolePrefix, msg.Content))
 
 
 
 
 
 
 
 
219
  }
 
220
 
221
- // 将所有消息合并为一个prompt
222
- prompt := strings.Join(allMessages, "\n\n")
223
- fmt.Printf("处理的prompt: %s\n", prompt)
224
-
225
- // 添加prompt到配置中
226
- defaultConfig["prompt"] = prompt
227
 
228
  // 添加model到配置中
229
  if userReq.Model != "" {
@@ -237,34 +197,8 @@ func forwardToSider(w http.ResponseWriter, r *http.Request) {
237
 
238
  fmt.Printf("使用的模型: %s\n", defaultConfig["model"])
239
 
240
- // 构造 Sider 请求
241
- siderReq := struct {
242
- AppName string `json:"app_name"`
243
- AppVersion string `json:"app_version"`
244
- TzName string `json:"tz_name"`
245
- Cid string `json:"cid"`
246
- Search bool `json:"search"`
247
- AutoSearch bool `json:"auto_search"`
248
- Model string `json:"model"`
249
- Stream bool `json:"stream"`
250
- Messages []struct {
251
- Role string `json:"role"`
252
- Content []struct {
253
- Type string `json:"type"`
254
- Text string `json:"text"`
255
- } `json:"content"`
256
- } `json:"messages"`
257
- }{
258
- AppName: "ChitChat_Edge_Ext",
259
- AppVersion: "4.40.0",
260
- TzName: "Asia/Shanghai",
261
- Model: userReq.Model,
262
- Stream: userReq.Stream,
263
- Messages: transformMessages(userReq.Messages),
264
- }
265
-
266
- // 转换为JSON
267
- finalBody, err := json.Marshal(siderReq)
268
  if err != nil {
269
  fmt.Printf("生成最终请求体失败: %v\n", err)
270
  http.Error(w, "处理请求失败", http.StatusInternalServerError)
@@ -316,160 +250,84 @@ func forwardToSider(w http.ResponseWriter, r *http.Request) {
316
 
317
  fmt.Printf("Sider响应状态码: %d\n", resp.StatusCode)
318
 
319
- // 读取响应体并保存副本
320
- bodyBytes, err := io.ReadAll(resp.Body)
321
- if err != nil {
322
- fmt.Printf("读取响应体失败: %v\n", err)
323
- http.Error(w, "读取响应失败", http.StatusInternalServerError)
324
- return
325
- }
326
-
327
- // 打印完整的响应信息
328
- fmt.Printf("Sider响应体: %s\n", string(bodyBytes))
329
-
330
- // 如果是错误状态码,打印更多调试信息
331
- if resp.StatusCode != http.StatusOK {
332
- fmt.Printf("导致%d错误的请求体: %s\n", resp.StatusCode, string(finalBody))
333
- fmt.Printf("请求Headers: %+v\n", req.Header)
334
- http.Error(w, fmt.Sprintf("Sider服务返回错误: %d - %s", resp.StatusCode, string(bodyBytes)), resp.StatusCode)
335
- return
336
- }
337
-
338
- // 重新创建一个新的 Reader,供后续处理使用
339
- resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
340
-
341
- // 根据 stream 参数选择响应模式
342
- if userReq.Stream {
343
- handleStreamResponse(w, resp, userReq.Model)
344
- } else {
345
- handleNonStreamResponse(w, resp, userReq.Model)
346
- }
347
- }
348
-
349
- func indexHandler(w http.ResponseWriter, r *http.Request) {
350
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
351
- fmt.Fprintf(w, "🚀服务已启动!")
352
- }
353
-
354
- type Model struct {
355
- ID string `json:"id"`
356
- Object string `json:"object"`
357
- OwnedBy string `json:"owned_by"`
358
- Permission []string `json:"permission"`
359
- }
360
-
361
- type ModelListResponse struct {
362
- Object string `json:"object"`
363
- Data []Model `json:"data"`
364
- }
365
-
366
- func listModelsHandler(w http.ResponseWriter, r *http.Request) {
367
- w.Header().Set("Access-Control-Allow-Origin", "*")
368
- w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
369
- w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
370
-
371
- if r.Method == "OPTIONS" {
372
- w.WriteHeader(http.StatusOK)
373
- return
374
- }
375
- authMiddleware(func(w http.ResponseWriter, r *http.Request) {
376
- models := []Model{
377
- {ID: "gpt-4o", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
378
- {ID: "claude-3.5-sonnet", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
379
- {ID: "deepseek-reasoner", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
380
- {ID: "o3-mini", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
381
- {ID: "o1", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
382
- {ID: "llama-3.1-405b", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
383
- {ID: "gemini-2.0-pro", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
384
- }
385
-
386
- response := ModelListResponse{
387
- Object: "list",
388
- Data: models,
389
- }
390
-
391
  w.Header().Set("Content-Type", "application/json")
392
- json.NewEncoder(w).Encode(response)
393
- })(w, r)
394
- }
395
-
396
- // 修改 handleNonStreamResponse 函数
397
- func handleNonStreamResponse(w http.ResponseWriter, resp *http.Response, model string) {
398
- w.Header().Set("Content-Type", "application/json")
399
- fullResponse := ""
400
- reader := bufio.NewReader(resp.Body)
401
 
402
- for {
403
- line, err := reader.ReadString('\n')
404
- if err != nil {
405
- if err == io.EOF {
406
- break
 
 
 
407
  }
408
- http.Error(w, "读取响应失败", http.StatusInternalServerError)
409
- return
410
- }
411
 
412
- line = strings.TrimSpace(line)
413
- line = strings.TrimPrefix(line, "data:")
414
 
415
- if line == "" || line == "[DONE]" {
416
- continue
417
- }
418
 
419
- var siderResp SiderResponse
420
- if err := json.Unmarshal([]byte(line), &siderResp); err != nil {
421
- continue
422
- }
423
 
424
- fullResponse += siderResp.Data.Text
425
- }
426
 
427
- openAIResp := OpenAIResponse{
428
- ID: "chatcmpl-" + time.Now().Format("20060102150405"),
429
- Object: "chat.completion",
430
- Created: time.Now().Unix(),
431
- Model: model, // 使用传入的模型名称
432
- Choices: []struct {
433
- Message struct {
434
- Role string `json:"role"`
435
- Content string `json:"content"`
436
- } `json:"message"`
437
- FinishReason string `json:"finish_reason"`
438
- Index int `json:"index"`
439
- }{
440
- {
441
- Message: struct {
442
  Role string `json:"role"`
443
  Content string `json:"content"`
444
- }{
445
- Role: "assistant",
446
- Content: fullResponse,
 
 
 
 
 
 
 
 
 
 
 
447
  },
448
- FinishReason: "stop",
449
- Index: 0,
450
  },
451
- },
452
- Usage: struct {
453
- PromptTokens int `json:"prompt_tokens"`
454
- CompletionTokens int `json:"completion_tokens"`
455
- TotalTokens int `json:"total_tokens"`
456
- }{
457
- PromptTokens: 0,
458
- CompletionTokens: len(fullResponse),
459
- TotalTokens: len(fullResponse),
460
- },
461
- }
462
 
463
- json.NewEncoder(w).Encode(openAIResp)
464
- }
 
465
 
466
- // 修改 handleStreamResponse 函数
467
- func handleStreamResponse(w http.ResponseWriter, resp *http.Response, model string) {
468
  w.Header().Set("Content-Type", "text/event-stream")
469
  w.Header().Set("Cache-Control", "no-cache")
470
  w.Header().Set("Connection", "keep-alive")
471
  w.WriteHeader(http.StatusOK)
472
 
 
473
  reader := bufio.NewReader(resp.Body)
474
 
475
  for {
@@ -483,13 +341,16 @@ func handleStreamResponse(w http.ResponseWriter, resp *http.Response, model stri
483
  return
484
  }
485
 
 
486
  line = strings.TrimSpace(line)
487
  line = strings.TrimPrefix(line, "data:")
488
 
 
489
  if line == "" {
490
  continue
491
  }
492
 
 
493
  if line == "[DONE]" {
494
  _, err = w.Write([]byte("data: [DONE]\n\n"))
495
  if err != nil {
@@ -499,17 +360,19 @@ func handleStreamResponse(w http.ResponseWriter, resp *http.Response, model stri
499
  break
500
  }
501
 
 
502
  var siderResp SiderResponse
503
  if err := json.Unmarshal([]byte(line), &siderResp); err != nil {
504
  fmt.Printf("解析Sider响应失败: %v\n", err)
505
  continue
506
  }
507
 
 
508
  openAIResp := OpenAIStreamResponse{
509
- ID: "chatcmpl-" + time.Now().Format("20060102150405"),
510
  Object: "chat.completion.chunk",
511
  Created: time.Now().Unix(),
512
- Model: model, // 使用传入的模型名称
513
  Choices: []struct {
514
  Delta struct {
515
  Content string `json:"content"`
@@ -529,12 +392,14 @@ func handleStreamResponse(w http.ResponseWriter, resp *http.Response, model stri
529
  },
530
  }
531
 
 
532
  openAIJSON, err := json.Marshal(openAIResp)
533
  if err != nil {
534
  fmt.Printf("转换OpenAI格式失败: %v\n", err)
535
  continue
536
  }
537
 
 
538
  _, err = w.Write([]byte("data: " + string(openAIJSON) + "\n\n"))
539
  if err != nil {
540
  fmt.Printf("写入响应失败: %v\n", err)
@@ -544,6 +409,53 @@ func handleStreamResponse(w http.ResponseWriter, resp *http.Response, model stri
544
  }
545
  }
546
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  func main() {
548
  // 注册路由处理函数
549
  http.HandleFunc("/", indexHandler) // 添加主页路由
 
131
  }
132
  }
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  func forwardToSider(w http.ResponseWriter, r *http.Request) {
135
  fmt.Printf("收到新请求: %s %s\n", r.Method, r.URL.Path)
136
 
 
166
  return
167
  }
168
 
169
+ // 获取全部用户消息内容,并合并为一条带多角色前缀的消息
170
+ mergedPrompt := "你好" // 默认提示词,当消息数组为空时使用
171
+ if len(userReq.Messages) > 0 {
172
+ var builder strings.Builder
173
+ // 依次遍历所有历史消息
174
+ for i, msg := range userReq.Messages {
175
+ // 例如:[user] 请求内容 或者 [assistant] 回复内容
176
+ builder.WriteString(fmt.Sprintf("[%s] %s", msg.Role, msg.Content))
177
+ if i < len(userReq.Messages)-1 {
178
+ builder.WriteString("\n")
179
+ }
180
+ }
181
+ mergedPrompt = builder.String()
182
  }
183
+ fmt.Printf("处理的mergedPrompt: %s\n", mergedPrompt)
184
 
185
+ // 添加prompt到配置中(使用合并后的所有消息)
186
+ defaultConfig["prompt"] = mergedPrompt
 
 
 
 
187
 
188
  // 添加model到配置中
189
  if userReq.Model != "" {
 
197
 
198
  fmt.Printf("使用的模型: %s\n", defaultConfig["model"])
199
 
200
+ // 转换回JSON
201
+ finalBody, err := json.Marshal(defaultConfig)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  if err != nil {
203
  fmt.Printf("生成最终请求体失败: %v\n", err)
204
  http.Error(w, "处理请求失败", http.StatusInternalServerError)
 
250
 
251
  fmt.Printf("Sider响应状态码: %d\n", resp.StatusCode)
252
 
253
+ if !userReq.Stream {
254
+ // 非流式响应
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  w.Header().Set("Content-Type", "application/json")
256
+ fullResponse := ""
257
+ reader := bufio.NewReader(resp.Body)
 
 
 
 
 
 
 
258
 
259
+ for {
260
+ line, err := reader.ReadString('\n')
261
+ if err != nil {
262
+ if err == io.EOF {
263
+ break
264
+ }
265
+ http.Error(w, "读取响应失败", http.StatusInternalServerError)
266
+ return
267
  }
 
 
 
268
 
269
+ line = strings.TrimSpace(line)
270
+ line = strings.TrimPrefix(line, "data:")
271
 
272
+ if line == "" || line == "[DONE]" {
273
+ continue
274
+ }
275
 
276
+ var siderResp SiderResponse
277
+ if err := json.Unmarshal([]byte(line), &siderResp); err != nil {
278
+ continue
279
+ }
280
 
281
+ fullResponse += siderResp.Data.Text
282
+ }
283
 
284
+ openAIResp := OpenAIResponse{
285
+ ID: "chatcmpl-" + time.Now().Format("20060102150405"),
286
+ Object: "chat.completion",
287
+ Created: time.Now().Unix(),
288
+ Model: userReq.Model,
289
+ Choices: []struct {
290
+ Message struct {
 
 
 
 
 
 
 
 
291
  Role string `json:"role"`
292
  Content string `json:"content"`
293
+ } `json:"message"`
294
+ FinishReason string `json:"finish_reason"`
295
+ Index int `json:"index"`
296
+ }{
297
+ {
298
+ Message: struct {
299
+ Role string `json:"role"`
300
+ Content string `json:"content"`
301
+ }{
302
+ Role: "assistant",
303
+ Content: fullResponse,
304
+ },
305
+ FinishReason: "stop",
306
+ Index: 0,
307
  },
 
 
308
  },
309
+ Usage: struct {
310
+ PromptTokens int `json:"prompt_tokens"`
311
+ CompletionTokens int `json:"completion_tokens"`
312
+ TotalTokens int `json:"total_tokens"`
313
+ }{
314
+ PromptTokens: len(mergedPrompt),
315
+ CompletionTokens: len(fullResponse),
316
+ TotalTokens: len(mergedPrompt) + len(fullResponse),
317
+ },
318
+ }
 
319
 
320
+ json.NewEncoder(w).Encode(openAIResp)
321
+ return
322
+ }
323
 
324
+ // 流式响应
 
325
  w.Header().Set("Content-Type", "text/event-stream")
326
  w.Header().Set("Cache-Control", "no-cache")
327
  w.Header().Set("Connection", "keep-alive")
328
  w.WriteHeader(http.StatusOK)
329
 
330
+ // 使用bufio.Reader来读取流式响应
331
  reader := bufio.NewReader(resp.Body)
332
 
333
  for {
 
341
  return
342
  }
343
 
344
+ // 去除前缀和空白字符
345
  line = strings.TrimSpace(line)
346
  line = strings.TrimPrefix(line, "data:")
347
 
348
+ // 跳过空行
349
  if line == "" {
350
  continue
351
  }
352
 
353
+ // 如果是[DONE],发送OpenAI格式的[DONE]
354
  if line == "[DONE]" {
355
  _, err = w.Write([]byte("data: [DONE]\n\n"))
356
  if err != nil {
 
360
  break
361
  }
362
 
363
+ // 解析Sider响应
364
  var siderResp SiderResponse
365
  if err := json.Unmarshal([]byte(line), &siderResp); err != nil {
366
  fmt.Printf("解析Sider响应失败: %v\n", err)
367
  continue
368
  }
369
 
370
+ // 转换为OpenAI格式
371
  openAIResp := OpenAIStreamResponse{
372
+ ID: "chatcmpl-" + siderResp.Data.ChatModel,
373
  Object: "chat.completion.chunk",
374
  Created: time.Now().Unix(),
375
+ Model: siderResp.Data.ChatModel,
376
  Choices: []struct {
377
  Delta struct {
378
  Content string `json:"content"`
 
392
  },
393
  }
394
 
395
+ // 转换为JSON
396
  openAIJSON, err := json.Marshal(openAIResp)
397
  if err != nil {
398
  fmt.Printf("转换OpenAI格式失败: %v\n", err)
399
  continue
400
  }
401
 
402
+ // 发送OpenAI格式的响应
403
  _, err = w.Write([]byte("data: " + string(openAIJSON) + "\n\n"))
404
  if err != nil {
405
  fmt.Printf("写入响应失败: %v\n", err)
 
409
  }
410
  }
411
 
412
+ func indexHandler(w http.ResponseWriter, r *http.Request) {
413
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
414
+ fmt.Fprintf(w, "🚀服务已启动!")
415
+ }
416
+
417
+ type Model struct {
418
+ ID string `json:"id"`
419
+ Object string `json:"object"`
420
+ OwnedBy string `json:"owned_by"`
421
+ Permission []string `json:"permission"`
422
+ }
423
+
424
+ type ModelListResponse struct {
425
+ Object string `json:"object"`
426
+ Data []Model `json:"data"`
427
+ }
428
+
429
+ func listModelsHandler(w http.ResponseWriter, r *http.Request) {
430
+ w.Header().Set("Access-Control-Allow-Origin", "*")
431
+ w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
432
+ w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
433
+
434
+ if r.Method == "OPTIONS" {
435
+ w.WriteHeader(http.StatusOK)
436
+ return
437
+ }
438
+ authMiddleware(func(w http.ResponseWriter, r *http.Request) {
439
+ models := []Model{
440
+ {ID: "gpt-4o", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
441
+ {ID: "claude-3.5-sonnet", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
442
+ {ID: "deepseek-reasoner", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
443
+ {ID: "o3-mini", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
444
+ {ID: "o1", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
445
+ {ID: "llama-3.1-405b", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
446
+ {ID: "gemini-2.0-pro", Object: "model", OwnedBy: "sider", Permission: []string{"read"}},
447
+ }
448
+
449
+ response := ModelListResponse{
450
+ Object: "list",
451
+ Data: models,
452
+ }
453
+
454
+ w.Header().Set("Content-Type", "application/json")
455
+ json.NewEncoder(w).Encode(response)
456
+ })(w, r)
457
+ }
458
+
459
  func main() {
460
  // 注册路由处理函数
461
  http.HandleFunc("/", indexHandler) // 添加主页路由