You've already forked grok
Compare commits
9 Commits
ff79cfd786
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| cf7bab2923 | |||
| d3c9a7984c | |||
| bc49bedde6 | |||
| a4f156eac7 | |||
| 6332aa3c19 | |||
| 21c46ff2c1 | |||
| e60555df02 | |||
| d16d8ed906 | |||
| 6e9c21328e |
@@ -3,9 +3,11 @@ services:
|
|||||||
build: .
|
build: .
|
||||||
environment:
|
environment:
|
||||||
BOT_TOKEN: ""
|
BOT_TOKEN: ""
|
||||||
CHAT_ID: ""
|
CHAT_ID: -1003268915330
|
||||||
OPENAI_BASE_URL: "http://localhost:8080/v1"
|
CHANNEL_ID: -1003290014225
|
||||||
|
OPENAI_BASE_URL: http://llama-server:8080/v1
|
||||||
SYSTEM_PROMPT_PATH: /etc/sysprompt.txt
|
SYSTEM_PROMPT_PATH: /etc/sysprompt.txt
|
||||||
|
MAX_CONCURRENT_REQUESTS: 2
|
||||||
volumes:
|
volumes:
|
||||||
- ./sysprompt.txt:/etc/sysprompt.txt:ro
|
- ./sysprompt.txt:/etc/sysprompt.txt:ro
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
85
main.go
85
main.go
@@ -21,13 +21,52 @@ import (
|
|||||||
type OpenAIPrompter struct {
|
type OpenAIPrompter struct {
|
||||||
cli openai.Client
|
cli openai.Client
|
||||||
cfg *Config
|
cfg *Config
|
||||||
|
log *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *OpenAIPrompter) Prompt(ctx context.Context, question string) (*HighlyTrustedResponse, error) {
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := p.cli.Responses.New(ctx, responses.ResponseNewParams{
|
resp, err := p.cli.Responses.New(ctx, responses.ResponseNewParams{
|
||||||
Instructions: openai.String(p.cfg.SystemPrompt),
|
|
||||||
Input: responses.ResponseNewParamsInputUnion{
|
Input: responses.ResponseNewParamsInputUnion{
|
||||||
OfString: openai.String(question),
|
OfInputItemList: input,
|
||||||
},
|
},
|
||||||
Reasoning: shared.ReasoningParam{
|
Reasoning: shared.ReasoningParam{
|
||||||
Effort: shared.ReasoningEffortXhigh,
|
Effort: shared.ReasoningEffortXhigh,
|
||||||
@@ -42,12 +81,13 @@ func (p *OpenAIPrompter) Prompt(ctx context.Context, question string) (*HighlyTr
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOpenAIProoooompter(cfg *Config) *OpenAIPrompter {
|
func NewOpenAIProoooompter(cfg *Config, log *slog.Logger) *OpenAIPrompter {
|
||||||
return &OpenAIPrompter{
|
return &OpenAIPrompter{
|
||||||
cli: openai.NewClient(
|
cli: openai.NewClient(
|
||||||
option.WithBaseURL(cfg.OpenAIBaseURL),
|
option.WithBaseURL(cfg.OpenAIBaseURL),
|
||||||
),
|
),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,8 +95,14 @@ type HighlyTrustedResponse struct {
|
|||||||
Text string
|
Text string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PromptRequest struct {
|
||||||
|
Username string
|
||||||
|
Question string
|
||||||
|
ReplyToContent *string
|
||||||
|
}
|
||||||
|
|
||||||
type Proompter interface {
|
type Proompter interface {
|
||||||
Prompt(ctx context.Context, question string) (*HighlyTrustedResponse, error)
|
Prompt(ctx context.Context, req PromptRequest) (*HighlyTrustedResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
@@ -93,7 +139,22 @@ func (a *App) handleMessage(ctx context.Context, msg *tgbotapi.Message) error {
|
|||||||
"transformed_text", question,
|
"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 {
|
if err != nil {
|
||||||
return fmt.Errorf("prompting: %w", err)
|
return fmt.Errorf("prompting: %w", err)
|
||||||
}
|
}
|
||||||
@@ -166,6 +227,7 @@ type Config struct {
|
|||||||
BotToken string
|
BotToken string
|
||||||
MaxConcurrentRequests uint
|
MaxConcurrentRequests uint
|
||||||
ChatID int64
|
ChatID int64
|
||||||
|
ChannelID int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig(cfg *Config) error {
|
func LoadConfig(cfg *Config) error {
|
||||||
@@ -197,6 +259,15 @@ func LoadConfig(cfg *Config) error {
|
|||||||
|
|
||||||
cfg.ChatID = chatID
|
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")
|
sysPromptPath := os.Getenv("SYSTEM_PROMPT_PATH")
|
||||||
promptBytes, err := os.ReadFile(sysPromptPath)
|
promptBytes, err := os.ReadFile(sysPromptPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -221,7 +292,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
prompter := NewOpenAIProoooompter(&cfg)
|
prompter := NewOpenAIProoooompter(&cfg, log)
|
||||||
|
|
||||||
app, err := NewApp(&cfg, prompter)
|
app, err := NewApp(&cfg, prompter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user