feat: 新增模型扩展映射与查询配置字段

This commit is contained in:
2026-05-23 18:08:09 +08:00
parent 855d5b9abe
commit 2548ffc7ac
11 changed files with 290 additions and 206 deletions

View File

@@ -12,9 +12,21 @@ import (
"prompts-core/model/dto"
"prompts-core/model/entity"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/util/gconv"
)
// UserPromptPayload 用户提示词请求体
type UserPromptPayload struct {
Model string `json:"model"`
PromptInfo string `json:"promptInfo"`
Form map[string]any `json:"form"`
UserForm any `json:"userForm"`
Consult []dto.ConsultItem `json:"consult"`
UserFilesText map[string]string `json:"userFilesText"`
Skills string `json:"skills"`
}
// buildInferenceRequest 构建推理请求
func buildInferenceRequest(ctx context.Context, req *dto.ComposeMessagesReq, chatModel *entity.AsynchModel, aiModel *entity.AsynchModel, history []map[string]any) (map[string]any, error) {
processedReq, totalBatches, err := ProcessUserFormBatches(ctx, req, aiModel)
@@ -117,7 +129,7 @@ func promptBuildWithRounds(ctx context.Context, req *dto.ComposeMessagesReq, mod
%s
技能名称: %s
用户文件: %v
`, req.ModelName, formInfo, req.SkillName, req.UserFiles)
`, req.ModelName, formInfo, req.SkillName, req.Consult)
return fmt.Sprintf(providerProtocol.SystemPromptTemplate,
req.ModelName, // %s 目标模型名称
@@ -148,19 +160,16 @@ func checkOverallContent(ir *PromptIR, model *entity.AsynchModel) bool {
// buildUserPrompt 构建用户提示词
func buildUserPrompt(ctx context.Context, req *dto.ComposeMessagesReq, prompt string) string {
userFormForPayload := prepareUserFormPayload(req.UserForm)
payload := map[string]any{
"model": req.ModelName,
"promptInfo": prompt,
"form": req.Form,
"userForm": userFormForPayload,
"userFiles": req.UserFiles,
"userFilesText": FetchFileTexts(ctx, req.UserFiles),
"skills": SkillMdContent(ctx, req.SkillName),
payload := UserPromptPayload{
Model: req.ModelName,
PromptInfo: prompt,
Form: req.Form,
UserForm: prepareUserFormPayload(req.UserForm),
Consult: req.Consult,
UserFilesText: ExtractFileTexts(ctx, req.Consult),
Skills: SkillMdContent(ctx, req.SkillName),
}
return util.MustMarshal(payload)
return gjson.New(payload).String()
}
// prepareUserFormPayload 准备用户表单载荷

View File

@@ -8,6 +8,7 @@ import (
"gitea.com/red-future/common/beans"
"gitea.com/red-future/common/utils"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"prompts-core/common/util"
@@ -122,7 +123,7 @@ func saveComposeTask(ctx context.Context, taskID string, req *dto.ComposeMessage
SkillName: req.SkillName,
BuildType: req.BuildType,
CallbackUrl: req.CallbackUrl,
RequestPayload: util.MustMarshal(req),
RequestPayload: util.MustMarshalToMap(req),
Status: public.ComposeStatusPending,
})
return err
@@ -182,13 +183,13 @@ func callInferenceModel(ctx context.Context, req *dto.ComposeMessagesReq, chatMo
}
// createDefaultResult 创建默认结果
func createDefaultResult(data map[string]any) *dto.MultiRoundResult {
func createDefaultResult(data map[string]any) map[string]any {
if data == nil {
data = make(map[string]any)
}
return &dto.MultiRoundResult{
TotalRounds: 1,
Rounds: []map[string]any{data},
return map[string]any{
"total_rounds": 1,
"rounds": []map[string]any{data},
}
}
@@ -196,14 +197,19 @@ func createDefaultResult(data map[string]any) *dto.MultiRoundResult {
func Callback(ctx context.Context, req *dto.CallbackReq) error {
g.Log().Infof(ctx, "[Callback][RECV] taskId=%s state=%d ossFile=%s fileType=%s textLen=%d",
req.TaskId, req.State, req.OssFile, req.FileType, len(req.Text))
// 查询任务
composeTask, err := dao.ComposeTask.Get(ctx, &entity.ComposeTask{
TaskId: req.TaskId,
})
if err != nil {
return fmt.Errorf("查询任务失败: %w", err)
}
if composeTask == nil {
return fmt.Errorf("任务不存在: %s", req.TaskId)
model, err := dao.Model.Get(ctx, &entity.AsynchModel{
SQLBaseDO: beans.SQLBaseDO{Creator: composeTask.Creator},
ModelName: composeTask.ModelName,
})
if err != nil {
return fmt.Errorf("查询模型失败: %w", err)
}
//处理失败
if req.State == 3 {
@@ -232,16 +238,18 @@ func Callback(ctx context.Context, req *dto.CallbackReq) error {
//处理成功
if req.State == 2 {
// 1. 根据 BuildType 解析结果
var messages any
var messages map[string]any
switch composeTask.BuildType {
case public.BuildTypePrompt: // 提示词构建解析
messages = parsePromptResult(req.Text)
messages = ParsePromptResult(req.Text)
case public.BuildTypeNode: // 节点构建解析
messages = parseNodeResult(req.Text)
messages = ParseNodeResult(req.Text)
default:
messages = req.Text
messages = gjson.New(req.Text).Map()
}
// 2. 更新数据库
// 2. 处理附加字段
messages = util.MergeConsult(composeTask.RequestPayload, messages, model.ExtendMapping)
// 3. 更新数据库
_, err = dao.ComposeTask.Update(ctx, &entity.ComposeTask{
TaskId: req.TaskId,
Status: public.ComposeStatusSuccess,
@@ -269,8 +277,8 @@ func Callback(ctx context.Context, req *dto.CallbackReq) error {
return err
}
// parsePromptResult 解析提示词构建结果
func parsePromptResult(raw string) *dto.MultiRoundResult {
// ParsePromptResult 解析提示词构建结果
func ParsePromptResult(raw string) map[string]any {
var wrapper map[string]any
if err := json.Unmarshal([]byte(raw), &wrapper); err != nil {
return createDefaultResult(map[string]any{"raw": raw})
@@ -283,17 +291,17 @@ func parsePromptResult(raw string) *dto.MultiRoundResult {
// 先尝试解析为数组
if roundsArray := tryParseAsMapArray(contentStr); roundsArray != nil {
return &dto.MultiRoundResult{
TotalRounds: len(roundsArray),
Rounds: roundsArray,
return map[string]any{
"total_rounds": len(roundsArray),
"rounds": roundsArray,
}
}
// 再尝试解析为单个对象
if singleRound := tryParseAsMap(contentStr); singleRound != nil {
return &dto.MultiRoundResult{
TotalRounds: 1,
Rounds: []map[string]any{singleRound},
return map[string]any{
"total_rounds": 1,
"rounds": []map[string]any{singleRound},
}
}
@@ -322,8 +330,8 @@ func tryParseAsMap(jsonStr string) map[string]any {
return obj
}
// parseNodeResult 解析节点构建结果
func parseNodeResult(raw string) *dto.MultiRoundResult {
// ParseNodeResult 解析节点构建结果
func ParseNodeResult(raw string) map[string]any {
var result map[string]any
if err := json.Unmarshal([]byte(raw), &result); err != nil {
return createDefaultResult(map[string]any{"raw": raw})
@@ -335,10 +343,9 @@ func parseNodeResult(raw string) *dto.MultiRoundResult {
result = inner
}
}
return &dto.MultiRoundResult{
TotalRounds: 1,
Rounds: []map[string]any{result},
return map[string]any{
"total_rounds": 1,
"rounds": []map[string]any{result},
}
}

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"io"
"net/http"
"prompts-core/model/dto"
"strings"
"time"
@@ -21,6 +22,17 @@ const (
bytesPerMB = 1024 * 1024
)
// ExtractFileTexts 从 ConsultItem 列表中提取文件内容
func ExtractFileTexts(ctx context.Context, consult []dto.ConsultItem) map[string]string {
urls := make([]string, 0, len(consult))
for _, item := range consult {
if item.Url != "" {
urls = append(urls, item.Url)
}
}
return FetchFileTexts(ctx, urls)
}
// FetchFileTexts 从 URL 列表获取文件内容,支持 zip 内文件
func FetchFileTexts(ctx context.Context, urls []string) map[string]string {
result := make(map[string]string)

View File

@@ -1,75 +0,0 @@
# Prompts-Core提示词核心服务
> 智能提示词构建与管理系统,支持多模态 AI 模型的提示词组装、会话管理和协议适配。
---
## 项目简介
**Prompts-Core** 是一个基于 Go 语言开发的提示词核心服务,作为 AI 应用层与模型网关之间的桥梁,负责将业务需求转换为标准化的模型请求。
### 核心价值
- **统一提示词管理**:集中化管理不同模型类型的提示词模板
- **智能会话维护**:基于 Redis + PostgreSQL 的双层会话存储
- **多协议适配**:支持 OpenAI、DeepSeek、Qwen、Gemini 等多种模型协议
- **文件处理能力**:自动提取文本文件和 ZIP 压缩包内容
- **技能系统集成**:支持从外部加载 Markdown 格式的技能描述
---
## 核心功能
### 1. 提示词构建引擎
#### 多模态支持
| 类型 | 说明 | 适用场景 |
|------|------|----------|
| Type 1 | 文字处理助手 | 文章撰写、文案优化、翻译等 |
| Type 2 | 图片处理助手 | 图像生成、风格迁移等 |
| Type 3 | 音频处理助手 | 语音合成、识别、降噪等 |
| Type 4 | 向量化处理助手 | 语义检索、知识索引等 |
| Type 5 | 全模态助手 | 跨模态转换、多模态融合等 |
#### 构建模式
- **BuildType 1提示词构建**:完整流程,包含系统提示词、历史会话、用户输入的智能组装
- **BuildType 2节点构建**:工作流路由决策,根据上下文选择节点 ID
#### 分批处理
当用户表单内容超出模型窗口限制时,自动按 Token 大小分批处理。
### 2. 会话管理系统
- **双层存储**Redis 缓存(最近 N 轮)+ PostgreSQL 持久化
- **自动管理**:最大轮数控制(默认 10 轮)、自动过期(默认 30 分钟)
### 3. 协议适配器
通过配置动态支持多种模型协议:
- 角色映射system/user/assistant → 目标协议角色
- 内容字段映射content → parts.text 等
- 消息顺序控制:灵活配置拼接顺序
- 请求模板渲染:支持占位符替换
### 4. 任务调度
- **异步流程**:创建网关任务 → 轮询等待 → 接收回调 → 返回结果
- **重试机制**:可配置最大重试次数(默认 3 次)
- **超时保护**:默认 300 秒超时
---
## 技术架构
### 技术栈
| 组件 | 版本 | 用途 |
|------|------|------|
| Go | 1.26.0 | 编程语言 |
| GoFrame | v2.10.0 | Web 框架 |
| PostgreSQL | - | 关系型数据库 |
| Redis | - | 缓存与会话存储 |
| Consul | - | 服务注册与发现 |
| Jaeger | - | 分布式链路追踪 |
### 架构图