refactor: 收口技能与专员目录定义
统一 skill 与 specialist 清单,移除旧的 office 执行包与下线对象,并补入 text_to_speech、customer_followup 等当前目录定义与种子数据。
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
│ ├── eai_agentplatform.db # SQLite(首启自动建)
|
||||
│ ├── backups/ # 定期备份(服务自动维护,见第 7 节)
|
||||
│ └── kb_data/ # 素材 + 提取缓存
|
||||
└── (前端静态资源由 Nginx 托管,见 ../docs/deploy.md)
|
||||
└── (前端静态资源由 Nginx 托管,见 ../docs/02_Architecture/部署文档.md)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// —— 积分规则(游戏化成长值,集中一处便于调整,见 docs/changelog.md 待确认项)——
|
||||
// —— 积分规则(游戏化成长值,集中一处便于调整,见 docs/01_System_Overall/变更日志.md 待确认项)——
|
||||
const (
|
||||
ptFirstCompany = 10 // 首次浏览公司介绍
|
||||
ptFirstProduct = 2 // 首次浏览单个产品
|
||||
|
||||
@@ -156,6 +156,8 @@ func RegisterRoutes(r *gin.Engine, cfg *config.Config) {
|
||||
r.POST("/api/batch/files", middleware.Auth(cfg), ExtractFromFiles)
|
||||
r.POST("/api/skills/office/execute", middleware.Auth(cfg), skillapi.ExecuteOfficeSkill)
|
||||
r.POST("/api/skills/office/ocr", middleware.Auth(cfg), skillapi.ExecuteOfficeSkillOCR)
|
||||
r.POST("/api/skills/office/tts", middleware.Auth(cfg), skillapi.ExecuteOfficeSkillTTS)
|
||||
r.GET("/api/tts/audio/:filename", middleware.Auth(cfg), skillapi.ServeTTSAudio)
|
||||
r.POST("/api/chat/message", middleware.Auth(cfg), HandleChatMessage)
|
||||
|
||||
// 语音工具
|
||||
|
||||
@@ -199,7 +199,7 @@ func ExecuteOfficeSkillOCR(c *gin.Context) {
|
||||
TaskID: task.ID,
|
||||
SpecialistKey: task.SpecialistKey,
|
||||
ActionKey: "ocr-understanding",
|
||||
ActionTitle: "OCR / 图文理解",
|
||||
ActionTitle: "图片/扫描件智能识别",
|
||||
ActionType: "ocr",
|
||||
Status: "done",
|
||||
InputJSON: string(inputJSON),
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
package skillapi
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"eai_agentplatform/backend/internal/config"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
specialistruntime "eai_agentplatform/backend/internal/specialists/runtime"
|
||||
"eai_agentplatform/backend/internal/store"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// ttsDefaultVoice 默认中文女声(edge-tts 自带音色)。
|
||||
const ttsDefaultVoice = "zh-CN-XiaoxiaoNeural"
|
||||
|
||||
// ttsAudioDir 存放合成 MP3 的目录,与公众号配图一致放在数据库同级的 tts_audio 下。
|
||||
func ttsAudioDir() string {
|
||||
cfg := config.Load()
|
||||
return filepath.Join(filepath.Dir(cfg.DBPath), "tts_audio")
|
||||
}
|
||||
|
||||
func defaultTTSText(text string) string {
|
||||
text = strings.TrimSpace(text)
|
||||
if text == "" {
|
||||
return "这是一个文字转语音的示例。"
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
// ExecuteOfficeSkillTTS POST /api/skills/office/tts —— 文字转语音。
|
||||
// body: { "task_id": <任务ID>, "text": "要朗读的文字", "voice": "音色(可空)", "rate": "语速(可空, 如 +0% / -10%)" }
|
||||
func ExecuteOfficeSkillTTS(c *gin.Context) {
|
||||
user := middleware.CurrentUser(c)
|
||||
if user == nil {
|
||||
web.Fail(c, web.NewAuthError("未登录"))
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
TaskID uint `json:"task_id"`
|
||||
Text string `json:"text"`
|
||||
Voice string `json:"voice"`
|
||||
Rate string `json:"rate"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
web.Fail(c, web.NewBadRequest("请求参数错误"))
|
||||
return
|
||||
}
|
||||
if req.TaskID == 0 {
|
||||
web.Fail(c, web.NewBadRequest("task_id 必填"))
|
||||
return
|
||||
}
|
||||
|
||||
text := defaultTTSText(req.Text)
|
||||
voice := strings.TrimSpace(req.Voice)
|
||||
if voice == "" {
|
||||
voice = ttsDefaultVoice
|
||||
}
|
||||
rate := strings.TrimSpace(req.Rate)
|
||||
|
||||
task, ok := loadMyOwnedTask(c, user, req.TaskID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
dir := ttsAudioDir()
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
web.Fail(c, web.NewBadRequest("无法创建音频目录"))
|
||||
return
|
||||
}
|
||||
sum := sha1.Sum([]byte(text + "|" + voice))
|
||||
filename := fmt.Sprintf("task_%d_%s_%x.mp3", task.ID, now.Format("20060102-150405"), sum[:6])
|
||||
audioPath := filepath.Join(dir, filename)
|
||||
|
||||
args := []string{"-m", "edge_tts", "--text", text, "--voice", voice, "--write-media", audioPath}
|
||||
if rate != "" {
|
||||
args = append(args, "--rate", rate)
|
||||
}
|
||||
cmd := exec.Command("python3", args...)
|
||||
var stderr strings.Builder
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
web.Fail(c, web.NewBadRequest("语音合成失败:"+firstNonEmpty(strings.TrimSpace(stderr.String()), err.Error())))
|
||||
return
|
||||
}
|
||||
if _, err := os.Stat(audioPath); err != nil {
|
||||
web.Fail(c, web.NewBadRequest("语音合成失败:未生成音频文件"))
|
||||
return
|
||||
}
|
||||
audioURL := "/api/tts/audio/" + filename
|
||||
|
||||
inputJSON, _ := json.Marshal(gin.H{"text": text, "voice": voice, "rate": rate})
|
||||
outputJSON, _ := json.Marshal(gin.H{
|
||||
"summary": "已将文本合成为语音,可在线播放或下载。",
|
||||
"text": text,
|
||||
"voice": voice,
|
||||
"audio_url": audioURL,
|
||||
})
|
||||
logsJSON, _ := json.Marshal([]string{
|
||||
"接收文字转语音请求",
|
||||
fmt.Sprintf("调用本地 TTS 引擎(voice=%s)", voice),
|
||||
"已生成 MP3 音频",
|
||||
})
|
||||
artifactPayloadJSON, _ := json.Marshal(gin.H{
|
||||
"text": text,
|
||||
"voice": voice,
|
||||
"audio_url": audioURL,
|
||||
"format": "mp3",
|
||||
})
|
||||
sourceRefsJSON, _ := json.Marshal([]string{"本地 edge-tts"})
|
||||
|
||||
var run model.TaskRun
|
||||
var artifact model.TaskArtifact
|
||||
err := store.DB.Transaction(func(tx *gorm.DB) error {
|
||||
run = model.TaskRun{
|
||||
TaskID: task.ID,
|
||||
SpecialistKey: task.SpecialistKey,
|
||||
ActionKey: "text-to-speech",
|
||||
ActionTitle: "文字转语音",
|
||||
ActionType: "audio",
|
||||
Status: "done",
|
||||
InputJSON: string(inputJSON),
|
||||
OutputJSON: string(outputJSON),
|
||||
LogsJSON: string(logsJSON),
|
||||
StartedAt: now,
|
||||
FinishedAt: &now,
|
||||
}
|
||||
if err := tx.Create(&run).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
artifact = model.TaskArtifact{
|
||||
TaskID: task.ID,
|
||||
SpecialistKey: task.SpecialistKey,
|
||||
Title: fmt.Sprintf("%s - 语音合成结果", task.Title),
|
||||
ArtifactType: "audio",
|
||||
Status: specialistruntime.ArtifactStatusDraft,
|
||||
ContentText: text,
|
||||
ContentJSON: string(artifactPayloadJSON),
|
||||
SourceRefsJSON: string(sourceRefsJSON),
|
||||
CreatedByRunID: &run.ID,
|
||||
}
|
||||
if err := tx.Create(&artifact).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
task.CurrentRunID = &run.ID
|
||||
task.CurrentResult = "已将文本合成为语音并生成 MP3。"
|
||||
task.Status = specialistruntime.TaskStatusDraft
|
||||
task.LastTriggeredAt = &now
|
||||
return tx.Save(&task).Error
|
||||
})
|
||||
if err != nil {
|
||||
web.Fail(c, web.NewBadRequest("保存结果失败:"+err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
freshTask, _ := reloadTask(task.ID)
|
||||
web.OK(c, gin.H{
|
||||
"audio_url": audioURL,
|
||||
"text": text,
|
||||
"voice": voice,
|
||||
"rate": rate,
|
||||
"run": run,
|
||||
"artifact": artifact,
|
||||
"task": freshTask,
|
||||
})
|
||||
}
|
||||
|
||||
// ServeTTSAudio GET /api/tts/audio/:filename —— 提供生成的 MP3 音频文件。
|
||||
func ServeTTSAudio(c *gin.Context) {
|
||||
filename := filepath.Base(strings.TrimSpace(c.Param("filename")))
|
||||
if filename == "." || filename == "" {
|
||||
web.Fail(c, web.NewNotFoundError("音频不存在"))
|
||||
return
|
||||
}
|
||||
fullPath := filepath.Join(ttsAudioDir(), filename)
|
||||
if _, err := os.Stat(fullPath); err != nil {
|
||||
web.Fail(c, web.NewNotFoundError("音频不存在"))
|
||||
return
|
||||
}
|
||||
c.File(fullPath)
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
contractreview "eai_agentplatform/backend/internal/skills/packages/contract_review"
|
||||
copyproofreading "eai_agentplatform/backend/internal/skills/packages/copy_proofreading"
|
||||
documenttranslate "eai_agentplatform/backend/internal/skills/packages/document_translate"
|
||||
emaildrafting "eai_agentplatform/backend/internal/skills/packages/email_drafting"
|
||||
interviewsummary "eai_agentplatform/backend/internal/skills/packages/interview_summary"
|
||||
longformwriting "eai_agentplatform/backend/internal/skills/packages/longform_writing"
|
||||
meetingminutes "eai_agentplatform/backend/internal/skills/packages/meeting_minutes"
|
||||
@@ -16,13 +15,10 @@ import (
|
||||
policyrewrite "eai_agentplatform/backend/internal/skills/packages/policy_rewrite"
|
||||
pptgeneration "eai_agentplatform/backend/internal/skills/packages/ppt_generation"
|
||||
progressreport "eai_agentplatform/backend/internal/skills/packages/progress_report"
|
||||
projectplanning "eai_agentplatform/backend/internal/skills/packages/project_planning"
|
||||
proposalsummary "eai_agentplatform/backend/internal/skills/packages/proposal_summary"
|
||||
reportgeneration "eai_agentplatform/backend/internal/skills/packages/report_generation"
|
||||
smartassistant "eai_agentplatform/backend/internal/skills/packages/smart_assistant"
|
||||
surveysummary "eai_agentplatform/backend/internal/skills/packages/survey_summary"
|
||||
tablecleanup "eai_agentplatform/backend/internal/skills/packages/table_cleanup"
|
||||
texttoolkit "eai_agentplatform/backend/internal/skills/packages/text_toolkit"
|
||||
texttospeech "eai_agentplatform/backend/internal/skills/packages/text_to_speech"
|
||||
)
|
||||
|
||||
var builtinRegistry = NewRegistry(
|
||||
@@ -36,18 +32,14 @@ var builtinRegistry = NewRegistry(
|
||||
pptgeneration.Manifest,
|
||||
mindmap.Manifest,
|
||||
longformwriting.Manifest,
|
||||
texttoolkit.Manifest,
|
||||
ocrunderstanding.Manifest,
|
||||
meetingminutes.Manifest,
|
||||
projectplanning.Manifest,
|
||||
emaildrafting.Manifest,
|
||||
tablecleanup.Manifest,
|
||||
proposalsummary.Manifest,
|
||||
progressreport.Manifest,
|
||||
contractbrief.Manifest,
|
||||
interviewsummary.Manifest,
|
||||
policyrewrite.Manifest,
|
||||
surveysummary.Manifest,
|
||||
texttospeech.Manifest,
|
||||
)
|
||||
|
||||
func BuiltinRegistry() *Registry {
|
||||
|
||||
@@ -11,8 +11,10 @@ type SkillDefinition struct {
|
||||
EAILogicCode string `gorm:"column:eailogic_code;size:32;default:'';index" json:"eailogic_code"`
|
||||
Description string `gorm:"type:text" json:"description"`
|
||||
ObjectKind string `gorm:"column:object_kind;size:32;not null;default:skill;index" json:"object_kind"`
|
||||
Source string `gorm:"size:32;not null;default:eai;index" json:"source"`
|
||||
ObjectEntryRoute string `gorm:"column:object_entry_route;size:128;default:''" json:"object_entry_route"`
|
||||
Source string `gorm:"size:32;not null;default:eai;index" json:"source"`
|
||||
ObjectEntryRoute string `gorm:"column:object_entry_route;size:128;default:''" json:"object_entry_route"` // 业务对象进入入口(D26 口径)
|
||||
Color string `gorm:"size:16;default:''" json:"color"` // 展示主色(面向用户展示层,唯一的真值在后端)
|
||||
InteractionCardJSON string `gorm:"column:interaction_card_json;type:text" json:"interaction_card_json"` // 交互卡对象(JSON,snake_case 与专员一致)
|
||||
// 这里**有意不写** `default:true`。带上它,GORM 在 Create 时会跳过布尔零值字段
|
||||
// (false 被当成「没填」),改由库默认值 true 生效 —— 于是对象显式设的 false
|
||||
// 被持久层改写成 true,创建接口永远设不出「不暴露给用户」的技能。
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "audio-transcribe",
|
||||
Label: "语音转写",
|
||||
Label: "会议音频分析(转写)",
|
||||
OwnedDefinitionKeys: []string{"skill.audio-transcribe.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.audio-transcribe"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "batch-extract",
|
||||
Label: "批量提取",
|
||||
Label: "批量字段提取 → Excel",
|
||||
OwnedDefinitionKeys: []string{"skill.batch-extract.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.batch-extract"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "contract-brief",
|
||||
Label: "合同要点提炼",
|
||||
Label: "合同批量审查与提取(提取)",
|
||||
OwnedDefinitionKeys: []string{"skill.contract-brief.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.contract-brief"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "contract-brief",
|
||||
Label: "合同要点提炼",
|
||||
Label: "合同批量审查与提取(提取)",
|
||||
PlanTitle: "合同要点提炼流程",
|
||||
PlanSteps: []string{"识别合同结构", "提炼核心条款", "标记风险事项", "输出摘要版本"},
|
||||
ResultTitle: "合同要点摘要",
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "contract-review",
|
||||
Label: "合同审查",
|
||||
Label: "合同批量审查与提取(审查)",
|
||||
OwnedDefinitionKeys: []string{"skill.contract-review.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.contract-review"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package emaildrafting
|
||||
|
||||
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "email-drafting",
|
||||
Label: "邮件起草",
|
||||
OwnedDefinitionKeys: []string{"skill.email-drafting.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.email-drafting"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package emaildrafting
|
||||
|
||||
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "email-drafting",
|
||||
Label: "邮件起草",
|
||||
PlanTitle: "邮件起草流程",
|
||||
PlanSteps: []string{"识别沟通目的", "整理背景与重点", "生成正式邮件", "补充简短跟进版本"},
|
||||
ResultTitle: "邮件草稿",
|
||||
Summary: "已生成一版可直接发送的邮件正文,并补了简短跟进版本和要点摘要。",
|
||||
Highlights: []string{"适合汇报、催办、确认和通知", "兼顾正式语气与清晰表达", "默认沉淀长邮件和短消息版本"},
|
||||
ActionType: "communication",
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "interview-summary",
|
||||
Label: "访谈整理",
|
||||
Label: "招聘简历助手",
|
||||
OwnedDefinitionKeys: []string{"skill.interview-summary.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.interview-summary"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "interview-summary",
|
||||
Label: "访谈整理",
|
||||
Label: "招聘简历助手",
|
||||
PlanTitle: "访谈整理流程",
|
||||
PlanSteps: []string{"归并访谈内容", "提炼主题观点", "总结关键洞察", "输出整理版本"},
|
||||
ResultTitle: "访谈整理稿",
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "longform-writing",
|
||||
Label: "长文创作",
|
||||
Label: "公文辅助写作(长文)",
|
||||
OwnedDefinitionKeys: []string{"skill.longform-writing.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.longform-writing"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "longform-writing",
|
||||
Label: "长文创作",
|
||||
Label: "公文辅助写作(长文)",
|
||||
PlanTitle: "长文创作流程",
|
||||
PlanSteps: []string{"明确文体与受众", "规划章节大纲", "生成正文骨架", "整理摘要与交付稿"},
|
||||
ResultTitle: "长文草稿",
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "meeting-minutes",
|
||||
Label: "会议纪要",
|
||||
Label: "会议音频分析(纪要)",
|
||||
OwnedDefinitionKeys: []string{"skill.meeting-minutes.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.meeting-minutes"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "meeting-minutes",
|
||||
Label: "会议纪要",
|
||||
Label: "会议音频分析(纪要)",
|
||||
PlanTitle: "会议纪要整理流程",
|
||||
PlanSteps: []string{"识别会议主题", "提炼关键结论", "整理行动项", "输出同步版本"},
|
||||
ResultTitle: "会议纪要草稿",
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "mind-map",
|
||||
Label: "思维导图",
|
||||
Label: "会议音频分析(思维导图)",
|
||||
OwnedDefinitionKeys: []string{"skill.mind-map.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.mind-map"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "mind-map",
|
||||
Label: "思维导图",
|
||||
Label: "会议音频分析(思维导图)",
|
||||
PlanTitle: "思维导图生成流程",
|
||||
PlanSteps: []string{"识别主题主线", "拆分一级分支", "补齐关键节点", "整理导图源结构"},
|
||||
ResultTitle: "导图结构草案",
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "ocr-understanding",
|
||||
Label: "OCR / 图文理解",
|
||||
Label: "图片/扫描件智能识别",
|
||||
OwnedDefinitionKeys: []string{"skill.ocr-understanding.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.ocr-understanding"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "ocr-understanding",
|
||||
Label: "OCR / 图文理解",
|
||||
Label: "图片/扫描件智能识别",
|
||||
PlanTitle: "图文理解流程",
|
||||
PlanSteps: []string{"识别图像内容", "抽取文字与字段", "整理结构摘要", "输出可复用结果"},
|
||||
ResultTitle: "识别结果摘要",
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "policy-rewrite",
|
||||
Label: "制度改写",
|
||||
Label: "公文辅助写作(制度)",
|
||||
OwnedDefinitionKeys: []string{"skill.policy-rewrite.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.policy-rewrite"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "policy-rewrite",
|
||||
Label: "制度改写",
|
||||
Label: "公文辅助写作(制度)",
|
||||
PlanTitle: "制度改写流程",
|
||||
PlanSteps: []string{"识别制度目标", "统一结构口径", "重写正式正文", "补充修订说明"},
|
||||
ResultTitle: "制度改写稿",
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "ppt-generation",
|
||||
Label: "PPT 生成",
|
||||
Label: "一键生成 PPT",
|
||||
OwnedDefinitionKeys: []string{"skill.ppt-generation.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.ppt-generation"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "ppt-generation",
|
||||
Label: "PPT 生成",
|
||||
Label: "一键生成 PPT",
|
||||
PlanTitle: "PPT 生成流程",
|
||||
PlanSteps: []string{"确认汇报目标", "规划页面结构", "提炼每页要点", "整理讲稿备注"},
|
||||
ResultTitle: "演示文稿骨架",
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "progress-report",
|
||||
Label: "周报 / 日报",
|
||||
Label: "一键周报",
|
||||
OwnedDefinitionKeys: []string{"skill.progress-report.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.progress-report"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "progress-report",
|
||||
Label: "周报 / 日报",
|
||||
Label: "一键周报",
|
||||
PlanTitle: "进展汇报流程",
|
||||
PlanSteps: []string{"归并本期工作", "提炼关键进展", "整理风险事项", "输出汇报版本"},
|
||||
ResultTitle: "进展汇报草稿",
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package projectplanning
|
||||
|
||||
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "project-planning",
|
||||
Label: "项目规划",
|
||||
OwnedDefinitionKeys: []string{"skill.project-planning.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.project-planning"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package projectplanning
|
||||
|
||||
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "project-planning",
|
||||
Label: "项目规划",
|
||||
PlanTitle: "项目规划流程",
|
||||
PlanSteps: []string{"明确目标边界", "拆解阶段路径", "整理里程碑", "补齐风险与依赖"},
|
||||
ResultTitle: "项目规划草案",
|
||||
Summary: "已把目标拆成阶段计划、里程碑和风险项,方便直接进入执行或评审。",
|
||||
Highlights: []string{"适合启动、排期和推进对齐", "默认沉淀阶段计划与风险清单", "结果适合继续流转到任务治理"},
|
||||
ActionType: "plan",
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package proposalsummary
|
||||
|
||||
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "proposal-summary",
|
||||
Label: "方案摘要",
|
||||
OwnedDefinitionKeys: []string{"skill.proposal-summary.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.proposal-summary"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package proposalsummary
|
||||
|
||||
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "proposal-summary",
|
||||
Label: "方案摘要",
|
||||
PlanTitle: "方案摘要流程",
|
||||
PlanSteps: []string{"识别方案目标", "提炼核心亮点", "压缩实施路径", "输出摘要版本"},
|
||||
ResultTitle: "方案摘要稿",
|
||||
Summary: "已提炼出方案核心结论、价值亮点和实施建议,适合快速汇报或同步。",
|
||||
Highlights: []string{"适合方案汇报和管理层预读", "自动压缩价值点与实施路径", "默认沉淀摘要正文和亮点清单"},
|
||||
ActionType: "summary",
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "report-generation",
|
||||
Label: "报告生成",
|
||||
Label: "一键生成报告",
|
||||
OwnedDefinitionKeys: []string{"skill.report-generation.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.report-generation"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "smart-assistant",
|
||||
Label: "通用助手",
|
||||
Label: "智能助手",
|
||||
OwnedDefinitionKeys: []string{"skill.smart-assistant.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.smart-assistant"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package surveysummary
|
||||
|
||||
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "survey-summary",
|
||||
Label: "表单问卷汇总",
|
||||
OwnedDefinitionKeys: []string{"skill.survey-summary.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.survey-summary"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package surveysummary
|
||||
|
||||
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "survey-summary",
|
||||
Label: "表单问卷汇总",
|
||||
PlanTitle: "问卷汇总流程",
|
||||
PlanSteps: []string{"归并表单结果", "提炼重点发现", "整理问题与建议", "输出汇总版本"},
|
||||
ResultTitle: "问卷汇总稿",
|
||||
Summary: "已整理出表单结果汇总、重点发现和改进建议,方便直接同步给负责人。",
|
||||
Highlights: []string{"适合反馈表、报名表、调查问卷", "自动压缩重点发现和改进建议", "默认沉淀汇总报告和行动建议"},
|
||||
ActionType: "report",
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "table-cleanup",
|
||||
Label: "表格整理",
|
||||
Label: "知识库表格视图",
|
||||
OwnedDefinitionKeys: []string{"skill.table-cleanup.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.table-cleanup"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "table-cleanup",
|
||||
Label: "表格整理",
|
||||
Label: "知识库表格视图",
|
||||
PlanTitle: "表格整理流程",
|
||||
PlanSteps: []string{"识别字段结构", "清洗原始数据", "整理表格内容", "补充字段说明"},
|
||||
ResultTitle: "表格整理结果",
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package texttospeech
|
||||
|
||||
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "text-to-speech",
|
||||
Label: "文字转语音",
|
||||
OwnedDefinitionKeys: []string{"skill.text-to-speech.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.text-to-speech"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package texttoolkit
|
||||
|
||||
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
|
||||
|
||||
var Manifest = skillcontracts.Manifest{
|
||||
Key: "text-toolkit",
|
||||
Label: "文本处理",
|
||||
OwnedDefinitionKeys: []string{"skill.text-toolkit.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.skill.text-toolkit"},
|
||||
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package texttoolkit
|
||||
|
||||
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
|
||||
|
||||
var OfficeRuntime = officecontracts.Runtime{
|
||||
Key: "text-toolkit",
|
||||
Label: "文本处理",
|
||||
PlanTitle: "文本处理流程",
|
||||
PlanSteps: []string{"识别清洗目标", "去除噪音符号", "统一格式与标点", "输出可复用文本"},
|
||||
ResultTitle: "清洗后文本",
|
||||
Summary: "已完成文本清洗、格式整理和统计,可直接复制或下载结果。",
|
||||
Highlights: []string{"去 Markdown 噪音", "输出文本统计", "适合高频复制到 Word 和 IM"},
|
||||
ActionType: "text",
|
||||
}
|
||||
-106
@@ -98,112 +98,6 @@ func BuildMeetingMinutesArtifacts(inputText string) []gin.H {
|
||||
}
|
||||
}
|
||||
|
||||
func BuildEmailDraftingArtifacts(inputText string) []gin.H {
|
||||
fields, bodyText := parseOfficeFields(inputText, map[string][]string{
|
||||
"recipient": {"收件人", "对象", "recipient", "to"},
|
||||
"cc": {"抄送", "抄送人", "cc"},
|
||||
"topic": {"主题", "标题", "topic", "subject"},
|
||||
"purpose": {"目的", "意图", "purpose"},
|
||||
"action": {"希望对方", "需要对方", "action"},
|
||||
"deadline": {"时间", "截止时间", "deadline"},
|
||||
"tone": {"语气", "风格", "tone", "style"},
|
||||
})
|
||||
topic := firstNonEmpty(fields["topic"], pickOfficeTopic(firstNonEmpty(bodyText, inputText), "邮件主题"))
|
||||
recipient := firstNonEmpty(fields["recipient"], "各位")
|
||||
ccList := splitSimpleList(fields["cc"])
|
||||
purpose := firstNonEmpty(fields["purpose"], "同步背景和当前进展")
|
||||
action := firstNonEmpty(fields["action"], "请协助确认并继续推进")
|
||||
deadline := firstNonEmpty(fields["deadline"], "请尽快反馈")
|
||||
tone := firstNonEmpty(fields["tone"], "正式、明确、礼貌")
|
||||
points := extractOfficePoints(firstNonEmpty(bodyText, inputText), []string{"交代背景和当前情况", "说明希望对方配合或确认的事项", "给出时间点和下一步动作", "保持礼貌但结论清楚"})
|
||||
subjectVariants := buildEmailSubjectVariants(topic, purpose)
|
||||
subject := subjectVariants[0]
|
||||
emailContent := strings.TrimSpace(strings.Join([]string{
|
||||
"主题:" + subject,
|
||||
"收件人:" + recipient,
|
||||
"抄送:" + firstNonEmpty(strings.Join(ccList, "、"), "无"),
|
||||
"",
|
||||
recipient + "好,",
|
||||
"",
|
||||
purpose + "。" + firstNonEmpty(pointAt(points, 0), "这边同步一下当前事项的背景和进展。"),
|
||||
action + "。" + firstNonEmpty(pointAt(points, 1), "目前需要大家协助确认相关事项。"),
|
||||
deadline + "。" + firstNonEmpty(pointAt(points, 2), "如无问题,请按约定时间继续推进。"),
|
||||
"",
|
||||
"语气建议:" + tone + "。如有问题,请直接回复沟通。",
|
||||
"",
|
||||
"谢谢。",
|
||||
}, "\n"))
|
||||
shortContent := strings.TrimSpace(strings.Join([]string{
|
||||
"【" + topic + "】",
|
||||
firstNonEmpty(pointAt(points, 1), "请协助确认相关事项。"),
|
||||
firstNonEmpty(pointAt(points, 2), "如无问题请按时推进。"),
|
||||
}, "\n"))
|
||||
briefContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# 邮件要点",
|
||||
"",
|
||||
"- 主题:" + subject,
|
||||
"- " + firstNonEmpty(pointAt(points, 0), "交代背景和当前情况"),
|
||||
"- " + firstNonEmpty(pointAt(points, 1), "说明希望对方配合或确认的事项"),
|
||||
"- " + firstNonEmpty(pointAt(points, 2), "给出时间点和下一步动作"),
|
||||
"- " + firstNonEmpty(pointAt(points, 3), "保持礼貌但结论清楚"),
|
||||
}, "\n"))
|
||||
subjectLines := []string{
|
||||
"# 主题与抄送建议",
|
||||
"",
|
||||
"- 收件人:" + recipient,
|
||||
"- 抄送建议:" + firstNonEmpty(strings.Join(ccList, "、"), "建议抄送直属负责人 / 相关协同方"),
|
||||
"",
|
||||
"## 可选主题",
|
||||
}
|
||||
for index, item := range subjectVariants {
|
||||
subjectLines = append(subjectLines, fmt.Sprintf("%d. %s", index+1, item))
|
||||
}
|
||||
subjectContent := strings.TrimSpace(strings.Join(subjectLines, "\n"))
|
||||
slug := officeSlug(topic, "email-drafting")
|
||||
return []gin.H{
|
||||
{
|
||||
"key": "email",
|
||||
"title": "正式邮件",
|
||||
"description": "可直接复制到邮箱发送的完整版本。",
|
||||
"kind": "text",
|
||||
"fileFormat": "txt",
|
||||
"downloadName": slug + ".txt",
|
||||
"mimeType": "text/plain;charset=utf-8",
|
||||
"content": emailContent,
|
||||
},
|
||||
{
|
||||
"key": "short-followup",
|
||||
"title": "简短跟进版",
|
||||
"description": "适合发到 IM 或群里的短消息版本。",
|
||||
"kind": "text",
|
||||
"fileFormat": "txt",
|
||||
"downloadName": slug + "-short.txt",
|
||||
"mimeType": "text/plain;charset=utf-8",
|
||||
"content": shortContent,
|
||||
},
|
||||
{
|
||||
"key": "brief",
|
||||
"title": "邮件要点",
|
||||
"description": "方便审批或复核邮件口径的要点版。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-brief.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": briefContent,
|
||||
},
|
||||
{
|
||||
"key": "subject-variants",
|
||||
"title": "主题与抄送建议",
|
||||
"description": "提供多版主题候选和抄送建议。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-subject.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": subjectContent,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func BuildProgressReportArtifacts(inputText string) []gin.H {
|
||||
topic := pickOfficeTopic(inputText, "进展汇报")
|
||||
points := extractOfficePoints(inputText, []string{"本期完成的关键工作", "当前风险和阻塞项", "需要协同支持的事项", "下一步计划"})
|
||||
|
||||
@@ -114,109 +114,6 @@ func BuildMindMapArtifacts(inputText string) []gin.H {
|
||||
}
|
||||
}
|
||||
|
||||
func BuildProjectPlanningArtifacts(inputText string) []gin.H {
|
||||
fields, bodyText := parseOfficeFields(inputText, map[string][]string{
|
||||
"topic": {"项目", "项目名称", "主题", "topic"},
|
||||
"deadline": {"时间要求", "截止时间", "deadline"},
|
||||
"owner": {"负责人", "owner"},
|
||||
"goal": {"目标", "goal"},
|
||||
"start": {"开始时间", "启动时间", "start"},
|
||||
})
|
||||
topic := firstNonEmpty(fields["topic"], pickOfficeTopic(firstNonEmpty(bodyText, inputText), "项目规划"))
|
||||
deadline := firstNonEmpty(fields["deadline"], "待确认")
|
||||
owner := firstNonEmpty(fields["owner"], "待指定")
|
||||
goal := firstNonEmpty(fields["goal"], "先明确目标、阶段、依赖和协同方式")
|
||||
start := firstNonEmpty(fields["start"], "尽快启动")
|
||||
points := extractOfficePoints(firstNonEmpty(bodyText, inputText), []string{"明确目标、范围和成功标准", "梳理关键里程碑与交付节点", "安排执行分工与协同节奏", "识别风险与外部依赖"})
|
||||
stageRows := buildProjectStageRows(points, owner, deadline)
|
||||
planContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# " + topic,
|
||||
"",
|
||||
"## 项目目标",
|
||||
fmt.Sprintf("围绕“%s”整理一版可执行的项目规划,先确保目标、阶段和依赖都清楚。", topic),
|
||||
"- 负责人:" + owner,
|
||||
"- 启动时间:" + start,
|
||||
"- 时间要求:" + deadline,
|
||||
"- 总体目标:" + goal,
|
||||
"",
|
||||
"## 阶段安排",
|
||||
"### 阶段 1:启动与对齐",
|
||||
"- " + firstNonEmpty(pointAt(points, 0), "明确目标和边界"),
|
||||
"### 阶段 2:执行与推进",
|
||||
"- " + firstNonEmpty(pointAt(points, 1), "推进关键里程碑和核心交付"),
|
||||
"### 阶段 3:验收与收口",
|
||||
"- " + firstNonEmpty(pointAt(points, 2), "完成验收、复盘和沉淀"),
|
||||
}, "\n"))
|
||||
milestoneContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# 里程碑清单",
|
||||
"",
|
||||
"1. M1:" + firstNonEmpty(pointAt(points, 0), "明确目标和边界"),
|
||||
"2. M2:" + firstNonEmpty(pointAt(points, 1), "推进关键里程碑和核心交付"),
|
||||
"3. M3:" + firstNonEmpty(pointAt(points, 2), "完成验收、复盘和沉淀"),
|
||||
"4. M4:" + firstNonEmpty(pointAt(points, 3), "确认依赖和外部配合事项"),
|
||||
}, "\n"))
|
||||
riskContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# 风险与依赖",
|
||||
"",
|
||||
"- 风险 1:" + firstNonEmpty(pointAt(points, 3), "关键依赖尚未完全明确"),
|
||||
"- 风险 2:跨团队协同节奏可能影响排期",
|
||||
"- 建议:将关键依赖提前前置到周会或启动会确认",
|
||||
}, "\n"))
|
||||
scheduleLines := []string{
|
||||
"# 阶段排期表",
|
||||
"",
|
||||
"| 阶段 | 时间窗 | 负责人 | 目标 | 交付物 |",
|
||||
"| --- | --- | --- | --- | --- |",
|
||||
}
|
||||
for _, item := range stageRows {
|
||||
scheduleLines = append(scheduleLines, fmt.Sprintf("| %s | %s | %s | %s | %s |", asString(item["stage"]), asString(item["window"]), asString(item["owner"]), asString(item["goal"]), asString(item["output"])))
|
||||
}
|
||||
scheduleContent := strings.TrimSpace(strings.Join(scheduleLines, "\n"))
|
||||
slug := officeSlug(topic, "project-planning")
|
||||
return []gin.H{
|
||||
{
|
||||
"key": "project-plan",
|
||||
"title": "项目计划",
|
||||
"description": "适合直接评审和继续细化的主计划。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + ".md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": planContent,
|
||||
},
|
||||
{
|
||||
"key": "milestones",
|
||||
"title": "里程碑清单",
|
||||
"description": "关键节点和交付节奏的简洁版列表。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-milestones.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": milestoneContent,
|
||||
},
|
||||
{
|
||||
"key": "risks",
|
||||
"title": "风险清单",
|
||||
"description": "项目推进前需要确认的风险与依赖。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-risks.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": riskContent,
|
||||
},
|
||||
{
|
||||
"key": "schedule",
|
||||
"title": "阶段排期表",
|
||||
"description": "更接近甘特视角的阶段、时间窗和交付物表。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-schedule.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": scheduleContent,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func BuildTableCleanupArtifacts(inputText string) []gin.H {
|
||||
fields, bodyText := parseOfficeFields(inputText, map[string][]string{
|
||||
"topic": {"主题", "标题", "topic", "title"},
|
||||
|
||||
@@ -58,115 +58,6 @@ func BuildLongformArtifacts(inputText string) []gin.H {
|
||||
}
|
||||
}
|
||||
|
||||
func BuildTextToolkitArtifacts(inputText string) []gin.H {
|
||||
cleaned := stripMarkdownText(inputText)
|
||||
stats := strings.Join([]string{
|
||||
"# 文本统计",
|
||||
"",
|
||||
fmt.Sprintf("- 字符数:%d", len([]rune(cleaned))),
|
||||
fmt.Sprintf("- 行数:%d", len(splitMeaningfulLines(cleaned))),
|
||||
fmt.Sprintf("- 原始长度:%d", len([]rune(strings.TrimSpace(inputText)))),
|
||||
"",
|
||||
"## 处理说明",
|
||||
"- 已移除常见 Markdown 标记",
|
||||
"- 已压缩多余空行",
|
||||
"- 已保留正文可读性",
|
||||
}, "\n")
|
||||
slug := officeSlug(pickOfficeTopic(inputText, "cleaned-text"), "text-toolkit")
|
||||
return []gin.H{
|
||||
{
|
||||
"key": "cleaned",
|
||||
"title": "清洗后文本",
|
||||
"description": "适合直接粘贴到文档或聊天工具。",
|
||||
"kind": "text",
|
||||
"fileFormat": "txt",
|
||||
"downloadName": slug + ".txt",
|
||||
"mimeType": "text/plain;charset=utf-8",
|
||||
"content": cleaned,
|
||||
},
|
||||
{
|
||||
"key": "stats",
|
||||
"title": "文本统计",
|
||||
"description": "记录本次清洗和统计结果。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-stats.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": stats,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func BuildProposalSummaryArtifacts(inputText string) []gin.H {
|
||||
topic := pickOfficeTopic(inputText, "方案摘要")
|
||||
points := extractOfficePoints(inputText, []string{"明确方案目标和解决的问题", "提炼核心价值与收益", "压缩关键实施路径", "明确需要决策的事项"})
|
||||
summaryContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# " + topic,
|
||||
"",
|
||||
"## 核心结论",
|
||||
fmt.Sprintf("%s 已压缩为适合汇报和快速预读的摘要版本,重点保留目标、价值点和实施建议。", topic),
|
||||
"",
|
||||
"## 关键亮点",
|
||||
"- " + firstNonEmpty(pointAt(points, 0), "明确方案目标和解决的问题"),
|
||||
"- " + firstNonEmpty(pointAt(points, 1), "提炼核心价值与收益"),
|
||||
"- " + firstNonEmpty(pointAt(points, 2), "压缩关键实施路径"),
|
||||
"- " + firstNonEmpty(pointAt(points, 3), "明确需要决策的事项"),
|
||||
"",
|
||||
"## 实施建议",
|
||||
"- 建议先确认资源与排期",
|
||||
"- 建议围绕高优先级场景先落一版 MVP",
|
||||
"- 建议同步关键负责人做进一步评审",
|
||||
}, "\n"))
|
||||
highlightsContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# 亮点清单",
|
||||
"",
|
||||
"1. " + firstNonEmpty(pointAt(points, 0), "明确方案目标和解决的问题"),
|
||||
"2. " + firstNonEmpty(pointAt(points, 1), "提炼核心价值与收益"),
|
||||
"3. " + firstNonEmpty(pointAt(points, 2), "压缩关键实施路径"),
|
||||
"4. " + firstNonEmpty(pointAt(points, 3), "明确需要决策的事项"),
|
||||
}, "\n"))
|
||||
briefingContent := strings.TrimSpace(strings.Join([]string{
|
||||
"【" + topic + " 摘要】",
|
||||
"1. " + firstNonEmpty(pointAt(points, 0), "明确方案目标和解决的问题"),
|
||||
"2. " + firstNonEmpty(pointAt(points, 1), "提炼核心价值与收益"),
|
||||
"3. " + firstNonEmpty(pointAt(points, 2), "压缩关键实施路径"),
|
||||
"建议按上述结论进入下一步决策或评审。",
|
||||
}, "\n"))
|
||||
slug := officeSlug(topic, "proposal-summary")
|
||||
return []gin.H{
|
||||
{
|
||||
"key": "summary",
|
||||
"title": "方案摘要",
|
||||
"description": "适合直接汇报或继续细化的主摘要。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + ".md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": summaryContent,
|
||||
},
|
||||
{
|
||||
"key": "highlights",
|
||||
"title": "亮点清单",
|
||||
"description": "压缩提炼后的价值点列表。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-highlights.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": highlightsContent,
|
||||
},
|
||||
{
|
||||
"key": "briefing",
|
||||
"title": "汇报短版",
|
||||
"description": "适合发群或口头汇报前快速同步的短摘要。",
|
||||
"kind": "text",
|
||||
"fileFormat": "txt",
|
||||
"downloadName": slug + "-briefing.txt",
|
||||
"mimeType": "text/plain;charset=utf-8",
|
||||
"content": briefingContent,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func BuildContractBriefArtifacts(inputText string) []gin.H {
|
||||
fields, bodyText := parseOfficeFields(inputText, map[string][]string{
|
||||
"topic": {"合同名称", "主题", "topic"},
|
||||
@@ -422,67 +313,3 @@ func BuildPolicyRewriteArtifacts(inputText string) []gin.H {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func BuildSurveySummaryArtifacts(inputText string) []gin.H {
|
||||
topic := pickOfficeTopic(inputText, "问卷汇总")
|
||||
points := extractOfficePoints(inputText, []string{"参与者的主要反馈方向", "高频问题或不满意点", "值得保留的积极反馈", "后续改进建议"})
|
||||
reportContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# " + topic,
|
||||
"",
|
||||
"## 汇总结论",
|
||||
"- " + firstNonEmpty(pointAt(points, 0), "参与者的主要反馈方向"),
|
||||
"- " + firstNonEmpty(pointAt(points, 1), "高频问题或不满意点"),
|
||||
"- " + firstNonEmpty(pointAt(points, 2), "值得保留的积极反馈"),
|
||||
"- " + firstNonEmpty(pointAt(points, 3), "后续改进建议"),
|
||||
"",
|
||||
"## 汇总说明",
|
||||
"已把表单和问卷结果压缩成便于阅读和决策的汇总结论。",
|
||||
}, "\n"))
|
||||
findingsContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# 重点发现",
|
||||
"",
|
||||
"- 发现 1:" + firstNonEmpty(pointAt(points, 0), "参与者主要关注体验和执行效果"),
|
||||
"- 发现 2:" + firstNonEmpty(pointAt(points, 1), "部分问题集中在流程或内容安排上"),
|
||||
"- 发现 3:" + firstNonEmpty(pointAt(points, 2), "已有若干积极反馈值得继续保留"),
|
||||
}, "\n"))
|
||||
actionsContent := strings.TrimSpace(strings.Join([]string{
|
||||
"# 改进建议",
|
||||
"",
|
||||
"- [ ] " + firstNonEmpty(pointAt(points, 3), "根据汇总结果制定下一步改进动作"),
|
||||
"- [ ] 对高频问题安排专项优化",
|
||||
"- [ ] 向负责人同步汇总结论和优先级建议",
|
||||
}, "\n"))
|
||||
slug := officeSlug(topic, "survey-summary")
|
||||
return []gin.H{
|
||||
{
|
||||
"key": "report",
|
||||
"title": "汇总报告",
|
||||
"description": "适合直接汇报或继续细化的主报告。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + ".md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": reportContent,
|
||||
},
|
||||
{
|
||||
"key": "findings",
|
||||
"title": "重点发现",
|
||||
"description": "从表单结果中提炼出的关键发现。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-findings.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": findingsContent,
|
||||
},
|
||||
{
|
||||
"key": "actions",
|
||||
"title": "改进建议",
|
||||
"description": "建议后续继续推进的改进行动。",
|
||||
"kind": "text",
|
||||
"fileFormat": "md",
|
||||
"downloadName": slug + "-actions.md",
|
||||
"mimeType": "text/markdown;charset=utf-8",
|
||||
"content": actionsContent,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package office
|
||||
|
||||
import (
|
||||
contractbrief "eai_agentplatform/backend/internal/skills/packages/contract_brief"
|
||||
emaildrafting "eai_agentplatform/backend/internal/skills/packages/email_drafting"
|
||||
interviewsummary "eai_agentplatform/backend/internal/skills/packages/interview_summary"
|
||||
longformwriting "eai_agentplatform/backend/internal/skills/packages/longform_writing"
|
||||
meetingminutes "eai_agentplatform/backend/internal/skills/packages/meeting_minutes"
|
||||
@@ -11,11 +10,7 @@ import (
|
||||
policyrewrite "eai_agentplatform/backend/internal/skills/packages/policy_rewrite"
|
||||
pptgeneration "eai_agentplatform/backend/internal/skills/packages/ppt_generation"
|
||||
progressreport "eai_agentplatform/backend/internal/skills/packages/progress_report"
|
||||
projectplanning "eai_agentplatform/backend/internal/skills/packages/project_planning"
|
||||
proposalsummary "eai_agentplatform/backend/internal/skills/packages/proposal_summary"
|
||||
surveysummary "eai_agentplatform/backend/internal/skills/packages/survey_summary"
|
||||
tablecleanup "eai_agentplatform/backend/internal/skills/packages/table_cleanup"
|
||||
texttoolkit "eai_agentplatform/backend/internal/skills/packages/text_toolkit"
|
||||
officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -29,18 +24,13 @@ var builtinRegistry = NewRegistry(
|
||||
withBuild(pptgeneration.OfficeRuntime, BuildPPTArtifacts),
|
||||
withBuild(mindmap.OfficeRuntime, BuildMindMapArtifacts),
|
||||
withBuild(longformwriting.OfficeRuntime, BuildLongformArtifacts),
|
||||
withBuild(texttoolkit.OfficeRuntime, BuildTextToolkitArtifacts),
|
||||
ocrunderstanding.OfficeRuntime,
|
||||
withBuild(meetingminutes.OfficeRuntime, BuildMeetingMinutesArtifacts),
|
||||
withBuild(projectplanning.OfficeRuntime, BuildProjectPlanningArtifacts),
|
||||
withBuild(emaildrafting.OfficeRuntime, BuildEmailDraftingArtifacts),
|
||||
withBuild(tablecleanup.OfficeRuntime, BuildTableCleanupArtifacts),
|
||||
withBuild(proposalsummary.OfficeRuntime, BuildProposalSummaryArtifacts),
|
||||
withBuild(progressreport.OfficeRuntime, BuildProgressReportArtifacts),
|
||||
withBuild(contractbrief.OfficeRuntime, BuildContractBriefArtifacts),
|
||||
withBuild(interviewsummary.OfficeRuntime, BuildInterviewSummaryArtifacts),
|
||||
withBuild(policyrewrite.OfficeRuntime, BuildPolicyRewriteArtifacts),
|
||||
withBuild(surveysummary.OfficeRuntime, BuildSurveySummaryArtifacts),
|
||||
)
|
||||
|
||||
func BuiltinRegistry() *Registry {
|
||||
|
||||
@@ -71,26 +71,6 @@ func parseMeetingActions(text string, fallback []string) []gin.H {
|
||||
return out
|
||||
}
|
||||
|
||||
func buildEmailSubjectVariants(topic, purpose string) []string {
|
||||
base := firstNonEmpty(topic, "事项")
|
||||
context := strings.TrimSpace(purpose)
|
||||
items := []string{
|
||||
base + " - 请协助确认",
|
||||
base + " - 需要回复",
|
||||
base + " - 进展同步",
|
||||
}
|
||||
if context != "" {
|
||||
runes := []rune(context)
|
||||
if len(runes) > 12 {
|
||||
context = string(runes[:12])
|
||||
}
|
||||
items = append(items, base+" - "+context)
|
||||
} else {
|
||||
items = append(items, base+" - 待处理提醒")
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func formatMeetingActionLine(actions []gin.H, index int) string {
|
||||
if index < 0 || index >= len(actions) {
|
||||
return fmt.Sprintf("%d. 待补充行动项", index+1)
|
||||
@@ -149,29 +129,3 @@ func buildContractRedlineItems(points, focusKeywords []string) []gin.H {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func stripMarkdownText(text string) string {
|
||||
text = strings.ReplaceAll(text, "\r", "\n")
|
||||
blockCode := regexp.MustCompile("```[\\s\\S]*?```")
|
||||
text = blockCode.ReplaceAllStringFunc(text, func(value string) string {
|
||||
return strings.TrimSpace(strings.ReplaceAll(value, "```", ""))
|
||||
})
|
||||
replacers := []struct {
|
||||
pattern string
|
||||
value string
|
||||
}{
|
||||
{"`([^`]+)`", "$1"},
|
||||
{"^#{1,6}\\s+", ""},
|
||||
{"^\\s*[-*+]\\s+", ""},
|
||||
{"^\\s*\\d+[.)]\\s+", ""},
|
||||
{"\\*\\*(.*?)\\*\\*", "$1"},
|
||||
{"\\*(.*?)\\*", "$1"},
|
||||
{"!\\[[^\\]]*\\]\\([^)]*\\)", ""},
|
||||
{"\\[([^\\]]+)\\]\\(([^)]*)\\)", "$1"},
|
||||
}
|
||||
for _, item := range replacers {
|
||||
text = regexp.MustCompile(item.pattern).ReplaceAllString(text, item.value)
|
||||
}
|
||||
text = regexp.MustCompile(`\n{3,}`).ReplaceAllString(text, "\n\n")
|
||||
return strings.TrimSpace(text)
|
||||
}
|
||||
|
||||
@@ -217,31 +217,6 @@ func splitSimpleList(value string) []string {
|
||||
return out
|
||||
}
|
||||
|
||||
func buildProjectStageRows(points []string, owner, deadline string) []gin.H {
|
||||
labels := []string{"阶段 1", "阶段 2", "阶段 3", "阶段 4"}
|
||||
windows := []string{"第 1 周", "第 2 周", "第 3 周", firstNonEmpty(deadline, "收口前")}
|
||||
rows := make([]gin.H, 0, len(labels))
|
||||
for index, label := range labels {
|
||||
output := "收口结论"
|
||||
switch index {
|
||||
case 0:
|
||||
output = "目标确认"
|
||||
case 1:
|
||||
output = "阶段交付"
|
||||
case 2:
|
||||
output = "验收材料"
|
||||
}
|
||||
rows = append(rows, gin.H{
|
||||
"stage": label,
|
||||
"window": windows[index],
|
||||
"goal": firstNonEmpty(pointAt(points, index), "补充"+label+"目标"),
|
||||
"owner": firstNonEmpty(owner, "待指定"),
|
||||
"output": output,
|
||||
})
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func repeatString(value string, count int) []string {
|
||||
items := make([]string, 0, count)
|
||||
for index := 0; index < count; index++ {
|
||||
|
||||
@@ -2,31 +2,17 @@ package specialistcore
|
||||
|
||||
import (
|
||||
contractreview "eai_agentplatform/backend/internal/specialists/packages/contract_review"
|
||||
generalassistant "eai_agentplatform/backend/internal/specialists/packages/general_assistant"
|
||||
hremailsorter "eai_agentplatform/backend/internal/specialists/packages/hr_email_sorter"
|
||||
knowledgeoperations "eai_agentplatform/backend/internal/specialists/packages/knowledge_operations"
|
||||
logisticsfulfillment "eai_agentplatform/backend/internal/specialists/packages/logistics_fulfillment"
|
||||
presentationbriefing "eai_agentplatform/backend/internal/specialists/packages/presentation_briefing"
|
||||
processcoordination "eai_agentplatform/backend/internal/specialists/packages/process_coordination"
|
||||
reportgeneration "eai_agentplatform/backend/internal/specialists/packages/report_generation"
|
||||
customerfollowup "eai_agentplatform/backend/internal/specialists/packages/customer_followup"
|
||||
resumeprocessor "eai_agentplatform/backend/internal/specialists/packages/resume_processor"
|
||||
solutionproposal "eai_agentplatform/backend/internal/specialists/packages/solution_proposal"
|
||||
trainingdelivery "eai_agentplatform/backend/internal/specialists/packages/training_delivery"
|
||||
wechatofficialaccount "eai_agentplatform/backend/internal/specialists/packages/wechat_official_account"
|
||||
)
|
||||
|
||||
var builtinRegistry = NewRegistry(
|
||||
generalassistant.Manifest,
|
||||
trainingdelivery.Manifest,
|
||||
knowledgeoperations.Manifest,
|
||||
processcoordination.Manifest,
|
||||
reportgeneration.Manifest,
|
||||
wechatofficialaccount.Manifest,
|
||||
contractreview.Manifest,
|
||||
solutionproposal.Manifest,
|
||||
presentationbriefing.Manifest,
|
||||
logisticsfulfillment.Manifest,
|
||||
hremailsorter.Manifest,
|
||||
customerfollowup.Manifest,
|
||||
resumeprocessor.Manifest,
|
||||
)
|
||||
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package customerfollowup
|
||||
|
||||
import specialistcontracts "eai_agentplatform/backend/internal/specialists/contracts"
|
||||
|
||||
var Manifest = specialistcontracts.Manifest{
|
||||
Key: "customer-followup",
|
||||
Label: "客户跟进专员",
|
||||
RuleFileMarkdown: `# 客户跟进专员
|
||||
|
||||
## 你是谁
|
||||
你负责客户资料整理到会议预约这一段的推进:资料归档、意向分级、联系建议、预约跟进、状态回写。
|
||||
你面对的是销售、售前或客户成功同学,他们要的是「哪些客户该先跟、怎么跟、何时约」。
|
||||
|
||||
## 你怎么推进
|
||||
1. 先给总览:客户一共多少个,分别处于新线索、已联系、待预约、已预约哪个阶段。
|
||||
2. 逐个客户整理「客户名称 / 关键背景 / 当前意向 / 最近动作 / 下一步建议」。
|
||||
3. 对高意向客户优先给出联系建议:推荐触达方式、首轮话术、会议目标和建议时间。
|
||||
4. 跟进结果要回写,明确哪些客户已联系、哪些待补资料、哪些需要升级处理。
|
||||
|
||||
## 输出要求
|
||||
- 客户资料要保留来源,标明来自 CRM、表格、邮件还是人工补录。
|
||||
- 意向判断要写依据,不要只给一个高、中、低标签。
|
||||
- 联系建议尽量可直接发出,避免只写空泛建议。
|
||||
|
||||
## 边界
|
||||
- 不伪造客户承诺,不代替用户直接发送外部联系。
|
||||
- 拿不到客户历史记录时如实说,不要按经验补全。`,
|
||||
AllowedSkills: []string{"progress-report", "report-generation"},
|
||||
OwnedDefinitionKeys: []string{"specialist.customer-followup.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.specialist.customer-followup"},
|
||||
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package hremailsorter
|
||||
|
||||
import specialistcontracts "eai_agentplatform/backend/internal/specialists/contracts"
|
||||
|
||||
var Manifest = specialistcontracts.Manifest{
|
||||
Key: "hr-email-sorter",
|
||||
Label: "HR 邮件整理专员",
|
||||
RuleFileMarkdown: `# HR 邮件整理专员
|
||||
|
||||
## 你是谁
|
||||
你负责把 HR 邮箱里的简历邮件理清楚:简历邮件识别、候选人信息抽取、去重归类。
|
||||
你面对的是要快速筛出有效候选人的招聘同学。
|
||||
|
||||
## 你怎么推进
|
||||
1. 先分类:简历投递 / 面试安排 / 其他(通知、广告、内部邮件)。
|
||||
2. 简历邮件逐封抽字段:姓名、联系方式、应聘岗位、年限、学历、附件有没有。
|
||||
3. 去重:同一候选人多次投递的合并,列出重复来源。
|
||||
4. 输出归类清单,按岗位分组。
|
||||
|
||||
## 输出要求
|
||||
- 字段缺失写「未提供」,不要用工整的占位内容填充。
|
||||
- 附件解析失败的单列出来,标明原因。
|
||||
|
||||
## 边界
|
||||
- 候选人个人信息只出现在整理结果里,不外传、不写入其他文档。
|
||||
- 不做录用判断——那是简历处理专员和用人部门的事。`,
|
||||
AllowedSkills: []string{"email-drafting", "batch-extract", "table-cleanup", "ocr-understanding"},
|
||||
OwnedDefinitionKeys: []string{"specialist.hr-email-sorter.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.specialist.hr-email-sorter"},
|
||||
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package logisticsfulfillment
|
||||
|
||||
import specialistcontracts "eai_agentplatform/backend/internal/specialists/contracts"
|
||||
|
||||
var Manifest = specialistcontracts.Manifest{
|
||||
Key: "logistics-fulfillment",
|
||||
Label: "履约跟单专员",
|
||||
RuleFileMarkdown: `# 履约跟单专员
|
||||
|
||||
## 你是谁
|
||||
你负责订单履约的过程跟踪:节点跟踪、异常识别、催办升级、状态回写。
|
||||
你面对的是盯着一批单子的人,他要的是「哪几单要出事了」。
|
||||
|
||||
## 你怎么推进
|
||||
1. 先给总览:在途多少单、正常多少、异常多少。
|
||||
2. 异常单逐条给出「单号 / 卡在哪个节点 / 卡了多久 / 原因 / 建议动作」。
|
||||
3. 按节点时效判断该催谁,给出可直接发送的催办话术。
|
||||
4. 收尾确认状态已回写,没回写的列出来。
|
||||
|
||||
## 输出要求
|
||||
- 时间口径统一(统一时区、标明统计截止时点)。
|
||||
- 异常分级:影响交付日期的算高优先级,只影响体感的往下降。
|
||||
|
||||
## 边界
|
||||
- 只读订单与物流数据,不代替用户改单、取消单、承诺新的交期。
|
||||
- 拿不到物流节点信息时如实说,不要按经验推测位置。`,
|
||||
AllowedSkills: []string{"progress-report", "table-cleanup", "email-drafting"},
|
||||
OwnedDefinitionKeys: []string{"specialist.logistics-fulfillment.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.specialist.logistics-fulfillment"},
|
||||
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@ var Manifest = specialistcontracts.Manifest{
|
||||
- 不编造数据、案例、客户反馈。
|
||||
- 不把未确认方案写成既定事实。
|
||||
- 视觉美化可以建议,但当前重点是结构与表达,不承诺设计成品。`,
|
||||
AllowedSkills: []string{"ppt-generation", "proposal-summary", "mind-map", "progress-report"},
|
||||
AllowedSkills: []string{"ppt-generation", "mind-map", "progress-report"},
|
||||
OwnedDefinitionKeys: []string{"specialist.presentation-briefing.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.specialist.presentation-briefing"},
|
||||
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ var Manifest = specialistcontracts.Manifest{
|
||||
## 边界
|
||||
- 只起草催办与升级建议,不代替用户对外发送。
|
||||
- 不评价同事的工作态度,只陈述事项状态与时间事实。`,
|
||||
AllowedSkills: []string{"progress-report", "project-planning", "email-drafting"},
|
||||
AllowedSkills: []string{"progress-report"},
|
||||
OwnedDefinitionKeys: []string{"specialist.process-coordination.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.specialist.process-coordination"},
|
||||
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
+10
-8
@@ -4,20 +4,22 @@ import specialistcontracts "eai_agentplatform/backend/internal/specialists/contr
|
||||
|
||||
var Manifest = specialistcontracts.Manifest{
|
||||
Key: "resume-processor",
|
||||
Label: "简历处理专员",
|
||||
RuleFileMarkdown: `# 简历处理专员
|
||||
Label: "招聘筛选专员",
|
||||
RuleFileMarkdown: `# 招聘筛选专员
|
||||
|
||||
## 你是谁
|
||||
你负责简历筛选到面试安排:筛选、评分排序、跟进标记、面试安排。
|
||||
你面对的是用人部门,他们要的是一份能直接拿去约面试的名单。
|
||||
你负责从招聘入口整理到候选人筛选的闭环:邮件归档、候选人抽取、评分排序、跟进标记、面试安排。
|
||||
你面对的是招聘同学和用人部门,他们要的是一份能直接拿去推进的候选人清单。
|
||||
|
||||
## 你怎么推进
|
||||
1. 先确认岗位要求与硬性门槛(学历、年限、必备技能),门槛项单独标。
|
||||
2. 逐份评分:按岗位要求逐项对照,给出总分与排序,并写明「为什么排这个位置」。
|
||||
3. 标出不确定项:信息缺失、表述含糊、需要电话确认的点。
|
||||
4. 给面试安排建议:分批、每批人选、建议面试重点。
|
||||
1. 先整理招聘入口:把招聘邮件、附件和候选人资料归到统一清单,重复投递先合并。
|
||||
2. 再确认岗位要求与硬性门槛(学历、年限、必备技能),门槛项单独标。
|
||||
3. 逐份评分:按岗位要求逐项对照,给出总分与排序,并写明「为什么排这个位置」。
|
||||
4. 标出不确定项:信息缺失、表述含糊、需要电话确认的点。
|
||||
5. 给面试安排建议:分批、每批人选、建议面试重点。
|
||||
|
||||
## 输出要求
|
||||
- 候选人入口整理要保留来源,标明来自哪封邮件、哪个附件或哪次投递。
|
||||
- 评分要能追溯到岗位要求的具体条目,不要只给一个分数。
|
||||
- 排序理由写事实(做过什么、做了多久),不写「感觉不错」。
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ var Manifest = specialistcontracts.Manifest{
|
||||
## 边界
|
||||
- 不承诺工期、不承诺价格——这两项由销售与交付确认。
|
||||
- 不替研发承诺功能,不贬低竞品。`,
|
||||
AllowedSkills: []string{"proposal-summary", "ppt-generation", "project-planning", "mind-map"},
|
||||
AllowedSkills: []string{"ppt-generation", "mind-map"},
|
||||
OwnedDefinitionKeys: []string{"specialist.solution-proposal.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.specialist.solution-proposal"},
|
||||
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
package trainingdelivery
|
||||
|
||||
import specialistcontracts "eai_agentplatform/backend/internal/specialists/contracts"
|
||||
|
||||
var Manifest = specialistcontracts.Manifest{
|
||||
Key: "training-delivery",
|
||||
Label: "培训交付专员",
|
||||
RuleFileMarkdown: `# 培训交付专员
|
||||
|
||||
## 你是谁
|
||||
你负责新人销售训练营的交付闭环:班级状态、考试预警、复盘归档、交付清单。
|
||||
你面对的是培训负责人,他关心的是「哪个班要出问题了」,不是过程数据。
|
||||
|
||||
## 你怎么推进
|
||||
1. 先给结论:本期班级整体交付状态(正常 / 有风险 / 已阻塞)+ 一句话原因。
|
||||
2. 再给异常清单:按风险高低排,每条写清「谁 / 什么信号 / 建议动作」。
|
||||
3. 最后给交付清单:本期还缺哪些材料、谁补、什么时候要。
|
||||
|
||||
## 输出要求
|
||||
- 数字要带口径(哪个班、哪场考试、统计截止到什么时候)。
|
||||
- 预警必须给出可执行的下一步,不要只说「需关注」。
|
||||
|
||||
## 边界
|
||||
- 只读班级资料与考试结果,不替学员报名、不替教练打分。
|
||||
- 涉及具体学员的评价,只陈述记录里的事实,不做主观评判。`,
|
||||
AllowedSkills: []string{"progress-report", "report-generation", "ppt-generation", "meeting-minutes"},
|
||||
OwnedDefinitionKeys: []string{"specialist.training-delivery.definition"},
|
||||
OwnedCatalogEntries: []string{"catalog.specialist.training-delivery"},
|
||||
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
|
||||
}
|
||||
+1
-1
@@ -573,7 +573,7 @@ func ExportOfficialAccountDocument(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if task.SpecialistKey != officialAccountSpecialistKey {
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号助手"))
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号专员"))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -186,7 +186,7 @@ func CreateOfficialAccountTask(c *gin.Context) {
|
||||
// 任务挂在已下线的专员上,历史记录仍要解释得通。
|
||||
specialist, found := specialistDAO.GetByKey(officialAccountSpecialistKey)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("公众号助手尚未配置"))
|
||||
web.Fail(c, web.NewNotFoundError("公众号专员尚未配置"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ func GetOfficialAccountWorkflow(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if task.SpecialistKey != officialAccountSpecialistKey {
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号助手"))
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号专员"))
|
||||
return
|
||||
}
|
||||
respondOfficialAccountWorkflow(c, task)
|
||||
@@ -243,7 +243,7 @@ func UpdateOfficialAccountTask(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if task.SpecialistKey != officialAccountSpecialistKey {
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号助手"))
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号专员"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@ func ExecuteOfficialAccountWorkflowStep(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if task.SpecialistKey != officialAccountSpecialistKey {
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号助手"))
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号专员"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -524,7 +524,7 @@ func RegenerateOfficialAccountImage(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if task.SpecialistKey != officialAccountSpecialistKey {
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号助手"))
|
||||
web.Fail(c, web.NewNotFoundError("当前事项不属于公众号专员"))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ import specialistcontracts "eai_agentplatform/backend/internal/specialists/contr
|
||||
|
||||
var Manifest = specialistcontracts.Manifest{
|
||||
Key: "wechat-official-account",
|
||||
Label: "公众号助手",
|
||||
RuleFileMarkdown: `# 公众号助手
|
||||
Label: "公众号专员",
|
||||
RuleFileMarkdown: `# 公众号专员
|
||||
|
||||
## 你是谁
|
||||
你负责公众号内容从选题到成稿:热点选题、标题、提纲、正文。
|
||||
|
||||
@@ -38,30 +38,6 @@ func SeedSpecialists(db *gorm.DB) error {
|
||||
State: "system",
|
||||
SortOrder: 0,
|
||||
},
|
||||
{
|
||||
Key: "training-delivery",
|
||||
Label: "培训交付专员",
|
||||
Tier: "generic",
|
||||
SpecialistMode: "dw",
|
||||
ObjectEntryRoute: "/apps/training-delivery",
|
||||
Summary: "新人销售训练营第 3 周",
|
||||
WorkStatus: "5 个进行中",
|
||||
RiskLabel: "0 个异常",
|
||||
Color: "#67c23a",
|
||||
Stage: "交付归档",
|
||||
Progress: 84,
|
||||
MarketTag: "已安装",
|
||||
Version: "v1.1",
|
||||
ConnectorScope: "连接课程系统 / 知识库 / 考试模块",
|
||||
PermissionScope: "班级资料读取、考试结果读取、交付包生成",
|
||||
ResourceBindings: "课程系统、考试模块、知识库、交付模板中心",
|
||||
InfoSources: "班级排期、学员成绩、互动记录、教练点评",
|
||||
BaseSkills: "班级日报、考试预警、复盘归档、交付清单生成",
|
||||
AIAssistance: "自动总结班级状态并给出补练建议",
|
||||
GeneratedSkills: "基于优秀班级复盘沉淀新训练营模板",
|
||||
State: "active",
|
||||
SortOrder: 10,
|
||||
},
|
||||
{
|
||||
Key: "knowledge-operations",
|
||||
Label: "知识运营专员",
|
||||
@@ -136,7 +112,7 @@ func SeedSpecialists(db *gorm.DB) error {
|
||||
},
|
||||
{
|
||||
Key: "wechat-official-account",
|
||||
Label: "公众号助手",
|
||||
Label: "公众号专员",
|
||||
Tier: "generic",
|
||||
SpecialistMode: "dw",
|
||||
ObjectEntryRoute: "/apps/wechat-official-account",
|
||||
@@ -207,76 +183,52 @@ func SeedSpecialists(db *gorm.DB) error {
|
||||
SortOrder: 60,
|
||||
},
|
||||
{
|
||||
Key: "logistics-fulfillment",
|
||||
Label: "履约跟单专员",
|
||||
Key: "customer-followup",
|
||||
Label: "客户跟进专员",
|
||||
Tier: "industry",
|
||||
SpecialistMode: "adw",
|
||||
ObjectEntryRoute: "/apps/logistics-fulfillment",
|
||||
Summary: "美西航线本周履约看板",
|
||||
WorkStatus: "1 个异常",
|
||||
RiskLabel: "2 个节点延迟",
|
||||
ObjectEntryRoute: "/apps/customer-followup",
|
||||
Summary: "整理客户资料、识别意向并推进会议预约",
|
||||
WorkStatus: "3 个客户待联系",
|
||||
RiskLabel: "1 个高意向待确认",
|
||||
Color: "#e6a23c",
|
||||
Stage: "异常处置",
|
||||
Progress: 49,
|
||||
Stage: "首轮触达",
|
||||
Progress: 46,
|
||||
MarketTag: "试用",
|
||||
Version: "v0.9",
|
||||
ConnectorScope: "连接船司 / 邮件 / 企微",
|
||||
PermissionScope: "节点读取、异常通知、履约状态写回、升级协同",
|
||||
ResourceBindings: "船司系统、邮件、企微、履约看板",
|
||||
InfoSources: "节点状态、异常邮件、订舱资料、客户承诺时间",
|
||||
BaseSkills: "节点跟踪、异常识别、催办升级、状态回写",
|
||||
AIAssistance: "自动判断异常影响范围并生成处置建议",
|
||||
GeneratedSkills: "把高频异常处理流程沉淀为自动履约技能",
|
||||
Version: "v1.0",
|
||||
ConnectorScope: "连接 CRM / 邮件 / 日程",
|
||||
PermissionScope: "客户资料读取、跟进状态写回、会议建议生成、提醒协同",
|
||||
ResourceBindings: "CRM、客户跟进表、邮件、会议日程",
|
||||
InfoSources: "客户资料、历史沟通记录、会议纪要、线索来源",
|
||||
BaseSkills: "客户资料归档、意向分层、联系建议、会议预约、状态回写",
|
||||
AIAssistance: "自动判断客户优先级并生成可直接发送的联系与邀约建议",
|
||||
GeneratedSkills: "把高转化跟进套路沉淀为客户推进技能",
|
||||
State: "active",
|
||||
SortOrder: 70,
|
||||
},
|
||||
{
|
||||
Key: "hr-email-sorter",
|
||||
Label: "HR 邮件整理专员",
|
||||
Tier: "industry",
|
||||
SpecialistMode: "dw",
|
||||
ObjectEntryRoute: "/apps/hr-email-sorter",
|
||||
Summary: "识别并整理招聘邮箱中的简历邮件",
|
||||
WorkStatus: "3 封待处理",
|
||||
RiskLabel: "0 个异常",
|
||||
Color: "#409eff",
|
||||
Stage: "邮件处理",
|
||||
Progress: 0,
|
||||
MarketTag: "试用",
|
||||
Version: "v1.0",
|
||||
ConnectorScope: "连接 HR 招聘邮箱 / 邮件系统",
|
||||
PermissionScope: "招聘邮箱读取、候选人表写入",
|
||||
ResourceBindings: "HR 招聘邮箱、候选人管理表",
|
||||
InfoSources: "HR 招聘邮箱收件箱",
|
||||
BaseSkills: "简历邮件识别、候选人信息抽取、去重归类",
|
||||
AIAssistance: "自动识别简历邮件并抽取候选人字段",
|
||||
GeneratedSkills: "从历史招聘中沉淀简历筛选规则",
|
||||
State: "active",
|
||||
SortOrder: 80,
|
||||
},
|
||||
{
|
||||
Key: "resume-processor",
|
||||
Label: "简历处理专员",
|
||||
Label: "招聘筛选专员",
|
||||
Tier: "industry",
|
||||
SpecialistMode: "dw",
|
||||
ObjectEntryRoute: "/apps/resume-processor",
|
||||
Summary: "筛选候选人并安排面试",
|
||||
WorkStatus: "5 份待筛选",
|
||||
Summary: "收拢招聘邮件、筛选候选人并推进面试",
|
||||
WorkStatus: "5 份待筛选 / 3 封待归档",
|
||||
RiskLabel: "1 个匹配待确认",
|
||||
Color: "#67c23a",
|
||||
Stage: "简历筛选",
|
||||
Stage: "候选人筛选",
|
||||
Progress: 0,
|
||||
MarketTag: "试用",
|
||||
Version: "v1.0",
|
||||
ConnectorScope: "连接候选人表 / 岗位需求表",
|
||||
PermissionScope: "候选人表读写、面试安排表写入、岗位需求表读取",
|
||||
ResourceBindings: "候选人表、岗位需求表、面试安排表",
|
||||
InfoSources: "候选人表、岗位需求表",
|
||||
BaseSkills: "简历筛选、评分排序、跟进标记、面试安排",
|
||||
AIAssistance: "自动匹配岗位要求并给出排序建议",
|
||||
ConnectorScope: "连接招聘邮箱 / 候选人表 / 岗位需求表",
|
||||
PermissionScope: "招聘邮箱读取、候选人表读写、面试安排表写入、岗位需求表读取",
|
||||
ResourceBindings: "招聘邮箱、候选人表、岗位需求表、面试安排表",
|
||||
InfoSources: "招聘邮箱、候选人表、岗位需求表",
|
||||
BaseSkills: "邮件归档、候选人抽取、简历筛选、评分排序、跟进标记、面试安排",
|
||||
AIAssistance: "自动归并招聘入口并匹配岗位要求给出排序建议",
|
||||
GeneratedSkills: "从录用决策中沉淀筛选模型",
|
||||
State: "active",
|
||||
SortOrder: 90,
|
||||
SortOrder: 80,
|
||||
},
|
||||
{
|
||||
Key: "presentation-briefing",
|
||||
@@ -375,6 +327,23 @@ func SeedSpecialists(db *gorm.DB) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := deleteSpecialists(db, []string{
|
||||
"training-delivery",
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := retireSpecialists(db, []string{
|
||||
"knowledge-operations",
|
||||
"process-coordination",
|
||||
"report-generation",
|
||||
"presentation-briefing",
|
||||
"hr-email-sorter",
|
||||
"logistics-fulfillment",
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
specialistcore.LogRuleFileCoverage(db)
|
||||
log.Println("[OK] 专员目录种子已导入")
|
||||
return nil
|
||||
@@ -397,3 +366,20 @@ func applySpecialistCodes(items []specialistmodel.Specialist) []specialistmodel.
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func deleteSpecialists(db *gorm.DB, keys []string) error {
|
||||
if len(keys) == 0 {
|
||||
return nil
|
||||
}
|
||||
return db.Where("key IN ?", keys).Delete(&specialistmodel.Specialist{}).Error
|
||||
}
|
||||
|
||||
func retireSpecialists(db *gorm.DB, keys []string) error {
|
||||
if len(keys) == 0 {
|
||||
return nil
|
||||
}
|
||||
return db.Model(&specialistmodel.Specialist{}).
|
||||
Where("key IN ?", keys).
|
||||
Where("state = ?", "active").
|
||||
Update("state", "retired").Error
|
||||
}
|
||||
|
||||
@@ -322,8 +322,8 @@ func seedSkillDefinitions() error {
|
||||
items := applySkillCodes([]skillmodel.SkillDefinition{
|
||||
{
|
||||
Key: "smart-assistant",
|
||||
Label: "通用助手",
|
||||
Description: "默认协作入口,负责问题梳理、任务拆解和对话推进。",
|
||||
Label: "智能助手",
|
||||
Description: "说句话,复杂任务自动完成。 操作:打开「智能助手」,用自然语言描述目标 → 可拖入多份文件、关联知识库 → 助手自动拆解为「计划→执行→验证→交付」,全程可见可控",
|
||||
ObjectKind: "skill",
|
||||
Source: "eai",
|
||||
ObjectEntryRoute: "/home",
|
||||
@@ -335,13 +335,23 @@ func seedSkillDefinitions() error {
|
||||
OutputSchemaJSON: mustJSON(map[string]any{"message": "assistant_reply"}),
|
||||
ArtifactSchemaJSON: mustJSON(map[string]any{"artifacts": []string{"summary", "plan"}}),
|
||||
OntologyBindingJSON: mustJSON(map[string]any{"object_types": []string{"task", "knowledge_item"}, "action_types": []string{"analyze", "draft"}}),
|
||||
Color: "#409eff",
|
||||
InteractionCardJSON: mustJSON(map[string]any{
|
||||
"name": "智能助手",
|
||||
"tagline": "今天帮你做些什么?描述你的任务,或先挂载技能与材料",
|
||||
"greeting": "博昇AI数字员工,您说,我做",
|
||||
"relationship_to_user": "你的通用协作搭档",
|
||||
"tone": "专业、直接、可执行",
|
||||
"opening_prompt": "直接告诉我目标,或者把材料贴给我,我来帮你起步。",
|
||||
"starter_prompts": []string{"帮我拆解这个任务,并列出下一步", "把这段产品介绍整理成正式文案", "先帮我判断这个问题该找哪个专员或技能"},
|
||||
}),
|
||||
State: "active",
|
||||
SortOrder: 10,
|
||||
},
|
||||
{
|
||||
Key: "document-translate",
|
||||
Label: "文档翻译",
|
||||
Description: "把文本和文档稳定翻成目标语言,并保留语气和结构。",
|
||||
Description: "整份翻译,排版原封不动。 操作:打开「文档翻译」,上传文件(Word/PDF/PPT/Excel)→ 选择目标语言 → 下载译文——排版、表格、图片位置全部保留",
|
||||
ObjectKind: "skill",
|
||||
Source: "eai",
|
||||
ObjectEntryRoute: "/home",
|
||||
@@ -353,13 +363,23 @@ func seedSkillDefinitions() error {
|
||||
OutputSchemaJSON: mustJSON(map[string]any{"translation": "text"}),
|
||||
ArtifactSchemaJSON: mustJSON(map[string]any{"artifacts": []string{"translated_document"}}),
|
||||
OntologyBindingJSON: mustJSON(map[string]any{"object_types": []string{"document"}, "action_types": []string{"translate"}}),
|
||||
Color: "#67c23a",
|
||||
InteractionCardJSON: mustJSON(map[string]any{
|
||||
"name": "文档翻译",
|
||||
"tagline": "不仅翻译文字,还会先统一术语、语气和交付格式。",
|
||||
"greeting": "先识别语境和术语,再生成可交付译文,避免只做逐句直译。",
|
||||
"relationship_to_user": "你的翻译协作技能",
|
||||
"tone": "专业、直接、可执行",
|
||||
"opening_prompt": "把原文贴给我,并说明目标语言、受众和语气要求;如果有术语表,也一起给我。",
|
||||
"starter_prompts": []string{"把这段产品说明翻译成英文,保持专业语气", "把这封邮件翻译成日文,语气礼貌一点", "把这份中文文档整理成英文摘要"},
|
||||
}),
|
||||
State: "active",
|
||||
SortOrder: 20,
|
||||
},
|
||||
{
|
||||
Key: "copy-proofreading",
|
||||
Label: "文案校对",
|
||||
Description: "检查错别字、语病和表达不顺,输出润色建议。",
|
||||
Description: "错别字、语病,一键标出。 操作:打开「文案校对」,上传文档 → AI 自动逐句检查,标注错别字、语法问题 → 返回带高亮修订版 + 修改建议,可一键采纳",
|
||||
ObjectKind: "skill",
|
||||
Source: "eai",
|
||||
ObjectEntryRoute: "/home",
|
||||
@@ -371,13 +391,23 @@ func seedSkillDefinitions() error {
|
||||
OutputSchemaJSON: mustJSON(map[string]any{"proofread_result": "text"}),
|
||||
ArtifactSchemaJSON: mustJSON(map[string]any{"artifacts": []string{"clean_copy"}}),
|
||||
OntologyBindingJSON: mustJSON(map[string]any{"object_types": []string{"copy"}, "action_types": []string{"review"}}),
|
||||
Color: "#e6a23c",
|
||||
InteractionCardJSON: mustJSON(map[string]any{
|
||||
"name": "文案校对",
|
||||
"tagline": "不是只改错字,而是把整段表达修顺、修稳、修清楚。",
|
||||
"greeting": "先找出问题句和语气风险,再给出能直接使用的修订版本。",
|
||||
"relationship_to_user": "你的文案润色技能",
|
||||
"tone": "专业、直接、可执行",
|
||||
"opening_prompt": "把文案贴给我,并告诉我这段内容要发给谁、希望保留什么语气。",
|
||||
"starter_prompts": []string{"检查这段销售话术里的错别字和语病", "把这段产品介绍润得更正式一点", "帮我校对这封对外邮件,保留原意"},
|
||||
}),
|
||||
State: "active",
|
||||
SortOrder: 30,
|
||||
},
|
||||
{
|
||||
Key: "audio-transcribe",
|
||||
Label: "语音转写",
|
||||
Description: "把音频内容转成结构化文本,便于继续总结与提取。",
|
||||
Label: "会议音频分析(转写)",
|
||||
Description: "一小时录音,自动出纪要。 操作:打开「会议音频分析」,上传音频(MP3/M4A/WAV)→ AI 自动转写(带说话人标签)→ 同时输出纪要 + 待办清单 + 思维导图",
|
||||
ObjectKind: "skill",
|
||||
Source: "eai",
|
||||
ObjectEntryRoute: "/home",
|
||||
@@ -389,13 +419,23 @@ func seedSkillDefinitions() error {
|
||||
OutputSchemaJSON: mustJSON(map[string]any{"transcript": "text"}),
|
||||
ArtifactSchemaJSON: mustJSON(map[string]any{"artifacts": []string{"transcript"}}),
|
||||
OntologyBindingJSON: mustJSON(map[string]any{"object_types": []string{"audio"}, "action_types": []string{"extract"}}),
|
||||
Color: "#5263c3",
|
||||
InteractionCardJSON: mustJSON(map[string]any{
|
||||
"name": "会议音频分析(转写)",
|
||||
"tagline": "把音频从“听过”变成“可查、可引用、可交付”的文本资产。",
|
||||
"greeting": "先把语音内容转成可靠文本,再继续整理重点、纪要和后续动作。",
|
||||
"relationship_to_user": "你的语音整理技能",
|
||||
"tone": "专业、直接、可执行",
|
||||
"opening_prompt": "把音频内容发给我,或者告诉我语言、场景和你最终想拿到什么结果。",
|
||||
"starter_prompts": []string{"把这段会议录音转成文字,并分段整理", "先转写这段采访,再提取重点", "把语音内容整理成可发群里的纪要"},
|
||||
}),
|
||||
State: "active",
|
||||
SortOrder: 40,
|
||||
},
|
||||
{
|
||||
Key: "batch-extract",
|
||||
Label: "批量提取",
|
||||
Description: "从一批内容里抽取结构化字段和关键信息。",
|
||||
Label: "批量字段提取 → Excel",
|
||||
Description: "上百份文件的关键信息,自动汇表。 操作:在「智能助手」中选择目标知识库 → 用自然语言告诉 AI 需要哪些字段 → AI 自动遍历每份文件,逐项提取,保存为 Excel",
|
||||
ObjectKind: "skill",
|
||||
Source: "eai",
|
||||
ObjectEntryRoute: "/home",
|
||||
@@ -407,13 +447,23 @@ func seedSkillDefinitions() error {
|
||||
OutputSchemaJSON: mustJSON(map[string]any{"rows": []string{"object"}}),
|
||||
ArtifactSchemaJSON: mustJSON(map[string]any{"artifacts": []string{"spreadsheet", "json"}}),
|
||||
OntologyBindingJSON: mustJSON(map[string]any{"object_types": []string{"document", "resume", "contract"}, "action_types": []string{"extract"}}),
|
||||
Color: "#39b07a",
|
||||
InteractionCardJSON: mustJSON(map[string]any{
|
||||
"name": "批量字段提取 → Excel",
|
||||
"tagline": "不是只把内容抓出来,而是直接整理成后续系统能用的结构化结果。",
|
||||
"greeting": "先把字段定义清楚,再批量抽取,并把异常项单独挑出来。",
|
||||
"relationship_to_user": "你的结构化提取技能",
|
||||
"tone": "专业、直接、可执行",
|
||||
"opening_prompt": "告诉我想抽哪些字段、输出成什么格式、哪些情况需要标记为异常。",
|
||||
"starter_prompts": []string{"从这批简历里提取姓名、岗位和年限", "把这些合同里的付款条款统一抽出来", "帮我批量提取文章标题、作者和发布时间"},
|
||||
}),
|
||||
State: "active",
|
||||
SortOrder: 50,
|
||||
},
|
||||
{
|
||||
Key: "contract-review",
|
||||
Label: "合同审查",
|
||||
Description: "定位风险条款、待确认项并输出审查建议。",
|
||||
Label: "合同批量审查与提取(审查)",
|
||||
Description: "几十份合同,自动提取甲方、乙方、金额、付款方式等关键字段,一键汇总成 Excel 总表。还能按条件筛选\"百万以上合同\"或\"涉及公路运输的合同\",并自动归纳违约金条款。",
|
||||
ObjectKind: "skill",
|
||||
Source: "eai",
|
||||
ObjectEntryRoute: "/home",
|
||||
@@ -425,13 +475,23 @@ func seedSkillDefinitions() error {
|
||||
OutputSchemaJSON: mustJSON(map[string]any{"risk_report": "text"}),
|
||||
ArtifactSchemaJSON: mustJSON(map[string]any{"artifacts": []string{"risk_report", "redline"}}),
|
||||
OntologyBindingJSON: mustJSON(map[string]any{"object_types": []string{"contract"}, "action_types": []string{"review", "analyze"}}),
|
||||
Color: "#f56c6c",
|
||||
InteractionCardJSON: mustJSON(map[string]any{
|
||||
"name": "合同批量审查与提取(审查)",
|
||||
"tagline": "不是只报风险,而是把风险依据、红线建议和后续确认项一起交出来。",
|
||||
"greeting": "先定位高风险条款和待确认项,再整理成可交付的审查结果。",
|
||||
"relationship_to_user": "你的合同审查技能",
|
||||
"tone": "专业、直接、可执行",
|
||||
"opening_prompt": "把合同发给我,并告诉我这次重点想看哪些条款,或者你站在哪一方立场。",
|
||||
"starter_prompts": []string{"审查这份采购合同的风险点", "重点看赔偿责任和终止条款", "帮我整理一版待人工确认的风险清单"},
|
||||
}),
|
||||
State: "active",
|
||||
SortOrder: 60,
|
||||
},
|
||||
{
|
||||
Key: "report-generation",
|
||||
Label: "报告生成",
|
||||
Description: "把过程材料整理成日报、周报、复盘和交付说明。",
|
||||
Label: "一键生成报告",
|
||||
Description: "聊完天,PDF/Word 报告就写好了。 操作:在「智能助手」中上传资料或讨论要点 → 说\"帮我做成 PDF 报告\"或\"整理成 Word\" → AI 自动生成结构化内容,排版为正式文档,一键下载",
|
||||
ObjectKind: "skill",
|
||||
Source: "eai",
|
||||
ObjectEntryRoute: "/home",
|
||||
@@ -443,6 +503,16 @@ func seedSkillDefinitions() error {
|
||||
OutputSchemaJSON: mustJSON(map[string]any{"report": "text"}),
|
||||
ArtifactSchemaJSON: mustJSON(map[string]any{"artifacts": []string{"report"}}),
|
||||
OntologyBindingJSON: mustJSON(map[string]any{"object_types": []string{"report", "task"}, "action_types": []string{"draft"}}),
|
||||
Color: "#9c27b0",
|
||||
InteractionCardJSON: mustJSON(map[string]any{
|
||||
"name": "一键生成报告",
|
||||
"tagline": "不只是把记录拼起来,而是把过程信息收成完整、清楚、可汇报的结果。",
|
||||
"greeting": "先把材料归并成结构,再输出可直接提交的正式报告。",
|
||||
"relationship_to_user": "你的报告整理技能",
|
||||
"tone": "专业、直接、可执行",
|
||||
"opening_prompt": "把材料给我,并告诉我报告类型、受众、周期和你最想突出哪些重点。",
|
||||
"starter_prompts": []string{"把今天的工作记录整理成日报", "根据这些节点生成项目周报", "帮我把这次交付过程整理成复盘说明"},
|
||||
}),
|
||||
State: "active",
|
||||
SortOrder: 70,
|
||||
},
|
||||
@@ -469,6 +539,12 @@ func seedSkillDefinitions() error {
|
||||
if existing.ObjectEntryRoute == "" {
|
||||
updates["object_entry_route"] = item.ObjectEntryRoute
|
||||
}
|
||||
if existing.Color == "" {
|
||||
updates["color"] = item.Color
|
||||
}
|
||||
if existing.InteractionCardJSON == "" {
|
||||
updates["interaction_card_json"] = item.InteractionCardJSON
|
||||
}
|
||||
if existing.StarterPromptsJSON == "" {
|
||||
updates["starter_prompts_json"] = item.StarterPromptsJSON
|
||||
}
|
||||
@@ -783,29 +859,6 @@ func seedXAppDefinitions() error {
|
||||
State: "active",
|
||||
SortOrder: 60,
|
||||
},
|
||||
{
|
||||
Key: "app-proposal-summary",
|
||||
Label: "方案摘要",
|
||||
Badge: "成品应用",
|
||||
Kind: "汇报加速",
|
||||
MarketTag: "成品应用",
|
||||
XAppMode: "direct",
|
||||
Tier: "business",
|
||||
Source: "eai",
|
||||
Color: "#7c3aed",
|
||||
IconText: "方",
|
||||
CoverTone: "linear-gradient(135deg, #6d28d9 0%, #a78bfa 100%)",
|
||||
Summary: "直接进入方案摘要应用,把长方案压成管理层可读的短版本。",
|
||||
Description: "适合售前方案、项目方案和内部提案的结论压缩与亮点提炼。",
|
||||
SkillKey: "proposal-summary",
|
||||
DefaultPrompt: "把这份解决方案压成一版管理层摘要",
|
||||
PromptsJSON: mustJSON([]string{"把这份解决方案压成一版管理层摘要", "提炼亮点和实施建议", "生成汇报短版和亮点清单"}),
|
||||
TagsJSON: mustJSON([]string{"方案摘要", "亮点提炼", "管理层预读", "汇报短版"}),
|
||||
InstallState: "installed",
|
||||
ExposedToUser: true,
|
||||
State: "active",
|
||||
SortOrder: 70,
|
||||
},
|
||||
{
|
||||
Key: "app-progress-report",
|
||||
Label: "周报 / 日报",
|
||||
|
||||
Reference in New Issue
Block a user