123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- package chat
- import (
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "wechat-api/ent"
- "wechat-api/internal/svc"
- "wechat-api/internal/types"
- "wechat-api/internal/utils/compapi"
- "wechat-api/internal/utils/contextkey"
- "wechat-api/internal/utils/typekit"
- "github.com/zeromicro/go-zero/core/logx"
- )
- type baseLogicWorkflow interface {
- AppendAsyncRequest(apiKeyObj *ent.ApiKey, req *types.CompApiReq) error
- DoSyncRequest(apiKeyObj *ent.ApiKey, req *types.CompApiReq) (*types.CompOpenApiResp, error)
- AppendUsageDetailLog(authToken string, req *types.CompApiReq, resp *types.CompOpenApiResp) error
- AdjustRequest(req *types.CompApiReq, apiKeyObj *ent.ApiKey)
- }
- type ChatCompletionsLogic struct {
- logx.Logger
- ctx context.Context
- svcCtx *svc.ServiceContext
- }
- type FastgptChatLogic struct {
- ChatCompletionsLogic
- }
- type MismatchChatLogic struct {
- ChatCompletionsLogic
- }
- type IntentChatLogic struct {
- ChatCompletionsLogic
- }
- /*
- 扩展LogicChat工厂方法
- 返回根据不同EventType相关的扩展LogicChat的baseLogicWorkflow接口形式
- 每增加一个新的扩展LogicChat结构,需要在此函数中增加相应的创建语句
- */
- func (l *ChatCompletionsLogic) getLogicWorkflow(apiKeyObj *ent.ApiKey, req *types.CompApiReq) (baseLogicWorkflow, error) {
- var (
- err error
- wf baseLogicWorkflow
- )
- if apiKeyObj.Edges.Agent.Type != 2 {
- err = fmt.Errorf("api agent type not support(%d)", apiKeyObj.Edges.Agent.Type)
- } else if req.EventType == "mismatch" {
- wf = &MismatchChatLogic{ChatCompletionsLogic: *l}
- } else if req.EventType == "intent" {
- wf = &IntentChatLogic{ChatCompletionsLogic: *l}
- } else {
- wf = &FastgptChatLogic{ChatCompletionsLogic: *l}
- }
- return wf, err
- }
- func NewChatCompletionsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ChatCompletionsLogic {
- return &ChatCompletionsLogic{
- Logger: logx.WithContext(ctx),
- ctx: ctx,
- svcCtx: svcCtx}
- }
- func (l *ChatCompletionsLogic) ChatCompletions(req *types.CompApiReq) (asyncMode bool, resp *types.CompOpenApiResp, err error) {
- // todo: add your logic here and delete this line
- var (
- apiKeyObj *ent.ApiKey
- ok bool
- )
- asyncMode = false
- //从上下文中获取鉴权中间件埋下的apiAuthInfo
- apiKeyObj, ok = contextkey.AuthTokenInfoKey.GetValue(l.ctx)
- if !ok {
- return asyncMode, nil, errors.New("content get auth info err")
- }
- //根据请求产生相关的工作流接口集
- wf, err := l.getLogicWorkflow(apiKeyObj, req)
- if err != nil {
- return false, nil, err
- }
- //请求前临时观察相关参数
- //PreChatVars(req, apiKeyObj, wf)
- //微调部分请求参数
- wf.AdjustRequest(req, apiKeyObj)
- if isAsyncReqest(req) { //异步请求处理模式
- asyncMode = true
- err = wf.AppendAsyncRequest(apiKeyObj, req)
- } else { //同步请求处理模式
- resp, err = wf.DoSyncRequest(apiKeyObj, req)
- if err == nil && resp != nil && len(resp.Choices) > 0 {
- wf.AppendUsageDetailLog(apiKeyObj.Key, req, resp) //请求记录
- } else if resp != nil && len(resp.Choices) == 0 {
- err = errors.New("返回结果缺失,请检查访问地址及权限")
- }
- }
- return asyncMode, resp, err
- }
- func (l *ChatCompletionsLogic) AdjustRequest(req *types.CompApiReq, apiKeyObj *ent.ApiKey) {
- if len(req.EventType) == 0 {
- req.EventType = "fastgpt"
- }
- if len(req.Model) == 0 && len(apiKeyObj.Edges.Agent.Model) > 0 {
- req.Model = apiKeyObj.Edges.Agent.Model
- }
- //异步任务相关参数调整
- if req.IsBatch {
- //流模式暂时不支持异步模式
- //Callback格式非法则取消批量模式
- if req.Stream || !compapi.IsValidURL(&req.Callback, true) {
- req.IsBatch = false
- }
- }
- }
- func (l *ChatCompletionsLogic) DoSyncRequest(apiKeyObj *ent.ApiKey, req *types.CompApiReq) (*types.CompOpenApiResp, error) {
- resp, err := compapi.NewClient(l.ctx, compapi.WithApiBase(apiKeyObj.Edges.Agent.APIBase),
- compapi.WithApiKey(apiKeyObj.Edges.Agent.APIKey)).
- Chat(req)
- if err != nil {
- return nil, err
- }
- //以下临时测试case
- //humanSeeValidResult(l.ctx, req, resp)
- return resp, err
- }
- func (l *ChatCompletionsLogic) AppendAsyncRequest(apiKeyObj *ent.ApiKey, req *types.CompApiReq) error {
- rawReqBs, err := json.Marshal(*req)
- if err != nil {
- return err
- }
- rawReqStr := string(rawReqBs)
- res, err := l.svcCtx.DB.CompapiAsynctask.Create().
- SetNotNilAuthToken(&apiKeyObj.Key).
- SetNotNilOpenaiBase(&apiKeyObj.Edges.Agent.APIBase).
- SetNotNilOpenaiKey(&apiKeyObj.Edges.Agent.APIKey).
- SetNotNilOrganizationID(&apiKeyObj.OrganizationID).
- SetNotNilEventType(&req.EventType).
- SetNillableModel(&req.Model).
- SetNillableChatID(&req.ChatId).
- SetNillableResponseChatItemID(&req.ResponseChatItemId).
- SetNotNilRequestRaw(&rawReqStr).
- SetNotNilCallbackURL(&req.Callback).
- Save(l.ctx)
- if err == nil {
- logx.Infof("appendAsyncRequest succ,get id:%d", res.ID)
- }
- return err
- }
- func (l *ChatCompletionsLogic) AppendUsageDetailLog(authToken string, req *types.CompApiReq, resp *types.CompOpenApiResp) error {
- svcCtx := &compapi.ServiceContext{Config: l.svcCtx.Config, DB: l.svcCtx.DB,
- Rds: l.svcCtx.Rds}
- return compapi.AppendUsageDetailLog(l.ctx, svcCtx, authToken, req, resp)
- }
- func (l *FastgptChatLogic) AdjustRequest(req *types.CompApiReq, apiKeyObj *ent.ApiKey) {
- l.ChatCompletionsLogic.AdjustRequest(req, apiKeyObj) //先父类的参数调整
- if req.EventType != "fastgpt" {
- return
- }
- if len(req.Model) > 0 {
- if req.Variables == nil {
- req.Variables = make(map[string]string)
- }
- req.Variables["model"] = req.Model
- }
- if len(req.ChatId) > 0 && len(req.FastgptChatId) == 0 {
- req.FastgptChatId = req.ChatId
- } else if len(req.ChatId) == 0 && len(req.FastgptChatId) > 0 {
- req.ChatId = req.FastgptChatId
- }
- }
- func humanSeePreChatVars(req *types.CompApiReq, apiKeyObj *ent.ApiKey, wf baseLogicWorkflow) {
- fmt.Println("=========================================")
- fmt.Printf("In ChatCompletion Get Token Info:\nKey:'%s'\n", apiKeyObj.Key)
- fmt.Printf("Auth Token:'%s'\n", apiKeyObj.Key)
- fmt.Printf("ApiKey AgentID:%d\n", apiKeyObj.AgentID)
- fmt.Printf("ApiKey APIBase:'%s'\n", apiKeyObj.Edges.Agent.APIBase)
- fmt.Printf("ApiKey APIKey:'%s'\n", apiKeyObj.Edges.Agent.APIKey)
- fmt.Printf("ApiKey Type:%d\n", apiKeyObj.Edges.Agent.Type)
- fmt.Printf("ApiKey Model:'%s'\n", apiKeyObj.Edges.Agent.Model)
- fmt.Printf("EventType:'%s'\n", req.EventType)
- fmt.Printf("req.ChatId:'%s VS req.FastgptChatId:'%s'\n", req.ChatId, req.FastgptChatId)
- fmt.Println("=========================================")
- switch wf.(type) {
- case *MismatchChatLogic:
- fmt.Println("MismatchChatLogic Flow.....")
- case *IntentChatLogic:
- fmt.Println("IntentChatLogic Flow.....")
- case *FastgptChatLogic:
- fmt.Println("FastgptChatLogic Flow.....")
- default:
- fmt.Println("Other Flow.....")
- }
- }
- func humanSeeValidResult(ctx context.Context, req *types.CompApiReq, resp *types.CompOpenApiResp) {
- clientFace, err := compapi.NewClient(ctx).GetClientActFace(req.EventType)
- if err != nil {
- fmt.Println(err)
- return
- }
- taskData := ent.CompapiAsynctask{}
- taskData.ID = 1234
- taskData.ResponseChatItemID = req.ResponseChatItemId
- taskData.EventType = req.EventType
- taskData.ChatID = req.ChatId
- taskData.ResponseRaw, err = resp.ToString()
- if err != nil {
- fmt.Println(err)
- return
- }
- var bs []byte
- bs, err = clientFace.CallbackPrepare(&taskData)
- if err != nil {
- fmt.Println(err)
- }
- fmt.Printf("当前请求EventType:%s\n", req.EventType)
- fmt.Printf("当前请求MODEL:%s\n", req.Model)
- fmt.Println("client.CallbackPrepare结果[]byte版.........")
- fmt.Println(string(bs))
- nres := map[string]any{}
- err = json.Unmarshal(bs, &nres)
- if err != nil {
- fmt.Println(err)
- }
- fmt.Println("client.CallbackPrepare结果map[string]any版.........")
- fmt.Println(typekit.PrettyPrint(nres))
- config := compapi.ResponseFormatConfig{}
- if req.EventType == "mismatch" {
- clientInst := clientFace.(*compapi.MismatchClient)
- config = clientInst.ResponseFormatSetting(req)
- } else if req.EventType == "intent" {
- clientInst := clientFace.(*compapi.IntentClient)
- config = clientInst.ResponseFormatSetting(req)
- } else {
- return
- }
- err = compapi.NewChatResult(resp).ParseContentAs(&config.ResformatStruct)
- if err != nil {
- fmt.Println(err)
- }
- nres["content"] = config.ResformatStruct
- fmt.Println("client.CallbackPrepare结果ParseContentAs定制版.........")
- fmt.Println(typekit.PrettyPrint(nres))
- }
- func isAsyncReqest(req *types.CompApiReq) bool {
- return req.IsBatch
- }
|