diff --git a/cmd/platform/ioc/llm.go b/cmd/platform/ioc/llm.go index 7a004a0..d83b9e0 100644 --- a/cmd/platform/ioc/llm.go +++ b/cmd/platform/ioc/llm.go @@ -45,9 +45,10 @@ func InitFunctionCallRegistry( askUser *fcall.AskUserFunctionCall, emitJSON *fcall.EmitJsonFunctionCall, invokeLLM *fcall.InvokeLLMFuncCall, + genDocs *fcall.GenDocFunctionCall, ) *fcall.Registry { registry := fcall.NewFunctionCallRegistry() - fcs := []fcall.FunctionCall{askUser, emitJSON, invokeLLM} + fcs := []fcall.FunctionCall{askUser, emitJSON, invokeLLM, genDocs} for i := range fcs { err := registry.Register(fcs[i]) if err != nil { diff --git a/cmd/platform/ioc/type.go b/cmd/platform/ioc/type.go index 74cad70..0a022e5 100644 --- a/cmd/platform/ioc/type.go +++ b/cmd/platform/ioc/type.go @@ -72,6 +72,7 @@ var ( fcall.NewInvokeLLMFuncCall, fcall.NewEmitJsonFunctionCall, fcall.NewAskUserFunctionCall, + fcall.NewGenDocFunctionCall, InitFunctionCallRegistry, ) diff --git a/cmd/platform/ioc/wire_gen.go b/cmd/platform/ioc/wire_gen.go index 7a19008..c0f05c8 100644 --- a/cmd/platform/ioc/wire_gen.go +++ b/cmd/platform/ioc/wire_gen.go @@ -30,7 +30,8 @@ func InitApp() *App { emitJsonFunctionCall := fcall.NewEmitJsonFunctionCall() defaultRender := InitRender() invokeLLMFuncCall := fcall.NewInvokeLLMFuncCall(invocationConfigRepo, defaultRender) - registry := InitFunctionCallRegistry(askUserFunctionCall, emitJsonFunctionCall, invokeLLMFuncCall) + genDocFunctionCall := fcall.NewGenDocFunctionCall() + registry := InitFunctionCallRegistry(askUserFunctionCall, emitJsonFunctionCall, invokeLLMFuncCall, genDocFunctionCall) handler := InitLLMHandler(registry) quotaDao := dao.NewQuotaDao(db) quotaRepo := repository.NewQuotaRepo(quotaDao) diff --git a/internal/service/llm/fcall/fcall_gen_doc.go b/internal/service/llm/fcall/fcall_gen_doc.go new file mode 100644 index 0000000..32af46c --- /dev/null +++ b/internal/service/llm/fcall/fcall_gen_doc.go @@ -0,0 +1,51 @@ +package fcall + +import ( + "github.com/goccy/go-json" +) + +type GenDocFunctionCall struct{} + +func NewGenDocFunctionCall() *GenDocFunctionCall { + return &GenDocFunctionCall{} +} + +func (e *GenDocFunctionCall) Name() string { + return NameGenDoc +} + +const jsonDataNameDocs = "doc" + +func (e *GenDocFunctionCall) Call(ctx *Context, req Request) (Response, error) { + d, err := req.GetArg(jsonDataNameDocs) + if err != nil { + return Response{}, err + } + var doc Doc + err = json.Unmarshal([]byte(d), &doc) + if err != nil { + return Response{}, err + } + var content string + switch doc.Type { + case DocMarkDown: + content = doc.Content + case DocPDF: + //todo: 将对应的 markdown 格式渲染成为对应的 pdf + default: + } + ctx.SetAttachment(e.Name(), content) + return Response{}, nil +} + +type Doc struct { + Content string `json:"content"` + Type DocType `json:"type"` +} + +type DocType string + +const ( + DocMarkDown = "markdown" + DocPDF = "pdf" +) diff --git a/internal/service/llm/fcall/type.go b/internal/service/llm/fcall/type.go index 238f6c5..a6e82da 100644 --- a/internal/service/llm/fcall/type.go +++ b/internal/service/llm/fcall/type.go @@ -15,6 +15,7 @@ const ( NameAskUser = "ask_user" NameEmitJSON = "emit_json" NameInvokeLLM = "invoke_llm" + NameGenDoc = "gen_doc" ) //go:generate mockgen -source=./type.go -package=mocks -destination=./mocks/fcall.mock.go -typed FunctionCall diff --git a/internal/test/chat_test.go b/internal/test/chat_test.go index 51ec02e..aef6253 100644 --- a/internal/test/chat_test.go +++ b/internal/test/chat_test.go @@ -34,6 +34,8 @@ var ( emitJSON string //go:embed testdata/invoke_llm.json invokeLLMJSON string + //go:embed testdata/gen_doc.json + genDocJSON string //go:embed testdata/resume_json_schema.json resumeJSONSchema string //go:embed testdata/resume_xiaoming.md @@ -83,6 +85,7 @@ func (s *ChatTestSuite) SetupSuite() { fcall.NewAskUserFunctionCall(), fcall.NewEmitJsonFunctionCall(), invokeLLMCall, + fcall.NewGenDocFunctionCall(), ) s.client = openai.NewClient( @@ -178,7 +181,7 @@ func (s *ChatTestSuite) TestUnmarshalFunctionToolParam() { t := s.T() t.Skip("测试定义的Function Definition是否能够被正确反序列化") var p responses.FunctionToolParam - for _, str := range []string{askUserJSON, emitJSON, invokeLLMJSON} { + for _, str := range []string{askUserJSON, emitJSON, invokeLLMJSON, genDocJSON} { // t.Logf("json_str: %s\n", str) err := json.Unmarshal([]byte(str), &p) require.NoError(t, err) @@ -704,6 +707,10 @@ func (s *ChatTestSuite) TestChatService_Stream() { Name: fcall.NameInvokeLLM, Definition: invokeLLMJSON, }, + { + Name: fcall.NameGenDoc, + Definition: genDocJSON, + }, }, Temperature: 0, TopP: 0, diff --git a/internal/test/ioc/wire_gen.go b/internal/test/ioc/wire_gen.go index 3576ca2..effd03f 100644 --- a/internal/test/ioc/wire_gen.go +++ b/internal/test/ioc/wire_gen.go @@ -53,7 +53,8 @@ func InitApp(to TestOnly) *TestApp { invokeLLMFuncCall := fcall.NewInvokeLLMFuncCall(invocationConfigRepo, defaultRender) askUserFunctionCall := fcall.NewAskUserFunctionCall() emitJsonFunctionCall := fcall.NewEmitJsonFunctionCall() - registry := ioc.InitFunctionCallRegistry(askUserFunctionCall, emitJsonFunctionCall, invokeLLMFuncCall) + genDocFunctionCall := fcall.NewGenDocFunctionCall() + registry := ioc.InitFunctionCallRegistry(askUserFunctionCall, emitJsonFunctionCall, invokeLLMFuncCall, genDocFunctionCall) testApp := &TestApp{ GrpcSever: component, GinServer: eginComponent, diff --git a/internal/test/testdata/gen_doc.json b/internal/test/testdata/gen_doc.json new file mode 100644 index 0000000..5a2c05f --- /dev/null +++ b/internal/test/testdata/gen_doc.json @@ -0,0 +1,28 @@ +{ + "type": "function", + "name": "gen_doc", + "description": "根据输入的内容生成对应的格式化文档", + "strict": true, + "parameters": { + "type": "object", + "properties": { + "doc": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "文档类型 比如markdown" + }, + "content": { + "type": "string", + "description": "文档的具体内容" + } + }, + "required": ["type", "content"], + "additionalProperties": false + } + }, + "required": ["doc"], + "additionalProperties": false + } +} \ No newline at end of file