Files
tell-me/main.go
Pavel Pivovarov 50a439a499 Initial commit
2025-12-12 11:15:02 +11:00

134 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"bufio"
"context"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"github.com/sashabaranov/go-openai"
"github.com/tell-me/config"
"github.com/tell-me/llm"
)
func main() {
// Load configuration
cfg, err := config.Load()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading configuration: %v\n", err)
fmt.Fprintf(os.Stderr, "Please create ~/.config/tell-me.ini from tell-me.ini.example\n")
os.Exit(1)
}
// Create LLM client
client := llm.NewClient(
cfg.LLM.APIURL,
cfg.LLM.APIKey,
cfg.LLM.Model,
cfg.LLM.ContextSize,
cfg.SearXNG.URL,
)
// Initialize conversation with system prompt
messages := []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleSystem,
Content: llm.GetSystemPrompt(),
},
}
ctx := context.Background()
// Check if arguments are provided (non-interactive mode)
if len(os.Args) > 1 {
query := strings.Join(os.Args[1:], " ")
processQuery(ctx, client, messages, query)
return
}
// Setup signal handling for Ctrl-C
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigChan
fmt.Println("\n\nGoodbye!")
os.Exit(0)
}()
// Print welcome message
fmt.Println("╔════════════════════════════════════════════════════════════════╗")
fmt.Println("║ Tell-Me CLI ║")
fmt.Println("║ AI-powered search with local LLM support ║")
fmt.Println("╚════════════════════════════════════════════════════════════════╝")
fmt.Println()
fmt.Printf("Using model: %s\n", cfg.LLM.Model)
fmt.Printf("SearXNG: %s\n", cfg.SearXNG.URL)
fmt.Println()
fmt.Println("Type your questions below. Type 'exit' or 'quit' to exit, or press Ctrl-C.")
fmt.Println("────────────────────────────────────────────────────────────────")
fmt.Println()
// Create scanner for user input
scanner := bufio.NewScanner(os.Stdin)
for {
// Prompt for user input
fmt.Print(" ")
if !scanner.Scan() {
break
}
userInput := strings.TrimSpace(scanner.Text())
// Check for exit commands
if userInput == "exit" || userInput == "quit" {
fmt.Println("\nGoodbye!")
break
}
// Skip empty input
if userInput == "" {
continue
}
// Process the query
messages = processQuery(ctx, client, messages, userInput)
}
if err := scanner.Err(); err != nil {
fmt.Fprintf(os.Stderr, "Error reading input: %v\n", err)
os.Exit(1)
}
}
// processQuery handles a single query and returns updated messages
func processQuery(ctx context.Context, client *llm.Client, messages []openai.ChatCompletionMessage, userInput string) []openai.ChatCompletionMessage {
// Add user message to conversation
messages = append(messages, openai.ChatCompletionMessage{
Role: openai.ChatMessageRoleUser,
Content: userInput,
})
// Get response from LLM
fmt.Println()
response, updatedMessages, err := client.Chat(ctx, messages)
if err != nil {
fmt.Fprintf(os.Stderr, "\nError: %v\n\n", err)
// Remove the failed user message
return messages[:len(messages)-1]
}
// Update messages with the full conversation history
messages = updatedMessages
// Print response with empty line before it
fmt.Println()
fmt.Println(response)
fmt.Println()
return messages
}