mismatch.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package compapi
  2. import (
  3. "errors"
  4. "fmt"
  5. "wechat-api/ent"
  6. "wechat-api/internal/types"
  7. "github.com/openai/openai-go"
  8. )
  9. type MismatchClient struct {
  10. StdClient
  11. }
  12. // Generate the JSON schema at initialization time
  13. var MismatchResponseSchema = GenerateSchema[MismatchResponse]()
  14. type MismatchResponse struct {
  15. UserIntent string `json:"user_intent" jsonschema_description:"用户意图"`
  16. SimilarReply []string `json:"similar_reply" jsonschema_description:"类似回复"`
  17. Keywords []string `json:"keywords" jsonschema_description:"关键词库"`
  18. Regular []string `json:"regular" jsonschema_description:"正则表达式"`
  19. }
  20. /*
  21. "response_format":{"type":"json_object"}}
  22. {"type":"json_schema",
  23. "json_schema":{
  24. "description":"从通话记录中提取表单","name":"keyword_schema","schema":{
  25. "$schema":"https://json-schema.org/draft/2020-12/schema","additionalProperties":false,"properties":{
  26. "keywords":{
  27. "description":"关键词库","items":{"type":"string"},"type":"array"},"regular":{"description":"正则表达式","items":{"type":"string"},"type":"array"},"similar_reply":{"description":"类似回复","items":{"type":"string"},"type":"array"},"swear_words":{"description":"脏话列表","items":{"type":"string"},"type":"array"},"user_intent":{"description":"用户意图","type":"string"},"user_mood":{"description":"用户情绪","type":"string"}},"required":["user_intent","similar_reply","keywords","regular","user_mood","swear_words"],"type":"object"},"strict":true}}
  28. */
  29. func (me *MismatchClient) BuildRequest(req *types.CompApiReq) error {
  30. //先重构message
  31. newMessSlice := make([]types.StdCompMessage, 2)
  32. newMessSlice[0] = types.StdCompMessage{Role: "system", Content: ` # 任务介绍
  33. 公司在用程序巡检电话通话记录时,有些用户的回复内容没有被关键词库识别到,请根据以下通话记录,给出一些类似的回复,以及对关键词库的具体建议,非常感谢!
  34. # 输出要求
  35. 1. 用户意图:结合上下文,首先考虑可能的语音识别错误并纠错,然后分析未识别内容的根本意图,用户说这句话的背后真实目的是什么,结合上下文挖掘用户最深的意图,请不要停留在表面的意思。
  36. 2. 类似回复:首先应包含未识别的内容原文:` + req.Variables["missed"] + `。其次生成尽可能多的类似意图的回复。
  37. 2. 关键词库:从类似回复中抽取特征词,要求有两点:一是特征词应尽可能的准确,即要覆盖住此类问题,又要尽可能避免和其他语境相冲突。二是需要注重通用性,一些专有名词、人名、地名、产品名、公司名等需要排除在外。
  38. 3. 正则表达式:对关键词词进行解耦,用正则表达式进行表示,专注于主要内容,排除次要内容
  39. # 注意事项
  40. 1. 应贴近真实的外呼场景,用户的素质参差不齐,请避免使用任何浮夸的用词,避免使用高级词汇,避免使用任何的礼貌用语或敬语,适当的低素质些,请至少给出20条结果
  41. 2. 通话记录为录音转译,因此可能有错别字或音同字不同的情况(例如:借和接),请根据上下文分析后就成可能的错字错误
  42. 3. 正则关键词库和正则表达式中也应该考虑到音同字不同的情况,且避免使用匹配次数相关的语法如{0,2}`}
  43. newMessSlice[1] = types.StdCompMessage{Role: "user", Content: `
  44. # 通话记录` + req.Variables["chat_history"] + `
  45. # 可能识别有误的内容:` + req.Variables["missed"]}
  46. //再构造ResponseFormat
  47. if !IsOpenaiModel(req.Model) {
  48. newMessSlice[1].Content = newMessSlice[1].Content.(string) + `{
  49. "user_intent": str, #用户意图
  50. "similar_reply": list[str], #类似回复
  51. "keywords": list[str], #关键词库
  52. "regular": list[str], #正则表达式
  53. }`
  54. req.ResponseFormat = openai.ResponseFormatJSONObjectParam{Type: "json_object"}
  55. } else {
  56. schemaParam := openai.ResponseFormatJSONSchemaJSONSchemaParam{
  57. Name: "keyword_schema",
  58. Description: openai.String("从通话记录中提取表单"),
  59. Schema: MismatchResponseSchema,
  60. Strict: openai.Bool(true),
  61. }
  62. req.ResponseFormat = openai.ResponseFormatJSONSchemaParam{JSONSchema: schemaParam}
  63. }
  64. //req.Model = oldModel
  65. req.Messages = newMessSlice
  66. return nil
  67. }
  68. func (me *MismatchClient) CallbackPrepare(params any) ([]byte, error) {
  69. taskData, ok := params.(*ent.CompapiAsynctask)
  70. if !ok {
  71. return nil, errors.New("invalid callback taskdata")
  72. }
  73. type OutResult struct {
  74. InternalID string `json:"internal_id"`
  75. ExternalID string `json:"external_id"`
  76. ChatID string `json:"chat_id"`
  77. EventType string `json:"event_type"`
  78. Content string `json:"content"`
  79. }
  80. res := OutResult{}
  81. res.InternalID = fmt.Sprintf("%d", taskData.ID)
  82. res.ExternalID = taskData.ResponseChatItemID
  83. res.EventType = taskData.EventType
  84. res.ChatID = taskData.ChatID
  85. var err error
  86. res.Content, err = NewChatResult(taskData.ResponseRaw).GetContentJsonStr()
  87. if err != nil {
  88. return nil, err
  89. }
  90. return WrapJSON(res, "", false)
  91. }