Skip to content

Commit a71e91b

Browse files
authored
chore: optimize (#8)
1 parent 3a4744a commit a71e91b

File tree

2 files changed

+74
-21
lines changed

2 files changed

+74
-21
lines changed

internal/adapters/http/handler.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package http
33
import (
44
"log/slog"
55
"net/http"
6+
"regexp"
7+
"strings"
68

79
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
810
"github.com/nduyhai/valjean/internal/infra/config"
@@ -43,7 +45,7 @@ func (h *Handler) WebHook(c *gin.Context) {
4345
MessageID: upd.Message.MessageID,
4446
UserID: upd.Message.From.ID,
4547
UserHandle: upd.Message.From.UserName,
46-
Text: upd.Message.Text,
48+
Text: h.cleanMention(upd.Message.Text, h.config.Telegram.BotUsername),
4749
ContextSnips: h.extractContextSnips(upd),
4850
ChatType: upd.Message.Chat.Type,
4951
ReplyFor: h.getReplyUserName(upd),
@@ -94,3 +96,13 @@ func (h *Handler) extractContextSnips(upd tgbotapi.Update) []string {
9496
}
9597
return nil
9698
}
99+
100+
func (h *Handler) cleanMention(text, botUsername string) string {
101+
if text == "" || botUsername == "" {
102+
return text
103+
}
104+
re := regexp.MustCompile(`(?i)@` + regexp.QuoteMeta(botUsername) + `\b`)
105+
cleaned := re.ReplaceAllString(text, "")
106+
cleaned = strings.TrimSpace(strings.Join(strings.Fields(cleaned), " "))
107+
return cleaned
108+
}

internal/adapters/llm/openai/openai.go

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package openai
33
import (
44
"context"
55
"log/slog"
6+
"strings"
67

78
"github.com/nduyhai/valjean/internal/app/entities"
89
goopenai "github.com/openai/openai-go/v3"
@@ -19,42 +20,82 @@ func NewClient(ai goopenai.Client, logger *slog.Logger) *Client {
1920

2021
func (c *Client) Evaluate(ctx context.Context, in entities.EvalInput) (entities.EvalOutput, error) {
2122

22-
// Combine context snippets with the main message
23-
var fullMessage string
24-
if len(in.ContextSnips) > 0 {
25-
fullMessage = "Context:\n"
26-
for _, contextText := range in.ContextSnips {
27-
if contextText != "" {
28-
fullMessage += contextText + "\n"
23+
// 1) Select & compress context
24+
ctxSnips := uniqueNonEmpty(in.ContextSnips)
25+
if len(ctxSnips) > 3 {
26+
ctxSnips = ctxSnips[len(ctxSnips)-3:] // keep last 3
27+
}
28+
for i := range ctxSnips {
29+
ctxSnips[i] = truncateRunes(strings.TrimSpace(ctxSnips[i]), 240)
30+
}
31+
32+
// 2) Build compact prompt
33+
// ctx lines as "- ..."; then Q: <message>
34+
var b strings.Builder
35+
if len(ctxSnips) > 0 {
36+
for _, s := range ctxSnips {
37+
if s != "" {
38+
b.WriteString("- ")
39+
b.WriteString(s)
40+
b.WriteByte('\n')
2941
}
3042
}
31-
fullMessage += "\nUser message:\n" + in.Text
32-
} else {
33-
fullMessage = in.Text
43+
b.WriteByte('\n')
3444
}
45+
b.WriteString("Q: ")
46+
b.WriteString(strings.TrimSpace(in.Text))
47+
userPrompt := b.String()
3548

49+
// 3) Messages: short system + one user
3650
messages := []goopenai.ChatCompletionMessageParamUnion{
37-
goopenai.UserMessage(fullMessage),
51+
goopenai.SystemMessage("You are concise. Answer ≤60 words. If uncertain, say so briefly."),
52+
goopenai.UserMessage(userPrompt),
3853
}
3954

55+
// 4) Call with a small model & caps
4056
chatCompletion, err := c.ai.Chat.Completions.New(ctx, goopenai.ChatCompletionNewParams{
41-
Messages: messages,
42-
Model: goopenai.ChatModelGPT4o,
57+
Messages: messages,
58+
Model: goopenai.ChatModelGPT4oMini, // cheaper than 4o
59+
MaxTokens: goopenai.Int(120), // cap output tokens
60+
Temperature: goopenai.Float(0.2),
4361
})
4462

4563
msg := "Please try again"
4664
if err != nil {
47-
return entities.EvalOutput{
48-
Summary: msg,
49-
}, err
65+
return entities.EvalOutput{Summary: msg}, err
5066
}
51-
52-
if length := len(chatCompletion.Choices); length > 0 {
53-
msg = chatCompletion.Choices[0].Message.Content
67+
if len(chatCompletion.Choices) > 0 && chatCompletion.Choices[0].Message.Content != "" {
68+
msg = strings.TrimSpace(chatCompletion.Choices[0].Message.Content)
5469
}
5570
return entities.EvalOutput{
5671
Summary: msg,
57-
Citations: []string{"Citation"},
72+
Citations: nil,
5873
Confidence: 80,
5974
}, nil
6075
}
76+
77+
func uniqueNonEmpty(ss []string) []string {
78+
seen := make(map[string]struct{}, len(ss))
79+
out := make([]string, 0, len(ss))
80+
for _, s := range ss {
81+
s = strings.TrimSpace(s)
82+
if s == "" {
83+
continue
84+
}
85+
key := strings.ToLower(s) // or hash/fingerprint
86+
if _, ok := seen[key]; ok {
87+
continue
88+
}
89+
seen[key] = struct{}{}
90+
out = append(out, s)
91+
}
92+
return out
93+
}
94+
95+
func truncateRunes(s string, max int) string {
96+
rs := []rune(s)
97+
if len(rs) <= max {
98+
return s
99+
}
100+
return string(rs[:max]) + "…"
101+
}

0 commit comments

Comments
 (0)