Skip to content

Commit b92b0f9

Browse files
committed
Fix review comments
1 parent 25bcf16 commit b92b0f9

File tree

6 files changed

+207
-62
lines changed

6 files changed

+207
-62
lines changed

libs/acl/langfuse/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Langfuse ACL Extension
2+
3+
This module provides the Langfuse adapter used by Eino for event and prompt management against the Langfuse public API.
4+
5+
- `prompt.go` implements the prompt client, including typed request/response models and helpers to list, fetch, and create prompts.
6+
- A minimal usage sample lives in `examples/prompt/main.go`, showing how to initialize a Langfuse client and load a prompt by name.
7+
8+
Run `go test ./...` before submitting changes to ensure the package continues to build and the existing suites pass.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2025 CloudWeGo Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package examples
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"log"
23+
24+
"github.com/cloudwego/eino-ext/libs/acl/langfuse"
25+
)
26+
27+
func main() {
28+
ctx := context.Background()
29+
30+
lf := langfuse.NewLangfuse(
31+
"https://cloud.your-langfuse-instance.com",
32+
"your-public-key",
33+
"your-secret-key",
34+
)
35+
36+
promptClient := lf.Prompt()
37+
38+
prompt, err := promptClient.GetPrompt(ctx, langfuse.GetParams{
39+
Name: "welcome-message",
40+
})
41+
if err != nil {
42+
log.Fatalf("failed to fetch prompt: %v", err)
43+
}
44+
45+
fmt.Printf("Loaded prompt %q version %d\n", prompt.Name, prompt.Version)
46+
}

libs/acl/langfuse/go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ module github.com/cloudwego/eino-ext/libs/acl/langfuse
22

33
go 1.23.0
44

5-
65
require (
76
github.com/bytedance/mockey v1.2.13
8-
github.com/bytedance/sonic v1.13.2
7+
github.com/bytedance/sonic v1.14.1
98
github.com/cenkalti/backoff/v4 v4.3.0
109
github.com/cloudwego/eino v0.3.27
1110
github.com/golang/mock v1.6.0
1211
github.com/google/uuid v1.6.0
13-
github.com/stretchr/testify v1.9.0
12+
github.com/stretchr/testify v1.10.0
1413
)
1514

