feat:工作流、工具架构调整 与 demo 编写

This commit is contained in:
fuzhongyun 2025-12-09 18:36:09 +08:00
parent 5e1fab132a
commit e099f82119
8 changed files with 183 additions and 1 deletions

4
go.mod
View File

@ -9,6 +9,7 @@ require (
github.com/alibabacloud-go/tea v1.2.2
github.com/alibabacloud-go/tea-utils/v2 v2.0.6
github.com/cloudwego/eino v0.7.7
github.com/cloudwego/eino-ext/components/model/ollama v0.1.6
github.com/cloudwego/eino-ext/components/model/openai v0.1.5
github.com/emirpasic/gods v1.18.1
github.com/faabiosr/cachego v0.26.0
@ -53,6 +54,7 @@ require (
github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/eino-contrib/jsonschema v1.0.3 // indirect
github.com/eino-contrib/ollama v0.1.0 // indirect
github.com/evanphx/json-patch v0.5.2 // indirect
github.com/fasthttp/websocket v1.5.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
@ -101,7 +103,7 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.11.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sys v0.33.0 // indirect

4
go.sum
View File

@ -132,6 +132,8 @@ github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
github.com/cloudwego/eino v0.7.7 h1:WhP0SMWWPgLdOH03HrKUxtP9/Q96NhziMZNEQl9lxpU=
github.com/cloudwego/eino v0.7.7/go.mod h1:nA8Vacmuqv3pqKBQbTWENBLQ8MmGmPt/WqiyLeB8ohQ=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.6 h1:ZbrhV91uE0hGIOYXhb2i3G6tQJ/rK2SLYtoYrmocZXM=
github.com/cloudwego/eino-ext/components/model/ollama v0.1.6/go.mod h1:GDXrvorGdRNV6g2mK5jdla2D8Xc/hh7XDrTeGDteLLo=
github.com/cloudwego/eino-ext/components/model/openai v0.1.5 h1:+yvGbTPw93li9GSmdm6Rix88Yy8AXg5NNBcRbWx3CQU=
github.com/cloudwego/eino-ext/components/model/openai v0.1.5/go.mod h1:IPVYMFoZcuHeVEsDTGN6SZjvue0xr1iZFhdpq1SBWdQ=
github.com/cloudwego/eino-ext/libs/acl/openai v0.1.2 h1:r9Id2wzJ05PoHl+Km7jQgNMgciaZI93TVnUYso89esM=
@ -151,6 +153,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/eino-contrib/jsonschema v1.0.3 h1:2Kfsm1xlMV0ssY2nuxshS4AwbLFuqmPmzIjLVJ1Fsp0=
github.com/eino-contrib/jsonschema v1.0.3/go.mod h1:cpnX4SyKjWjGC7iN2EbhxaTdLqGjCi0e9DxpLYxddD4=
github.com/eino-contrib/ollama v0.1.0 h1:z1NaMdKW6X1ftP8g5xGGR5zDRPUtuTKFq35vBQgxsN4=
github.com/eino-contrib/ollama v0.1.0/go.mod h1:mYsQ7b3DeqY8bHPuD3MZJYTqkgyL6LoemxoP/B7ZNhA=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=

View File

@ -0,0 +1,47 @@
package order_after_reseller_batch
import (
"ai_scheduler/internal/config"
"ai_scheduler/internal/pkg/l_request"
"ai_scheduler/internal/pkg/util"
"context"
"encoding/json"
"errors"
"fmt"
)
func Call(ctx context.Context, cfg config.ToolConfig, orderNumbers []string) (OrderAfterSaleResellerBatchData, error) {
if len(orderNumbers) == 0 {
return OrderAfterSaleResellerBatchData{}, errors.New("批充订单号不能为空")
}
token := util.GetTokenFromContext(ctx)
if token == "" {
return OrderAfterSaleResellerBatchData{}, errors.New("token 未注入")
}
r := l_request.Request{
Url: cfg.BaseURL,
Headers: map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", token),
},
Method: "POST",
Json: map[string]any{
"order_numbers": orderNumbers,
"order_type": 2,
},
}
res, err := r.Send()
if err != nil {
return OrderAfterSaleResellerBatchData{}, err
}
var response OrderAfterSaleResellerBatchResponse
if err = json.Unmarshal(res.Content, &response); err != nil {
return OrderAfterSaleResellerBatchData{}, err
}
if response.Code != 200 {
return OrderAfterSaleResellerBatchData{}, fmt.Errorf("售后订单查询异常: %s", response.Error)
}
if len(response.Data.Data) == 0 {
return OrderAfterSaleResellerBatchData{}, errors.New("未查询到相应售后订单,请核实订单号是否正确")
}
return response.Data, nil
}

View File

@ -0,0 +1,24 @@
package order_after_reseller_batch
import (
"ai_scheduler/internal/config"
"context"
"github.com/cloudwego/eino/components/tool"
toolutils "github.com/cloudwego/eino/components/tool/utils"
)
type Args struct {
OrderNumber []string `json:"orderNumber"`
}
func NewInvokable(cfg config.ToolConfig) tool.InvokableTool {
run := func(ctx context.Context, in Args) (OrderAfterSaleResellerBatchData, error) {
return Call(ctx, cfg, in.OrderNumber)
}
t, err := toolutils.InferTool("zltxOrderAfterSaleResellerBatch", "直连天下下游分销商批充订单售后工具", run)
if err != nil {
panic(err)
}
return t
}

View File

@ -0,0 +1,32 @@
package order_after_reseller_batch
type OrderAfterSaleResellerBatchResponse struct {
Code int `json:"code"`
Error string `json:"error"`
Data OrderAfterSaleResellerBatchData `json:"data"`
}
type OrderAfterSaleResellerBatchData struct {
Data []OrderAfterSaleResellerBatchBase `json:"data"`
ExtData map[string]OrderAfterSaleResellerBatchExtItem `json:"extraData"`
}
type OrderAfterSaleResellerBatchBase struct {
OrderType int `json:"orderType"`
OrderNumber string `json:"orderNumber"`
OrderAmount float64 `json:"orderAmount"`
OrderPrice float64 `json:"orderPrice"`
SignCompany int `json:"signCompany"`
OrderQuantity int `json:"orderQuantity"`
ResellerID int `json:"resellerId"`
ResellerName string `json:"resellerName"`
OurProductID int `json:"ourProductId"`
OurProductTitle string `json:"ourProductTitle"`
Account []string `json:"account"`
Platforms map[int]string `json:"platforms"`
}
type OrderAfterSaleResellerBatchExtItem struct {
IsExistsAfterSale bool `json:"isExistsAfterSale"`
SerialCreateTime int `json:"createTime"`
}

View File

@ -0,0 +1 @@
package zltx

View File

@ -0,0 +1,47 @@
package zltx
import (
"ai_scheduler/internal/config"
toolZoarb "ai_scheduler/internal/domain/tools/zltx/order_after_reseller_batch"
"context"
"errors"
"github.com/cloudwego/eino/compose"
)
type OrderAfterSaleResellerBatchWorkflowInput struct {
Token string `json:"token"`
OrderNumber []string `json:"orderNumber"`
}
var ErrInvalidOrderNumbers = errors.New("orderNumber 不能为空")
var ErrMissingToken = errors.New("token 不能为空")
func BuildOrderAfterResellerBatchWorkflow(ctx context.Context, cfg config.ToolConfig) (compose.Runnable[OrderAfterSaleResellerBatchWorkflowInput, toolZoarb.OrderAfterSaleResellerBatchData], error) {
// 定义工作流、出入参
c := compose.NewChain[OrderAfterSaleResellerBatchWorkflowInput, toolZoarb.OrderAfterSaleResellerBatchData]()
// 1.入参解析与校验
c.AppendLambda(compose.InvokableLambda(func(_ context.Context, in OrderAfterSaleResellerBatchWorkflowInput) (OrderAfterSaleResellerBatchWorkflowInput, error) {
if len(in.OrderNumber) == 0 {
return OrderAfterSaleResellerBatchWorkflowInput{}, ErrInvalidOrderNumbers
}
if in.Token == "" {
return OrderAfterSaleResellerBatchWorkflowInput{}, ErrMissingToken
}
return in, nil
}))
// 2.调用工具
c.AppendLambda(compose.InvokableLambda(func(ctx context.Context, in OrderAfterSaleResellerBatchWorkflowInput) (toolZoarb.OrderAfterSaleResellerBatchData, error) {
return toolZoarb.Call(ctx, cfg, in.OrderNumber)
}))
// 3.结果映射与整形
c.AppendLambda(compose.InvokableLambda(func(_ context.Context, in toolZoarb.OrderAfterSaleResellerBatchData) (toolZoarb.OrderAfterSaleResellerBatchData, error) {
return in, nil
}))
// 编译工作流
return c.Compile(ctx)
}

25
internal/pkg/util/ctx.go Normal file
View File

@ -0,0 +1,25 @@
package util
import (
"context"
)
type ContextKey string
const (
ContextKeyToken ContextKey = "token"
)
// token 写入上下文
func SetTokenToContext(ctx context.Context, token string) context.Context {
return context.WithValue(ctx, ContextKeyToken, token)
}
// 从上下文获取token
func GetTokenFromContext(ctx context.Context) string {
token, ok := ctx.Value(ContextKeyToken).(string)
if !ok {
return ""
}
return token
}