openai_gateway_grok_chat_image_tools.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package service
  2. import (
  3. "encoding/json"
  4. "strings"
  5. "github.com/tidwall/gjson"
  6. "github.com/tidwall/sjson"
  7. )
  8. // 当前轮的内联 image_url 已可由 Grok 直接读取;若同时保留客户端本地
  9. // view_image,Grok 可能只预告调用工具而不继续作答,因此只移除这一冗余自动选择。
  10. func stripRedundantGrokChatViewImageTool(body []byte) ([]byte, error) {
  11. messages := gjson.GetBytes(body, "messages")
  12. if !messages.IsArray() {
  13. return body, nil
  14. }
  15. items := messages.Array()
  16. if len(items) == 0 {
  17. return body, nil
  18. }
  19. current := items[len(items)-1]
  20. if strings.TrimSpace(current.Get("role").String()) != "user" ||
  21. !openAIJSONValueMayContainImageInput(current) {
  22. return body, nil
  23. }
  24. toolChoice := gjson.GetBytes(body, "tool_choice")
  25. if toolChoice.IsObject() && strings.TrimSpace(toolChoice.Get("type").String()) == "function" {
  26. choiceName := strings.TrimSpace(toolChoice.Get("function.name").String())
  27. if choiceName == "" {
  28. choiceName = strings.TrimSpace(toolChoice.Get("name").String())
  29. }
  30. if choiceName == "view_image" {
  31. return body, nil
  32. }
  33. }
  34. tools := gjson.GetBytes(body, "tools")
  35. if !tools.IsArray() {
  36. return body, nil
  37. }
  38. filtered := make([]json.RawMessage, 0, len(tools.Array()))
  39. changed := false
  40. for _, tool := range tools.Array() {
  41. toolName := strings.TrimSpace(tool.Get("function.name").String())
  42. if toolName == "" {
  43. toolName = strings.TrimSpace(tool.Get("name").String())
  44. }
  45. if strings.TrimSpace(tool.Get("type").String()) == "function" && toolName == "view_image" {
  46. changed = true
  47. continue
  48. }
  49. filtered = append(filtered, json.RawMessage(tool.Raw))
  50. }
  51. if !changed {
  52. return body, nil
  53. }
  54. if len(filtered) == 0 && strings.TrimSpace(toolChoice.String()) == "required" {
  55. return body, nil
  56. }
  57. if len(filtered) > 0 {
  58. encoded, err := json.Marshal(filtered)
  59. if err != nil {
  60. return nil, err
  61. }
  62. return sjson.SetRawBytes(body, "tools", encoded)
  63. }
  64. out, err := sjson.DeleteBytes(body, "tools")
  65. if err != nil {
  66. return nil, err
  67. }
  68. out, err = sjson.DeleteBytes(out, "parallel_tool_calls")
  69. if err != nil {
  70. return nil, err
  71. }
  72. if strings.TrimSpace(toolChoice.String()) == "auto" {
  73. out, err = sjson.DeleteBytes(out, "tool_choice")
  74. }
  75. return out, err
  76. }