1615
require (
17-
github.com/bytedance/sonic/loader v0.2.4 // indirect
18-
github.com/cloudwego/base64x v0.1.5 // indirect
16+
github.com/bytedance/gopkg v0.1.3 // indirect
17+
github.com/bytedance/sonic/loader v0.3.0 // indirect
18+
github.com/cloudwego/base64x v0.1.6 // indirect
1919
github.com/davecgh/go-spew v1.1.1 // indirect
2020
github.com/dustin/go-humanize v1.0.1 // indirect
2121
github.com/getkin/kin-openapi v0.118.0 // indirect

libs/acl/langfuse/go.sum

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE
33
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
44
github.com/bugsnag/bugsnag-go v1.4.0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
55
github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
6+
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
7+
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
68
github.com/bytedance/mockey v1.2.13 h1:jokWZAm/pUEbD939Rhznz615MKUCZNuvCFQlJ2+ntoo=
79
github.com/bytedance/mockey v1.2.13/go.mod h1:1BPHF9sol5R1ud/+0VEHGQq/+i2lN+GTsr3O2Q9IENY=
8-
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
9-
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
10-
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
11-
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
12-
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
10+
github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w=
11+
github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc=
12+
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
13+
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
1314
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
1415
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
1516
github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
16-
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
17-
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
17+
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
18+
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
1819
github.com/cloudwego/eino v0.3.27 h1:Oz4HcuivJyb+zT0W43Gmtb6wqmXZaYel0CS4iF6XsoI=
1920
github.com/cloudwego/eino v0.3.27/go.mod h1:wUjz990apdsaOraOXdh6CdhVXq8DJsOvLsVlxNTcNfY=
20-
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
2121
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2222
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2323
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -57,10 +57,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
5757
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
5858
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
5959
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
60-
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
6160
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
6261
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
63-
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
6462
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
6563
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
6664
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -119,8 +117,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
119117
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
120118
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
121119
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
122-
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
123-
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
120+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
121+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
124122
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
125123
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
126124
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
@@ -183,4 +181,3 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
183181
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
184182
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
185183
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
186-
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=

libs/acl/langfuse/prompt.go

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ const (
3434
promptByNamePath = "/api/public/v2/prompts/"
3535
)
3636

37+
// PromptType enumerates supported prompt formats.
38+
type PromptType = string
39+
40+
const (
41+
PromptTypeText PromptType = "text"
42+
PromptTypeChat PromptType = "chat"
43+
)
44+
45+
// ChatMessageType enumerates supported chat message kinds.
46+
type ChatMessageType = string
47+
48+
const (
49+
ChatMessageTypeChatMessage ChatMessageType = "chatmessage"
50+
ChatMessageTypePlaceholder ChatMessageType = "placeholder"
51+
)
52+
3753
type ListMetadata struct {
3854
Page int `json:"page"`
3955
Limit int `json:"limit"`
@@ -47,12 +63,15 @@ type ListMetadata struct {
4763
// The Role field specifies the message role (e.g., "system", "user", "assistant"),
4864
// Type specifies the content type, and Content contains the message text with optional placeholders.
4965
type ChatMessageWithPlaceHolder struct {
50-
Role string `json:"role"`
51-
Type string `json:"type"`
52-
Content string `json:"content"`
66+
Role string `json:"role"`
67+
Type ChatMessageType `json:"type"`
68+
Content string `json:"content"`
5369
}
5470

5571
func (c *ChatMessageWithPlaceHolder) validate() error {
72+
if c.Type != ChatMessageTypeChatMessage && c.Type != ChatMessageTypePlaceholder {
73+
return fmt.Errorf("'type' must be either 'chatmessage' or 'placeholder'")
74+
}
5675
if c.Role == "" {
5776
return errors.New("'role' is required")
5877
}
@@ -65,17 +84,17 @@ func (c *ChatMessageWithPlaceHolder) validate() error {
6584
// PromptEntry represents a complete prompt template with its configuration and messages.
6685
//
6786
// A prompt entry contains the prompt name, which can be either a string (when Type is "text")
68-
// or an array of chat messages with placeholders (for other types).
69-
// The Type field determines the expected structure of the Prompt field.
87+
// or an array of chat messages with placeholders (when Type is "chat").
88+
// The Type field determines the expected structure of the Prompt field and must be either "text" or "chat".
7089
// The Config field can contain model-specific configuration parameters.
7190
type PromptEntry struct {
72-
Name string `json:"name"`
73-
Prompt any `json:"prompt"`
74-
Type string `json:"type"`
75-
Version int `json:"version,omitempty"`
76-
Tags []string `json:"tags,omitempty"`
77-
Labels []string `json:"labels,omitempty"`
78-
Config any `json:"config,omitempty"`
91+
Name string `json:"name"`
92+
Prompt any `json:"prompt"`
93+
Type PromptType `json:"type"`
94+
Version int `json:"version,omitempty"`
95+
Tags []string `json:"tags,omitempty"`
96+
Labels []string `json:"labels,omitempty"`
97+
Config any `json:"config,omitempty"`
7998
}
8099

81100
// UnmarshalJSON implements custom JSON unmarshalling for PromptEntry.
@@ -92,21 +111,24 @@ func (p *PromptEntry) UnmarshalJSON(data []byte) error {
92111
}{
93112
Alias: (*Alias)(p),
94113
}
95-
96114
if err := json.Unmarshal(data, temp); err != nil {
97115
return err
98116
}
99117

100-
if p.Type == "text" {
118+
if p.Type != PromptTypeText && p.Type != PromptTypeChat {
119+
return fmt.Errorf("'type' must be either 'text' or 'chat'")
120+
}
121+
122+
if p.Type == PromptTypeText {
101123
var promptStr string
102124
if err := json.Unmarshal(temp.Prompt, &promptStr); err != nil {
103125
return fmt.Errorf("failed to unmarshal prompt as string for type 'text': %w", err)
104126
}
105127
p.Prompt = promptStr
106-
} else {
128+
} else { // p.Type == "chat"
107129
var promptMessages []ChatMessageWithPlaceHolder
108130
if err := json.Unmarshal(temp.Prompt, &promptMessages); err != nil {
109-
return fmt.Errorf("failed to unmarshal prompt as []ChatMessageWithPlaceHolder for type '%s': %w", p.Type, err)
131+
return fmt.Errorf("failed to unmarshal prompt as []ChatMessageWithPlaceHolder for type '%s': %w", string(p.Type), err)
110132
}
111133
p.Prompt = promptMessages
112134
}
@@ -121,24 +143,30 @@ func (p *PromptEntry) validate() error {
121143
if p.Prompt == nil {
122144
return errors.New("'prompt' cannot be nil")
123145
}
146+
if p.Type == "" {
147+
return errors.New("'type' is required")
148+
}
149+
if p.Type != PromptTypeText && p.Type != PromptTypeChat {
150+
return errors.New("'type' must be either 'text' or 'chat'")
151+
}
124152

125153
// Validate based on Type field
126-
if p.Type == "text" {
154+
if p.Type == PromptTypeText {
127155
// For text type, prompt should be a string
128156
if str, ok := p.Prompt.(string); !ok || str == "" {
129157
return errors.New("'prompt' must be a non-empty string when type is 'text'")
130158
}
131-
} else {
132-
// For other types, prompt should be []ChatMessageWithPlaceHolder
159+
} else { // p.Type == PromptTypeChat
160+
// For chat type, prompt should be []ChatMessageWithPlaceHolder
133161
messages, ok := p.Prompt.([]ChatMessageWithPlaceHolder)
134162
if !ok {
135-
return errors.New("'prompt' must be []ChatMessageWithPlaceHolder when type is not 'text'")
163+
return errors.New("'prompt' must be []ChatMessageWithPlaceHolder when type is 'chat'")
136164
}
137165
if len(messages) == 0 {
138166
return errors.New("'prompt' cannot be empty")
139167
}
140-
for _, msg := range messages {
141-
if err := msg.validate(); err != nil {
168+
for i := range messages {
169+
if err := messages[i].validate(); err != nil {
142170
return fmt.Errorf("invalid prompts message: %w", err)
143171
}
144172
}

0 commit comments

Comments
 (0)