154 lines
4.2 KiB
Go
154 lines
4.2 KiB
Go
package biz
|
||
|
||
import (
|
||
"ai_scheduler/internal/biz/llm_service/third_party"
|
||
"ai_scheduler/internal/entitys"
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"os"
|
||
|
||
"strings"
|
||
|
||
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
|
||
"github.com/volcengine/volcengine-go-sdk/volcengine"
|
||
)
|
||
|
||
type AdviceBiz struct {
|
||
hsyq *third_party.Hsyq
|
||
}
|
||
|
||
func NewAdviceBiz(hsyq *third_party.Hsyq) *AdviceBiz {
|
||
return &AdviceBiz{
|
||
hsyq: hsyq,
|
||
}
|
||
}
|
||
|
||
const (
|
||
key = "236ba4b6-9daa-4755-b22f-2fd274cd223a"
|
||
modelName = "doubao-seed-1-8-251228"
|
||
)
|
||
|
||
var dataMap = map[string]string{
|
||
"DialectFeatures": (&entitys.DialectFeatures{}).Example(),
|
||
"SentencePatterns": (&entitys.SentencePatterns{}).Example(),
|
||
"PersonalityTags": (&entitys.PersonalityTags{}).Example(),
|
||
"ToneTags": (&entitys.ToneTags{}).Example(),
|
||
"SignatureDialogues": (&entitys.SignatureDialogues{}).Example(),
|
||
"RegionValue": (&entitys.RegionValue{}).Example(),
|
||
"CompetitionComparison": (&entitys.CompetitionComparison{}).Example(),
|
||
"CoreSellingPoints": (&entitys.CoreSellingPoints{}).Example(),
|
||
"SupportingFacilities": (&entitys.SupportingFacilities{}).Example(),
|
||
"DeveloperBacking": (&entitys.DeveloperBacking{}).Example(),
|
||
"NeedsMining": (&entitys.NeedsMining{}).Example(),
|
||
"PainPointResponse": (&entitys.PainPointResponse{}).Example(),
|
||
"ValueBuilding": (&entitys.ValueBuilding{}).Example(),
|
||
"ClosingTechniques": (&entitys.ClosingTechniques{}).Example(),
|
||
"CommunicationRhythm": (&entitys.CommunicationRhythm{}).Example(),
|
||
}
|
||
|
||
func (a *AdviceBiz) WordAna(ctx context.Context, wordContent string) error {
|
||
examples := a.getAllExamples()
|
||
prompt := a.buildSimplePrompt(wordContent, examples)
|
||
anaContent, err := a.callLlm(ctx, prompt)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
data := a.parseResponse(anaContent)
|
||
jsonData, _ := json.MarshalIndent(data, "", " ")
|
||
os.WriteFile("extracted.json", jsonData, 0644)
|
||
fmt.Println("✅ 数据已保存到 extracted.json")
|
||
return nil
|
||
}
|
||
|
||
func (a *AdviceBiz) callLlm(ctx context.Context, prompt string) (string, error) {
|
||
var message = make([]*model.ChatCompletionMessage, 1)
|
||
message[0] = &model.ChatCompletionMessage{
|
||
Role: model.ChatMessageRoleUser,
|
||
Content: &model.ChatCompletionMessageContent{
|
||
StringValue: volcengine.String(prompt),
|
||
},
|
||
}
|
||
|
||
res, err := a.hsyq.RequestHsyq(ctx, key, modelName, message)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return *res.Choices[0].Message.Content.StringValue, nil
|
||
}
|
||
|
||
func (a *AdviceBiz) getAllExamples() map[string]string {
|
||
return dataMap
|
||
}
|
||
|
||
func (a *AdviceBiz) buildSimplePrompt(wordContent string, examples map[string]string) string {
|
||
// 最简单的提示词模板
|
||
template := `分析以下房地产销售对话,按指定格式提取信息:
|
||
|
||
对话内容:
|
||
%s
|
||
|
||
请按照以下` + fmt.Sprintf("%d", len(examples)) + `个格式生成JSON数据,每个格式用===分隔:
|
||
|
||
%s
|
||
|
||
输出要求:
|
||
1. 每个结构体一个JSON对象
|
||
2. 严格按照示例格式
|
||
3. 用空行分隔不同结构体`
|
||
|
||
// 构建格式部分
|
||
var formats strings.Builder
|
||
for name, example := range examples {
|
||
formats.WriteString(fmt.Sprintf("=== %s ===\n示例:%s\n\n", name, example))
|
||
}
|
||
|
||
return fmt.Sprintf(template, wordContent, formats.String())
|
||
}
|
||
|
||
func (a *AdviceBiz) parseResponse(response string) map[string]interface{} {
|
||
result := make(map[string]interface{})
|
||
|
||
// 按空行分割
|
||
parts := strings.Split(response, "\n\n")
|
||
|
||
for _, part := range parts {
|
||
part = strings.TrimSpace(part)
|
||
if part == "" || !strings.Contains(part, "{") {
|
||
continue
|
||
}
|
||
|
||
// 找到第一个 { 和最后一个 }
|
||
start := strings.Index(part, "{")
|
||
end := strings.LastIndex(part, "}")
|
||
|
||
if start == -1 || end == -1 || end <= start {
|
||
continue
|
||
}
|
||
|
||
jsonStr := part[start : end+1]
|
||
|
||
// 尝试解析
|
||
var data interface{}
|
||
if err := json.Unmarshal([]byte(jsonStr), &data); err == nil {
|
||
// 判断是什么结构体
|
||
for _, name := range getStructNames() {
|
||
if strings.Contains(jsonStr, `"`+name+`"`) || strings.Contains(part, name) {
|
||
result[name] = data
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
func getStructNames() []string {
|
||
var res = make([]string, 0, len(dataMap))
|
||
for k, _ := range dataMap {
|
||
res = append(res, k)
|
||
}
|
||
return res
|
||
}
|