Compare commits

...

9 Commits

2 changed files with 82 additions and 9 deletions

View File

@@ -3,9 +3,11 @@ services:
build: .
environment:
BOT_TOKEN: ""
CHAT_ID: ""
OPENAI_BASE_URL: "http://localhost:8080/v1"
CHAT_ID: -1003268915330
CHANNEL_ID: -1003290014225
OPENAI_BASE_URL: http://llama-server:8080/v1
SYSTEM_PROMPT_PATH: /etc/sysprompt.txt
MAX_CONCURRENT_REQUESTS: 2
volumes:
- ./sysprompt.txt:/etc/sysprompt.txt:ro
restart: unless-stopped

85
main.go
View File

@@ -21,13 +21,52 @@ import (
type OpenAIPrompter struct {
cli openai.Client
cfg *Config
log *slog.Logger
}
func composeSysPromptWithContext(systemPrompt string, req PromptRequest) string {
var b strings.Builder
b.WriteString(systemPrompt)
b.WriteString("\nИмя пользователя: ")
b.WriteString(req.Username)
if req.ReplyToContent != nil {
b.WriteString("\nПользователь отсылается на текст сообщения: ")
b.WriteString(*req.ReplyToContent)
}
return b.String()
}
func (p *OpenAIPrompter) Prompt(ctx context.Context, req PromptRequest) (*HighlyTrustedResponse, error) {
p.log.Info("new prompt request",
"req", req)
sysPrompt := composeSysPromptWithContext(p.cfg.SystemPrompt, req)
input := []responses.ResponseInputItemUnionParam{
{
OfMessage: &responses.EasyInputMessageParam{
Content: responses.EasyInputMessageContentUnionParam{
OfString: openai.String(sysPrompt),
},
Role: responses.EasyInputMessageRoleSystem,
},
},
{
OfMessage: &responses.EasyInputMessageParam{
Content: responses.EasyInputMessageContentUnionParam{
OfString: openai.String(req.Question),
},
Role: responses.EasyInputMessageRoleUser,
},
},
}
func (p *OpenAIPrompter) Prompt(ctx context.Context, question string) (*HighlyTrustedResponse, error) {
resp, err := p.cli.Responses.New(ctx, responses.ResponseNewParams{
Instructions: openai.String(p.cfg.SystemPrompt),
Input: responses.ResponseNewParamsInputUnion{
OfString: openai.String(question),
OfInputItemList: input,
},
Reasoning: shared.ReasoningParam{
Effort: shared.ReasoningEffortXhigh,
@@ -42,12 +81,13 @@ func (p *OpenAIPrompter) Prompt(ctx context.Context, question string) (*HighlyTr
}, nil
}
func NewOpenAIProoooompter(cfg *Config) *OpenAIPrompter {
func NewOpenAIProoooompter(cfg *Config, log *slog.Logger) *OpenAIPrompter {
return &OpenAIPrompter{
cli: openai.NewClient(
option.WithBaseURL(cfg.OpenAIBaseURL),
),
cfg: cfg,
log: log,
}
}
@@ -55,8 +95,14 @@ type HighlyTrustedResponse struct {
Text string
}
type PromptRequest struct {
Username string
Question string
ReplyToContent *string
}
type Proompter interface {
Prompt(ctx context.Context, question string) (*HighlyTrustedResponse, error)
Prompt(ctx context.Context, req PromptRequest) (*HighlyTrustedResponse, error)
}
type App struct {
@@ -93,7 +139,22 @@ func (a *App) handleMessage(ctx context.Context, msg *tgbotapi.Message) error {
"transformed_text", question,
)
response, err := a.proompter.Prompt(ctx, question)
var repliedToContent *string
if msg.ReplyToMessage != nil {
a.log.Info("message was a reply")
repliedToContent = &msg.ReplyToMessage.Text
}
var username string
if msg.From != nil {
username = msg.From.UserName
}
response, err := a.proompter.Prompt(ctx, PromptRequest{
Question: question,
ReplyToContent: repliedToContent,
Username: username,
})
if err != nil {
return fmt.Errorf("prompting: %w", err)
}
@@ -166,6 +227,7 @@ type Config struct {
BotToken string
MaxConcurrentRequests uint
ChatID int64
ChannelID int64
}
func LoadConfig(cfg *Config) error {
@@ -197,6 +259,15 @@ func LoadConfig(cfg *Config) error {
cfg.ChatID = chatID
channelID, err := strconv.ParseInt(os.Getenv("CHANNEL_ID"), 10, 64)
if err != nil {
return err
}
if chatID == 0 {
slog.Warn("channel id is not set")
}
cfg.ChannelID = channelID
sysPromptPath := os.Getenv("SYSTEM_PROMPT_PATH")
promptBytes, err := os.ReadFile(sysPromptPath)
if err != nil {
@@ -221,7 +292,7 @@ func main() {
os.Exit(1)
}
prompter := NewOpenAIProoooompter(&cfg)
prompter := NewOpenAIProoooompter(&cfg, log)
app, err := NewApp(&cfg, prompter)
if err != nil {