no brain command
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
bin/
|
||||
config.yml
|
||||
ask
|
||||
discord
|
||||
|
||||
@@ -23,7 +23,19 @@ var (
|
||||
commands = []*discordgo.ApplicationCommand{
|
||||
{
|
||||
Name: "ask",
|
||||
Description: "Stelle eine Frage an deinen AI Brain",
|
||||
Description: "Stelle eine Frage an deinen AI Brain (mit Wissensdatenbank)",
|
||||
Options: []*discordgo.ApplicationCommandOption{
|
||||
{
|
||||
Type: discordgo.ApplicationCommandOptionString,
|
||||
Name: "frage",
|
||||
Description: "Die Frage, die du stellen möchtest",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "asknobrain",
|
||||
Description: "Stelle eine Frage direkt ans LLM (ohne Wissensdatenbank)",
|
||||
Options: []*discordgo.ApplicationCommandOption{
|
||||
{
|
||||
Type: discordgo.ApplicationCommandOptionString,
|
||||
@@ -95,17 +107,16 @@ func onReady(s *discordgo.Session, r *discordgo.Ready) {
|
||||
|
||||
func registerCommands() {
|
||||
guildID := config.Cfg.Discord.GuildID
|
||||
for _, cmd := range commands {
|
||||
_, err := dg.ApplicationCommandCreate(dg.State.User.ID, guildID, cmd)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ Slash-Command /%s konnte nicht registriert werden: %v", cmd.Name, err)
|
||||
} else {
|
||||
scope := "global"
|
||||
if guildID != "" {
|
||||
scope = "guild " + guildID
|
||||
}
|
||||
fmt.Printf("📝 Slash-Command /%s registriert (%s)\n", cmd.Name, scope)
|
||||
}
|
||||
registered, err := dg.ApplicationCommandBulkOverwrite(dg.State.User.ID, guildID, commands)
|
||||
if err != nil {
|
||||
log.Fatalf("❌ Slash-Commands konnten nicht registriert werden: %v", err)
|
||||
}
|
||||
scope := "global"
|
||||
if guildID != "" {
|
||||
scope = "guild " + guildID
|
||||
}
|
||||
for _, cmd := range registered {
|
||||
fmt.Printf("📝 Slash-Command /%s registriert (%s)\n", cmd.Name, scope)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +127,9 @@ func onInteraction(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
|
||||
switch i.ApplicationCommandData().Name {
|
||||
case "ask":
|
||||
handleAsk(s, i, i.ApplicationCommandData().Options[0].StringValue())
|
||||
handleAsk(s, i, i.ApplicationCommandData().Options[0].StringValue(), true)
|
||||
case "asknobrain":
|
||||
handleAsk(s, i, i.ApplicationCommandData().Options[0].StringValue(), false)
|
||||
case "ingest":
|
||||
handleIngest(s, i)
|
||||
case "remember":
|
||||
@@ -157,13 +170,22 @@ func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
s.ChannelMessageSendReply(m.ChannelID, reply, m.Reference())
|
||||
}
|
||||
|
||||
func handleAsk(s *discordgo.Session, i *discordgo.InteractionCreate, question string) {
|
||||
// Sofort mit "Denke nach..." antworten (Discord-Timeout: 3s)
|
||||
func handleAsk(s *discordgo.Session, i *discordgo.InteractionCreate, question string, useBrain bool) {
|
||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseDeferredChannelMessageWithSource,
|
||||
})
|
||||
|
||||
reply := queryAndFormat(question)
|
||||
var reply string
|
||||
if useBrain {
|
||||
reply = queryAndFormat(question)
|
||||
} else {
|
||||
answer, err := brain.ChatDirect(question)
|
||||
if err != nil {
|
||||
reply = fmt.Sprintf("❌ Fehler: %v", err)
|
||||
} else {
|
||||
reply = fmt.Sprintf("💬 **Antwort:** _%s_\n\n%s", question, answer)
|
||||
}
|
||||
}
|
||||
|
||||
s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
|
||||
Content: &reply,
|
||||
@@ -190,7 +212,14 @@ func handleRemember(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
})
|
||||
|
||||
text := i.ApplicationCommandData().Options[0].StringValue()
|
||||
author := i.Member.User.Username
|
||||
var author string
|
||||
if i.Member != nil {
|
||||
author = i.Member.User.Username
|
||||
} else if i.User != nil {
|
||||
author = i.User.Username
|
||||
} else {
|
||||
author = "unknown"
|
||||
}
|
||||
source := fmt.Sprintf("discord/#%s", i.ChannelID)
|
||||
|
||||
err := brain.IngestChatMessage(text, author, source)
|
||||
|
||||
@@ -169,4 +169,38 @@ func buildContext(chunks []KnowledgeChunk) string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// ChatDirect stellt eine Frage direkt an das LLM ohne Datenbankkontext.
|
||||
func ChatDirect(question string) (string, error) {
|
||||
ctx := context.Background()
|
||||
chatClient := config.NewChatClient()
|
||||
|
||||
systemPrompt := `Du bist ein hilfreicher persönlicher Assistent. Antworte auf Deutsch, präzise und direkt.`
|
||||
|
||||
stream, err := chatClient.CreateChatCompletionStream(ctx, openai.ChatCompletionRequest{
|
||||
Model: config.Cfg.Chat.Model,
|
||||
Messages: []openai.ChatCompletionMessage{
|
||||
{Role: openai.ChatMessageRoleSystem, Content: systemPrompt},
|
||||
{Role: openai.ChatMessageRoleUser, Content: question},
|
||||
},
|
||||
Temperature: 0.7,
|
||||
MaxTokens: 500,
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("LLM Fehler: %w", err)
|
||||
}
|
||||
defer stream.Close()
|
||||
|
||||
var answer strings.Builder
|
||||
for {
|
||||
response, err := stream.Recv()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if len(response.Choices) > 0 {
|
||||
answer.WriteString(response.Choices[0].Delta.Content)
|
||||
}
|
||||
}
|
||||
return answer.String(), nil
|
||||
}
|
||||
|
||||
func floatPtr(f float32) *float32 { return &f }
|
||||
|
||||
Reference in New Issue
Block a user