package service import ( "context" "encoding/json" "errors" "fmt" "prompts-core/model/dto" "prompts-core/model/entity" "strings" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" ) // 获取请求模型的提示词 func GetModelPrompt(ctx context.Context, Type int) string { return g.Cfg().MustGet(ctx, "modelPrompts.types."+gconv.String(Type), "").String() } // 获取构建提示词 func GetBuildPrompt(ctx context.Context, Type int) string { return g.Cfg().MustGet(ctx, "buildProject.types."+gconv.String(Type), "").String() } // buildInferenceRequest 构建返回请求 func buildInferenceRequest(ctx context.Context, req *dto.ComposeMessagesReq, chatModel *entity.AsynchModel, model *entity.AsynchModel, history []map[string]any) (map[string]any, error) { messages := []map[string]any{} switch req.BuildType { //构建提示词请求 case 1: //1. 构建系统提示词 messages = append(messages, map[string]any{ "role": "system", "content": promptBuild(ctx, req, model), }) // 2. 构建历史会话提示词 for _, msg := range history { role := gconv.String(msg["role"]) content := gconv.String(msg["content"]) if role != "user" && role != "assistant" { continue } messages = append(messages, map[string]any{ "role": role, "content": content, }) } // 3. 当前用户问题(原来的最后一条) messages = append(messages, map[string]any{ "role": "user", "content": buildUserPrompt(ctx, req, GetModelPrompt(ctx, model.ModelType)), }) //构建节点请求 case 2: messages = append(messages, map[string]any{ "role": "user", "content": NodeBuid(ctx, req), }) default: return nil, errors.New("不支持的构建类型") } // 构建请求体 return map[string]any{ "modelName": chatModel.ModelName, "bizName": "prompts-core", "callbackUrl": "/prompt/callback", "requestPayload": map[string]any{ "model": chatModel.ModelName, "messages": messages, "stream": false, }, }, nil } // ============================================ // 构建用户提示词 // ============================================ func buildUserPrompt(ctx context.Context, req *dto.ComposeMessagesReq, prompt string) string { payload := map[string]any{ "model": req.ModelName, //数据库提示信息 "promptInfo": prompt, // 系统表单 "form": req.Form, // 用户表单 "userForm": req.UserForm, //文件url "userFiles": req.UserFiles, //解读文件(只支持可读类型 如:xml,json,yaml) "userFilesText": FetchFileTexts(ctx, req.UserFiles), //skill 相关(根据传入的 skillName 获取 zip 内所有 md 文件拼接内容) "skills": SkillMdContent(ctx, req.SkillName), } return mustMarshal(payload) } // promptBuild 提示词构建 func promptBuild(ctx context.Context, req *dto.ComposeMessagesReq, model *entity.AsynchModel) string { // 1. 从配置文件读取提示词模板 promptTpl := GetBuildPrompt(ctx, req.BuildType) if promptTpl == "" { return "" } // 2. 构建字段映射说明 mappingBytes, _ := json.Marshal(model.RequestMapping) mappingStr := string(mappingBytes) var mapping map[string]string _ = json.Unmarshal(mappingBytes, &mapping) var fieldDesc strings.Builder for key, path := range mapping { fieldDesc.WriteString(fmt.Sprintf("- %s → %s\n", key, path)) } // 3. 拼接 UserForm 全文(必须完整阅读) var userFormContent strings.Builder for k, v := range req.UserForm { userFormContent.WriteString(fmt.Sprintf("%s=%v;", k, v)) } userFormFullText := strings.TrimSuffix(userFormContent.String(), ";") // 4. 双表单信息 formInfo := fmt.Sprintf(` 【系统表单(系统提示词/参数)】 %s 【用户表单全文(必须完整阅读,全部作为用户提示词来源)】 %s `, formToJSON(req.Form), userFormFullText) // 5. 格式化最终提示词(替换配置里的 %s) return fmt.Sprintf(promptTpl, mappingStr, fieldDesc.String(), formInfo) } // NodeBuid 节点构建 func NodeBuid(ctx context.Context, req *dto.ComposeMessagesReq) string { promptTpl := GetBuildPrompt(ctx, req.BuildType) if promptTpl == "" { return "" } formStr := formToJSON(req.Form) userFormStr := formToJSON(req.UserForm) return fmt.Sprintf(promptTpl, formStr, userFormStr) }