no brain command

This commit is contained in:
Christoph K.
2026-03-12 19:49:50 +01:00
parent 3c8d3873dc
commit e597617266
3 changed files with 81 additions and 17 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
bin/
config.yml
ask
discord

View File

@@ -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,19 +107,18 @@ 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)
registered, err := dg.ApplicationCommandBulkOverwrite(dg.State.User.ID, guildID, commands)
if err != nil {
log.Printf("⚠️ Slash-Command /%s konnte nicht registriert werden: %v", cmd.Name, err)
} else {
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)
}
}
}
func onInteraction(s *discordgo.Session, i *discordgo.InteractionCreate) {
if i.Type != discordgo.InteractionApplicationCommand {
@@ -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)

View File

@@ -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 }