Spaces:
Configuration error
Configuration error
BOHE
commited on
Commit
·
fb2b2c5
1
Parent(s):
fed4dbc
修改上下文处理方式测试
Browse files- api/main.go +149 -110
api/main.go
CHANGED
|
@@ -245,91 +245,84 @@ func Handler(w http.ResponseWriter, r *http.Request) {
|
|
| 245 |
// 构建 You.com 聊天历史
|
| 246 |
var chatHistory []map[string]interface{}
|
| 247 |
var sources []map[string]interface{}
|
|
|
|
|
|
|
| 248 |
|
| 249 |
-
//
|
| 250 |
-
for i := 0; i < len(openAIReq.Messages)
|
| 251 |
-
|
| 252 |
-
userMsg := openAIReq.Messages[i]
|
| 253 |
-
assistantMsg := openAIReq.Messages[i+1]
|
| 254 |
-
|
| 255 |
-
if userMsg.Role == "user" && assistantMsg.Role == "assistant" {
|
| 256 |
-
// 获取 nonce
|
| 257 |
-
nonceResp, err := getNonce(dsToken)
|
| 258 |
-
if err != nil {
|
| 259 |
-
fmt.Printf("获取 nonce 失败: %v\n", err)
|
| 260 |
-
http.Error(w, "Failed to get nonce", http.StatusInternalServerError)
|
| 261 |
-
return
|
| 262 |
-
}
|
| 263 |
-
|
| 264 |
-
// 创建临时文件
|
| 265 |
-
tempFile := fmt.Sprintf("temp_%s.txt", nonceResp.Uuid)
|
| 266 |
-
if err := os.WriteFile(tempFile, []byte(userMsg.Content), 0644); err != nil {
|
| 267 |
-
fmt.Printf("创建临时文件失败: %v\n", err)
|
| 268 |
-
http.Error(w, "Failed to create temp file", http.StatusInternalServerError)
|
| 269 |
-
return
|
| 270 |
-
}
|
| 271 |
-
defer os.Remove(tempFile)
|
| 272 |
-
|
| 273 |
-
// 上传文件
|
| 274 |
-
uploadResp, err := uploadFile(dsToken, tempFile)
|
| 275 |
-
if err != nil {
|
| 276 |
-
fmt.Printf("上传文件失败: %v\n", err)
|
| 277 |
-
http.Error(w, "Failed to upload file", http.StatusInternalServerError)
|
| 278 |
-
return
|
| 279 |
-
}
|
| 280 |
-
|
| 281 |
-
// 添加文件源信息
|
| 282 |
-
sources = append(sources, map[string]interface{}{
|
| 283 |
-
"source_type": "user_file",
|
| 284 |
-
"filename": uploadResp.Filename,
|
| 285 |
-
"user_filename": uploadResp.UserFilename,
|
| 286 |
-
"size_bytes": len(userMsg.Content),
|
| 287 |
-
})
|
| 288 |
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
http.Error(w, "Failed to get nonce", http.StatusInternalServerError)
|
| 294 |
-
return
|
| 295 |
-
}
|
| 296 |
-
|
| 297 |
-
// 创建临时文件
|
| 298 |
-
tempFileAssistant := fmt.Sprintf("temp_%s.txt", nonceRespAssistant.Uuid)
|
| 299 |
-
if err := os.WriteFile(tempFileAssistant, []byte(assistantMsg.Content), 0644); err != nil {
|
| 300 |
-
fmt.Printf("创建临时文件失败: %v\n", err)
|
| 301 |
-
http.Error(w, "Failed to create temp file", http.StatusInternalServerError)
|
| 302 |
-
return
|
| 303 |
-
}
|
| 304 |
-
defer os.Remove(tempFileAssistant)
|
| 305 |
-
|
| 306 |
-
// 上传文件
|
| 307 |
-
uploadRespAssistant, err := uploadFile(dsToken, tempFileAssistant)
|
| 308 |
-
if err != nil {
|
| 309 |
-
fmt.Printf("上传文件失败: %v\n", err)
|
| 310 |
-
http.Error(w, "Failed to upload file", http.StatusInternalServerError)
|
| 311 |
-
return
|
| 312 |
-
}
|
| 313 |
-
|
| 314 |
-
// 添加文件源信息
|
| 315 |
-
sources = append(sources, map[string]interface{}{
|
| 316 |
-
"source_type": "user_file",
|
| 317 |
-
"filename": uploadRespAssistant.Filename,
|
| 318 |
-
"user_filename": uploadRespAssistant.UserFilename,
|
| 319 |
-
"size_bytes": len(assistantMsg.Content),
|
| 320 |
-
})
|
| 321 |
|
| 322 |
-
|
|
|
|
|
|
|
| 323 |
chatHistory = append(chatHistory, map[string]interface{}{
|
| 324 |
-
"question":
|
| 325 |
-
"answer":
|
| 326 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
}
|
| 328 |
}
|
| 329 |
}
|
| 330 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
chatHistoryJSON, _ := json.Marshal(chatHistory)
|
| 332 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 333 |
// 创建 You.com API 请求
|
| 334 |
youReq, _ := http.NewRequest("GET", "https://you.com/api/streamingSearch", nil)
|
| 335 |
|
|
@@ -340,40 +333,12 @@ func Handler(w http.ResponseWriter, r *http.Request) {
|
|
| 340 |
|
| 341 |
// 处理最后一条消息
|
| 342 |
lastMessage := openAIReq.Messages[len(openAIReq.Messages)-1]
|
| 343 |
-
|
| 344 |
-
// 获取 nonce
|
| 345 |
-
nonceResp, err := getNonce(dsToken)
|
| 346 |
if err != nil {
|
| 347 |
-
|
| 348 |
-
http.Error(w, "Failed to get nonce", http.StatusInternalServerError)
|
| 349 |
return
|
| 350 |
}
|
| 351 |
|
| 352 |
-
// 创建临时文件
|
| 353 |
-
tempFile := fmt.Sprintf("temp_%s.txt", nonceResp.Uuid)
|
| 354 |
-
if err := os.WriteFile(tempFile, []byte(lastMessage.Content), 0644); err != nil {
|
| 355 |
-
fmt.Printf("创建临时文件失败: %v\n", err)
|
| 356 |
-
http.Error(w, "Failed to create temp file", http.StatusInternalServerError)
|
| 357 |
-
return
|
| 358 |
-
}
|
| 359 |
-
defer os.Remove(tempFile)
|
| 360 |
-
|
| 361 |
-
// 上传文件
|
| 362 |
-
uploadResp, err := uploadFile(dsToken, tempFile)
|
| 363 |
-
if err != nil {
|
| 364 |
-
fmt.Printf("上传文件失败: %v\n", err)
|
| 365 |
-
http.Error(w, "Failed to upload file", http.StatusInternalServerError)
|
| 366 |
-
return
|
| 367 |
-
}
|
| 368 |
-
|
| 369 |
-
// 添加文件源信息
|
| 370 |
-
sources = append(sources, map[string]interface{}{
|
| 371 |
-
"source_type": "user_file",
|
| 372 |
-
"filename": uploadResp.Filename,
|
| 373 |
-
"user_filename": uploadResp.UserFilename,
|
| 374 |
-
"size_bytes": len(lastMessage.Content),
|
| 375 |
-
})
|
| 376 |
-
|
| 377 |
// 构建查询参数
|
| 378 |
q := youReq.URL.Query()
|
| 379 |
|
|
@@ -395,13 +360,61 @@ func Handler(w http.ResponseWriter, r *http.Request) {
|
|
| 395 |
q.Add("traceId", traceId)
|
| 396 |
q.Add("use_nested_youchat_updates", "true")
|
| 397 |
|
| 398 |
-
//
|
| 399 |
-
|
| 400 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 401 |
|
| 402 |
-
// 使用文件引用作为查询
|
| 403 |
-
q.Add("q", fmt.Sprintf("Please review the attached file: %s", uploadResp.UserFilename))
|
| 404 |
-
q.Add("chat", string(chatHistoryJSON))
|
| 405 |
youReq.URL.RawQuery = q.Encode()
|
| 406 |
|
| 407 |
fmt.Printf("\n=== 完整请求信息 ===\n")
|
|
@@ -661,6 +674,32 @@ func uploadFile(dsToken, filePath string) (*UploadResponse, error) {
|
|
| 661 |
return &uploadResp, nil
|
| 662 |
}
|
| 663 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 664 |
// 将 system 消息转换为第一条 user 消息
|
| 665 |
func convertSystemToUser(messages []Message) []Message {
|
| 666 |
if len(messages) == 0 {
|
|
|
|
| 245 |
// 构建 You.com 聊天历史
|
| 246 |
var chatHistory []map[string]interface{}
|
| 247 |
var sources []map[string]interface{}
|
| 248 |
+
var lastUserMessage string
|
| 249 |
+
var lastAssistantMessage string
|
| 250 |
|
| 251 |
+
// 处理历史消息
|
| 252 |
+
for i := 0; i < len(openAIReq.Messages); i++ {
|
| 253 |
+
msg := openAIReq.Messages[i]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
|
| 255 |
+
if msg.Role == "user" {
|
| 256 |
+
lastUserMessage = msg.Content
|
| 257 |
+
} else if msg.Role == "assistant" {
|
| 258 |
+
lastAssistantMessage = msg.Content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
|
| 260 |
+
// 当我们找到一个assistant消息,将其与前面最近的user消息配对
|
| 261 |
+
if lastUserMessage != "" {
|
| 262 |
+
// 添加一条完整的问答对
|
| 263 |
chatHistory = append(chatHistory, map[string]interface{}{
|
| 264 |
+
"question": lastUserMessage,
|
| 265 |
+
"answer": lastAssistantMessage,
|
| 266 |
})
|
| 267 |
+
|
| 268 |
+
// 重置消息,防止重复添加
|
| 269 |
+
lastUserMessage = ""
|
| 270 |
+
lastAssistantMessage = ""
|
| 271 |
}
|
| 272 |
}
|
| 273 |
}
|
| 274 |
|
| 275 |
+
// 如果还有未配对的用户消息(最后一条),将其添加到历史记录中
|
| 276 |
+
if lastUserMessage != "" {
|
| 277 |
+
chatHistory = append(chatHistory, map[string]interface{}{
|
| 278 |
+
"question": lastUserMessage,
|
| 279 |
+
"answer": "",
|
| 280 |
+
})
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
// 将聊天历史转换为JSON
|
| 284 |
chatHistoryJSON, _ := json.Marshal(chatHistory)
|
| 285 |
|
| 286 |
+
// 使用文件上传方式处理所有历史消息
|
| 287 |
+
var chatFileURL string
|
| 288 |
+
if len(chatHistory) > 0 {
|
| 289 |
+
// 获取 nonce
|
| 290 |
+
nonceResp, err := getNonce(dsToken)
|
| 291 |
+
if err != nil {
|
| 292 |
+
fmt.Printf("获取历史消息nonce失败: %v\n", err)
|
| 293 |
+
http.Error(w, "Failed to get nonce for chat history", http.StatusInternalServerError)
|
| 294 |
+
return
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
// 创建临时文件存储历史消息
|
| 298 |
+
tempChatFile := fmt.Sprintf("temp_chat_%s.txt", nonceResp.Uuid)
|
| 299 |
+
if err := os.WriteFile(tempChatFile, chatHistoryJSON, 0644); err != nil {
|
| 300 |
+
fmt.Printf("创建历史消息临时文件失败: %v\n", err)
|
| 301 |
+
http.Error(w, "Failed to create temp file for chat history", http.StatusInternalServerError)
|
| 302 |
+
return
|
| 303 |
+
}
|
| 304 |
+
defer os.Remove(tempChatFile)
|
| 305 |
+
|
| 306 |
+
// 上传历史消息文件
|
| 307 |
+
uploadChatResp, err := uploadFile(dsToken, tempChatFile)
|
| 308 |
+
if err != nil {
|
| 309 |
+
fmt.Printf("上传历史消息文件失败: %v\n", err)
|
| 310 |
+
http.Error(w, "Failed to upload chat history file", http.StatusInternalServerError)
|
| 311 |
+
return
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
// 添加历史消息文件源信息
|
| 315 |
+
sources = append(sources, map[string]interface{}{
|
| 316 |
+
"source_type": "chat_history_file",
|
| 317 |
+
"filename": uploadChatResp.Filename,
|
| 318 |
+
"user_filename": uploadChatResp.UserFilename,
|
| 319 |
+
"size_bytes": len(string(chatHistoryJSON)),
|
| 320 |
+
})
|
| 321 |
+
|
| 322 |
+
// 保存历史消息文件URL
|
| 323 |
+
chatFileURL = uploadChatResp.Filename
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
// 创建 You.com API 请求
|
| 327 |
youReq, _ := http.NewRequest("GET", "https://you.com/api/streamingSearch", nil)
|
| 328 |
|
|
|
|
| 333 |
|
| 334 |
// 处理最后一条消息
|
| 335 |
lastMessage := openAIReq.Messages[len(openAIReq.Messages)-1]
|
| 336 |
+
lastMessageTokens, err := countTokens([]Message{lastMessage})
|
|
|
|
|
|
|
| 337 |
if err != nil {
|
| 338 |
+
http.Error(w, "Failed to count tokens", http.StatusInternalServerError)
|
|
|
|
| 339 |
return
|
| 340 |
}
|
| 341 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
// 构建查询参数
|
| 343 |
q := youReq.URL.Query()
|
| 344 |
|
|
|
|
| 360 |
q.Add("traceId", traceId)
|
| 361 |
q.Add("use_nested_youchat_updates", "true")
|
| 362 |
|
| 363 |
+
// 如果有聊天历史文件,添加到查询参数
|
| 364 |
+
if chatFileURL != "" {
|
| 365 |
+
q.Add("chat", chatFileURL)
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
// 如果最后一条消息超过限制,使用文件上传
|
| 369 |
+
if lastMessageTokens > MaxContextTokens {
|
| 370 |
+
// 获取 nonce
|
| 371 |
+
nonceResp, err := getNonce(dsToken)
|
| 372 |
+
if err != nil {
|
| 373 |
+
fmt.Printf("获取 nonce 失败: %v\n", err)
|
| 374 |
+
http.Error(w, "Failed to get nonce", http.StatusInternalServerError)
|
| 375 |
+
return
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
// 创建临时文件
|
| 379 |
+
tempFile := fmt.Sprintf("temp_%s.txt", nonceResp.Uuid)
|
| 380 |
+
if err := os.WriteFile(tempFile, []byte(lastMessage.Content), 0644); err != nil {
|
| 381 |
+
fmt.Printf("创建临时文件失败: %v\n", err)
|
| 382 |
+
http.Error(w, "Failed to create temp file", http.StatusInternalServerError)
|
| 383 |
+
return
|
| 384 |
+
}
|
| 385 |
+
defer os.Remove(tempFile)
|
| 386 |
+
|
| 387 |
+
// 上传文件
|
| 388 |
+
uploadResp, err := uploadFile(dsToken, tempFile)
|
| 389 |
+
if err != nil {
|
| 390 |
+
fmt.Printf("上传文件失败: %v\n", err)
|
| 391 |
+
http.Error(w, "Failed to upload file", http.StatusInternalServerError)
|
| 392 |
+
return
|
| 393 |
+
}
|
| 394 |
+
|
| 395 |
+
// 添加文件源信息
|
| 396 |
+
sources = append(sources, map[string]interface{}{
|
| 397 |
+
"source_type": "user_file",
|
| 398 |
+
"filename": uploadResp.Filename,
|
| 399 |
+
"user_filename": uploadResp.UserFilename,
|
| 400 |
+
"size_bytes": len(lastMessage.Content),
|
| 401 |
+
})
|
| 402 |
+
|
| 403 |
+
// 添加 sources 参数
|
| 404 |
+
sourcesJSON, _ := json.Marshal(sources)
|
| 405 |
+
q.Add("sources", string(sourcesJSON))
|
| 406 |
+
|
| 407 |
+
// 使用文件引用作为查询
|
| 408 |
+
q.Add("q", fmt.Sprintf("Please review the attached file: %s", uploadResp.UserFilename))
|
| 409 |
+
} else {
|
| 410 |
+
// 如果有之前上传的文件,添加 sources
|
| 411 |
+
if len(sources) > 0 {
|
| 412 |
+
sourcesJSON, _ := json.Marshal(sources)
|
| 413 |
+
q.Add("sources", string(sourcesJSON))
|
| 414 |
+
}
|
| 415 |
+
q.Add("q", lastMessage.Content)
|
| 416 |
+
}
|
| 417 |
|
|
|
|
|
|
|
|
|
|
| 418 |
youReq.URL.RawQuery = q.Encode()
|
| 419 |
|
| 420 |
fmt.Printf("\n=== 完整请求信息 ===\n")
|
|
|
|
| 674 |
return &uploadResp, nil
|
| 675 |
}
|
| 676 |
|
| 677 |
+
// 计算消息的 token 数(使用字符估算方法)
|
| 678 |
+
func countTokens(messages []Message) (int, error) {
|
| 679 |
+
totalTokens := 0
|
| 680 |
+
for _, msg := range messages {
|
| 681 |
+
content := msg.Content
|
| 682 |
+
englishCount := 0
|
| 683 |
+
chineseCount := 0
|
| 684 |
+
|
| 685 |
+
// 遍历每个字符
|
| 686 |
+
for _, r := range content {
|
| 687 |
+
if r <= 127 { // ASCII 字符(英文和符号)
|
| 688 |
+
englishCount++
|
| 689 |
+
} else { // 非 ASCII 字符(中文等)
|
| 690 |
+
chineseCount++
|
| 691 |
+
}
|
| 692 |
+
}
|
| 693 |
+
|
| 694 |
+
// 计算 tokens:英文字符 * 0.3 + 中文字符 * 0.6
|
| 695 |
+
tokens := int(float64(englishCount)*0.3 + float64(chineseCount)*1)
|
| 696 |
+
|
| 697 |
+
// 加上角色名的 token(约 2 个)
|
| 698 |
+
totalTokens += tokens + 2
|
| 699 |
+
}
|
| 700 |
+
return totalTokens, nil
|
| 701 |
+
}
|
| 702 |
+
|
| 703 |
// 将 system 消息转换为第一条 user 消息
|
| 704 |
func convertSystemToUser(messages []Message) []Message {
|
| 705 |
if len(messages) == 0 {
|