Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions backend/api/handler/coze/loop/apis/prompt_open_apiservice.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ require (
github.com/dolthub/vitess v0.0.0-20240228192915-d55088cef56a
github.com/expr-lang/expr v1.17.0
github.com/fatih/structs v1.1.0
github.com/flosch/pongo2/v6 v6.0.0
github.com/fsnotify/fsnotify v1.8.0
github.com/getkin/kin-openapi v0.118.0
github.com/go-playground/validator/v10 v10.20.0
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

97 changes: 97 additions & 0 deletions backend/modules/prompt/api/jinja2_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) 2025 coze-dev Authors
// SPDX-License-Identifier: Apache-2.0

package api

import (
"context"

"github.com/coze-dev/coze-loop/backend/kitex_gen/coze/loop/prompt/openapi"
"github.com/coze-dev/coze-loop/backend/modules/prompt/domain/entity"
)

// Jinja2TemplateService Jinja2模板服务
type Jinja2TemplateService struct{}

// NewJinja2TemplateService 创建新的Jinja2模板服务实例
func NewJinja2TemplateService() *Jinja2TemplateService {
return &Jinja2TemplateService{}
}

// ValidateTemplate 验证Jinja2模板语法
func (s *Jinja2TemplateService) ValidateTemplate(ctx context.Context, req *openapi.ValidateTemplateRequest) (*openapi.ValidateTemplateResponse, error) {
// 验证模板类型
if req.TemplateType != "jinja2" {
return &openapi.ValidateTemplateResponse{
Code: 400,
Msg: "Only jinja2 template type is supported for validation",
Data: &openapi.ValidateTemplateData{
IsValid: false,
ErrorMessage: "Unsupported template type",
},
}, nil
}

// 创建Jinja2引擎进行语法验证
engine := entity.NewJinja2Engine()

// 使用空变量进行语法验证
_, err := engine.Execute(req.Template, map[string]interface{}{})

response := &openapi.ValidateTemplateResponse{
Code: 200,
Msg: "Success",
Data: &openapi.ValidateTemplateData{
IsValid: err == nil,
},
}

if err != nil {
response.Data.ErrorMessage = err.Error()
}

return response, nil
}

// PreviewTemplate 预览Jinja2模板渲染结果
func (s *Jinja2TemplateService) PreviewTemplate(ctx context.Context, req *openapi.PreviewTemplateRequest) (*openapi.PreviewTemplateResponse, error) {
// 验证模板类型
if req.TemplateType != "jinja2" {
return &openapi.PreviewTemplateResponse{
Code: 400,
Msg: "Only jinja2 template type is supported for preview",
Data: &openapi.PreviewTemplateData{
Result: "Error: Unsupported template type",
},
}, nil
}

// 创建Jinja2引擎
engine := entity.NewJinja2Engine()

// 构建变量映射
variables := make(map[string]interface{})
for key, value := range req.Variables {
variables[key] = value
}

// 执行模板渲染
result, err := engine.Execute(req.Template, variables)
if err != nil {
return &openapi.PreviewTemplateResponse{
Code: 400,
Msg: "Template execution failed",
Data: &openapi.PreviewTemplateData{
Result: "Error: " + err.Error(),
},
}, nil
}

return &openapi.PreviewTemplateResponse{
Code: 200,
Msg: "Success",
Data: &openapi.PreviewTemplateData{
Result: result,
},
}, nil
}
101 changes: 101 additions & 0 deletions backend/modules/prompt/application/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,104 @@ func (p *PromptOpenAPIApplicationImpl) AllowBySpace(ctx context.Context, workspa
}
return false
}

// ValidateTemplate 验证Jinja2模板语法
func (p *PromptOpenAPIApplicationImpl) ValidateTemplate(ctx context.Context, req *openapi.ValidateTemplateRequest) (*openapi.ValidateTemplateResponse, error) {
r := openapi.NewValidateTemplateResponse()

// 参数验证
if req.GetTemplate() == "" {
return r, errorx.NewByCode(prompterr.CommonInvalidParamCode, errorx.WithExtraMsg("template参数不能为空"))
}

if req.GetTemplateType() != "jinja2" {
return r, errorx.NewByCode(prompterr.CommonInvalidParamCode, errorx.WithExtraMsg("目前只支持jinja2模板类型"))
}

defer func() {
if err := recover(); err != nil {
logs.CtxError(ctx, "template validation panic, err=%v", err)
r.Code = 500
r.Msg = "Internal server error"
r.Data = &openapi.ValidateTemplateData{
IsValid: false,
ErrorMessage: "Template validation failed due to internal error",
}
}
}()

// 创建Jinja2引擎进行语法验证
engine := entity.NewJinja2Engine()

// 使用空变量进行语法验证
_, err := engine.Execute(req.GetTemplate(), map[string]interface{}{})

r.Code = 200
r.Msg = "Success"
r.Data = &openapi.ValidateTemplateData{
IsValid: err == nil,
}

if err != nil {
r.Data.ErrorMessage = err.Error()
logs.CtxInfo(ctx, "template validation failed, template=%s, error=%v", req.GetTemplate(), err)
}

return r, nil
}

// PreviewTemplate 预览Jinja2模板渲染结果
func (p *PromptOpenAPIApplicationImpl) PreviewTemplate(ctx context.Context, req *openapi.PreviewTemplateRequest) (*openapi.PreviewTemplateResponse, error) {
r := openapi.NewPreviewTemplateResponse()

// 参数验证
if req.GetTemplate() == "" {
return r, errorx.NewByCode(prompterr.CommonInvalidParamCode, errorx.WithExtraMsg("template参数不能为空"))
}

if req.GetTemplateType() != "jinja2" {
return r, errorx.NewByCode(prompterr.CommonInvalidParamCode, errorx.WithExtraMsg("目前只支持jinja2模板类型"))
}

defer func() {
if err := recover(); err != nil {
logs.CtxError(ctx, "template preview panic, err=%v", err)
r.Code = 500
r.Msg = "Internal server error"
r.Data = &openapi.PreviewTemplateData{
Result: "Template preview failed due to internal error",
}
}
}()

// 创建Jinja2引擎进行模板渲染
engine := entity.NewJinja2Engine()

// 转换变量类型
variables := make(map[string]interface{})
for key, value := range req.GetVariables() {
variables[key] = value
}

// 执行模板渲染
result, err := engine.Execute(req.GetTemplate(), variables)

r.Code = 200
r.Msg = "Success"

if err != nil {
r.Code = 400
r.Msg = "Template execution failed"
r.Data = &openapi.PreviewTemplateData{
Result: fmt.Sprintf("Error: %s", err.Error()),
}
logs.CtxError(ctx, "template preview failed, template=%s, variables=%v, error=%v", req.GetTemplate(), variables, err)
} else {
r.Data = &openapi.PreviewTemplateData{
Result: result,
}
logs.CtxInfo(ctx, "template preview success, template=%s, variables=%v, result_length=%d", req.GetTemplate(), variables, len(result))
}

return r, nil
}
Loading