Skip to content

Commit 30e7917

Browse files
committed
logger
1 parent 880abde commit 30e7917

File tree

6 files changed

+240
-9
lines changed

6 files changed

+240
-9
lines changed

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
.PHONY: help format clean build generate-client run deps tidy
22

3-
# Default target
43
.DEFAULT_GOAL := help
54

65
help: ## Show this help message

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ module github.com/JudgmentLabs/judgeval-go
33
go 1.25.1
44

55
require (
6-
github.com/joho/godotenv v1.5.1
6+
github.com/google/uuid v1.6.0
77
go.opentelemetry.io/otel v1.38.0
8+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0
89
go.opentelemetry.io/otel/sdk v1.38.0
910
go.opentelemetry.io/otel/trace v1.38.0
1011
)
@@ -13,11 +14,9 @@ require (
1314
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
1415
github.com/go-logr/logr v1.4.3 // indirect
1516
github.com/go-logr/stdr v1.2.2 // indirect
16-
github.com/google/uuid v1.6.0 // indirect
1717
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
1818
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
1919
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
20-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect
2120
go.opentelemetry.io/otel/metric v1.38.0 // indirect
2221
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
2322
golang.org/x/net v0.43.0 // indirect

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
77
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
88
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
99
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
10+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
11+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
1012
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
1113
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
1214
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
1315
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1416
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
1517
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
16-
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
17-
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
1818
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1919
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2020
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
@@ -45,6 +45,8 @@ golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
4545
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
4646
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
4747
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
48+
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
49+
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
4850
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
4951
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
5052
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=

pkg/logger/logger.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ import (
44
"fmt"
55
"os"
66
"strings"
7+
"time"
8+
)
9+
10+
const (
11+
RESET = "\033[0m"
12+
RED = "\033[31m"
13+
YELLOW = "\033[33m"
14+
GRAY = "\033[90m"
715
)
816

917
type Level int
@@ -24,10 +32,21 @@ var levelNames = map[Level]string{
2432
CRITICAL: "CRITICAL",
2533
}
2634

27-
var level = WARNING // Default to WARNING level
35+
var levelColors = map[Level]string{
36+
DEBUG: GRAY,
37+
INFO: GRAY,
38+
WARNING: YELLOW,
39+
ERROR: RED,
40+
CRITICAL: RED,
41+
}
42+
43+
var level = WARNING
44+
var useColor = true
2845

2946
func init() {
30-
// Set log level from environment variable
47+
noColor := os.Getenv("JUDGMENT_NO_COLOR")
48+
useColor = noColor == ""
49+
3150
if levelStr := os.Getenv("JUDGMENT_LOG_LEVEL"); levelStr != "" {
3251
SetLevelFromString(levelStr)
3352
}
@@ -37,6 +56,10 @@ func SetLevel(l Level) {
3756
level = l
3857
}
3958

59+
func SetUseColor(enableColor bool) {
60+
useColor = enableColor
61+
}
62+
4063
func SetLevelFromString(levelStr string) {
4164
switch strings.ToLower(levelStr) {
4265
case "debug":
@@ -60,7 +83,14 @@ func log(l Level, format string, args ...interface{}) {
6083
}
6184

6285
message := fmt.Sprintf(format, args...)
63-
fmt.Printf("[%s] %s\n", levelNames[l], message)
86+
timestamp := time.Now().Format("2006-01-02 15:04:05")
87+
formattedMessage := fmt.Sprintf("%s - judgeval - %s - %s", timestamp, levelNames[l], message)
88+
89+
if useColor {
90+
formattedMessage = levelColors[l] + formattedMessage + RESET
91+
}
92+
93+
fmt.Println(formattedMessage)
6494
}
6595

6696
func Debug(format string, args ...interface{}) {
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package prompt_scorer
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/JudgmentLabs/judgeval-go/pkg/data"
7+
"github.com/JudgmentLabs/judgeval-go/pkg/env"
8+
"github.com/JudgmentLabs/judgeval-go/pkg/internal/api"
9+
"github.com/JudgmentLabs/judgeval-go/pkg/internal/api/models"
10+
"github.com/JudgmentLabs/judgeval-go/pkg/scorers"
11+
)
12+
13+
type BasePromptScorer struct {
14+
*scorers.APIScorer
15+
prompt string
16+
options map[string]float64
17+
judgmentAPIKey string
18+
organizationID string
19+
}
20+
21+
func NewBasePromptScorer(
22+
scoreType data.APIScorerType,
23+
name string,
24+
prompt string,
25+
threshold float64,
26+
options map[string]float64,
27+
judgmentAPIKey string,
28+
organizationID string,
29+
) *BasePromptScorer {
30+
apiScorer := scorers.NewAPIScorer(scoreType, scorers.WithName(name), scorers.WithThreshold(threshold))
31+
32+
return &BasePromptScorer{
33+
APIScorer: apiScorer,
34+
prompt: prompt,
35+
options: options,
36+
judgmentAPIKey: judgmentAPIKey,
37+
organizationID: organizationID,
38+
}
39+
}
40+
41+
func ScorerExists(name, judgmentAPIKey, organizationID string) (bool, error) {
42+
client := api.NewClient(env.JudgmentAPIURL, judgmentAPIKey, organizationID)
43+
request := &models.ScorerExistsRequest{
44+
Name: name,
45+
}
46+
47+
response, err := client.ScorerExists(request)
48+
if err != nil {
49+
return false, fmt.Errorf("failed to check if scorer exists: %v", err)
50+
}
51+
52+
return response.Exists, nil
53+
}
54+
55+
func FetchPromptScorer(name, judgmentAPIKey, organizationID string) (*models.PromptScorer, error) {
56+
client := api.NewClient(env.JudgmentAPIURL, judgmentAPIKey, organizationID)
57+
request := &models.FetchPromptScorersRequest{
58+
Names: []string{name},
59+
}
60+
61+
response, err := client.FetchScorers(request)
62+
if err != nil {
63+
return nil, fmt.Errorf("failed to fetch prompt scorer '%s': %v", name, err)
64+
}
65+
66+
if len(response.Scorers) == 0 {
67+
return nil, fmt.Errorf("failed to fetch prompt scorer '%s': not found", name)
68+
}
69+
70+
return &response.Scorers[0], nil
71+
}
72+
73+
func PushPromptScorer(
74+
name string,
75+
prompt string,
76+
threshold float64,
77+
options map[string]float64,
78+
judgmentAPIKey string,
79+
organizationID string,
80+
isTrace bool,
81+
) (string, error) {
82+
client := api.NewClient(env.JudgmentAPIURL, judgmentAPIKey, organizationID)
83+
84+
apiOptions := make(map[string]interface{})
85+
for k, v := range options {
86+
apiOptions[k] = v
87+
}
88+
89+
request := &models.SavePromptScorerRequest{
90+
Name: name,
91+
Prompt: prompt,
92+
Threshold: threshold,
93+
Options: apiOptions,
94+
IsTrace: isTrace,
95+
}
96+
97+
response, err := client.SaveScorer(request)
98+
if err != nil {
99+
return "", fmt.Errorf("failed to save prompt scorer: %v", err)
100+
}
101+
102+
if response != nil {
103+
return response.Name, nil
104+
}
105+
return "", nil
106+
}
107+
108+
func (bps *BasePromptScorer) GetPrompt() string {
109+
return bps.prompt
110+
}
111+
112+
func (bps *BasePromptScorer) GetOptions() map[string]float64 {
113+
if bps.options == nil {
114+
return nil
115+
}
116+
result := make(map[string]float64)
117+
for k, v := range bps.options {
118+
result[k] = v
119+
}
120+
return result
121+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package prompt_scorer
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
7+
"github.com/JudgmentLabs/judgeval-go/pkg/data"
8+
"github.com/JudgmentLabs/judgeval-go/pkg/env"
9+
"github.com/JudgmentLabs/judgeval-go/pkg/internal/api/models"
10+
)
11+
12+
type PromptScorer struct {
13+
*BasePromptScorer
14+
}
15+
16+
func Get(name string) (*PromptScorer, error) {
17+
return GetWithCredentials(name, env.JudgmentAPIKey, env.JudgmentOrgID)
18+
}
19+
20+
func GetWithCredentials(name, judgmentAPIKey, organizationID string) (*PromptScorer, error) {
21+
scorerConfig, err := FetchPromptScorer(name, judgmentAPIKey, organizationID)
22+
if err != nil {
23+
return nil, err
24+
}
25+
26+
if scorerConfig.IsTrace {
27+
return nil, fmt.Errorf("scorer with name %s is not a PromptScorer", name)
28+
}
29+
30+
options := make(map[string]float64)
31+
if scorerConfig.Options != nil {
32+
if optionsMap, ok := scorerConfig.Options.(map[string]interface{}); ok {
33+
for k, v := range optionsMap {
34+
if num, ok := v.(float64); ok {
35+
options[k] = num
36+
} else if str, ok := v.(string); ok {
37+
if num, err := strconv.ParseFloat(str, 64); err == nil {
38+
options[k] = num
39+
}
40+
}
41+
}
42+
}
43+
}
44+
45+
threshold := 0.5
46+
if scorerConfig.Threshold != 0 {
47+
threshold = scorerConfig.Threshold
48+
}
49+
50+
return &PromptScorer{
51+
BasePromptScorer: NewBasePromptScorer(
52+
data.PromptScorer,
53+
name,
54+
scorerConfig.Prompt,
55+
threshold,
56+
options,
57+
judgmentAPIKey,
58+
organizationID,
59+
),
60+
}, nil
61+
}
62+
63+
func (ps *PromptScorer) GetScorerConfig() models.ScorerConfig {
64+
config := ps.BasePromptScorer.APIScorer.GetScorerConfig()
65+
66+
kwargs := make(map[string]interface{})
67+
kwargs["prompt"] = ps.GetPrompt()
68+
if ps.GetOptions() != nil {
69+
kwargs["options"] = ps.GetOptions()
70+
}
71+
72+
if ps.APIScorer.AdditionalProperties != nil {
73+
for k, v := range ps.APIScorer.AdditionalProperties {
74+
kwargs[k] = v
75+
}
76+
}
77+
78+
config.Kwargs = kwargs
79+
return config
80+
}

0 commit comments

Comments
 (0)