β οΈ Note: This project is under active development and currently supports only the Gemini LLM.
GoPilot is an intelligent automation library that enables natural language interaction with your Go functions. It automatically routes user queries to appropriate functions, manages parameter mapping, and manages execution flow - all through simple speech inputs.
- π€ Natural Language Processing: Process user queries in natural language
- π― Automatic Function Routing: Map queries to the most appropriate function
- π Type-Safe Parameter Mapping: Convert dynamic inputs to strongly-typed parameters
- π‘οΈ Validation Built-in: Automatic validation of required parameters
- π Easy Integration: Simple API for registering and executing functions
- π¨ Flexible Response Handling: Support for various response types and formats
go get github.com/SadikSunbul/gopilot
Here's a simple example that demonstrates how to use GoPilot:
package main
import (
"context"
"fmt"
"log"
"github.com/SadikSunbul/gopilot"
"github.com/SadikSunbul/gopilot/clients"
"github.com/SadikSunbul/gopilot/pkg/generator"
)
// Define your function parameters
type WeatherParams struct {
City string `json:"city" description:"The name of the city to get weather information for" required:"true"`
}
// Define your function response
type WeatherResponse struct {
City string `json:"city"`
Temp int `json:"temp"`
Condition string `json:"condition"`
}
// Implement your function logic
func GetWeather(params WeatherParams) (WeatherResponse, error) {
if params.City == "" {
return WeatherResponse{}, fmt.Errorf("city cannot be empty")
}
// Your weather API integration here
return WeatherResponse{
City: params.City,
Temp: 25,
Condition: "sunny",
}, nil
}
func main() {
// Initialize Gemini client
client, err := clients.NewGeminiClient(context.Background(), "your-api-key", "gemini-2.0-flash")
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Create GoPilot instance
gp, err := gopilot.NewGopilot(client)
if err != nil {
log.Fatal("failed to initialize gopilot:", err)
}
// Register your function
weatherFn := &gopilot.Function[WeatherParams, WeatherResponse]{
Name: "weather-agent",
Description: "Gets weather information for a specified city",
Parameters: generator.GenerateParameterSchema(WeatherParams{}),
Execute: GetWeather,
}
if err := gp.FunctionRegister(weatherFn); err != nil {
log.Fatal(err)
}
// Set system prompt (required)
gp.SetSystemPrompt(nil)
// Process user query
input := "What's the weather like in Istanbul?"
// Option 1: Generate and Execute separately
response, err := gp.Generate(input)
if err != nil {
log.Fatal(err)
}
result, err := gp.FunctionExecute(response.Agent, response.Parameters)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Result: %+v\n", result)
// Option 2: Generate and Execute in one step
result, err = gp.GenerateAndExecute(input)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Result: %+v\n", result)
}
GoPilot supports nested and complex parameter types:
type TranslateParams struct {
Text string `json:"text" description:"The text to translate" required:"true"`
Path struct {
From string `json:"from" description:"Source language code" required:"true"`
To string `json:"to" description:"Target language code" required:"true"`
Options struct {
Style string `json:"style" description:"Translation style"`
} `json:"options" description:"Additional options"`
} `json:"path" description:"Translation configuration" required:"true"`
}
type TranslateResponse struct {
Original string `json:"original"`
Translated string `json:"translated"`
From string `json:"from"`
To string `json:"to"`
Style string `json:"style,omitempty"`
}
func Translate(params TranslateParams) (TranslateResponse, error) {
// Your translation logic here
}
// Register the translation function
translateFn := &gopilot.Function[TranslateParams, TranslateResponse]{
Name: "translate-agent",
Description: "Translates text between languages",
Parameters: generator.GenerateParameterSchema(TranslateParams{}),
Execute: Translate,
}
Here's how to create an interactive CLI application:
reader := bufio.NewReader(os.Stdin)
fmt.Println("Welcome! Type 'exit' to exit.")
for {
fmt.Print("\nQuestion: ")
input, err := reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
input = strings.TrimSpace(input)
if input == "exit" {
break
}
result, err := gp.GenerateAndExecute(input)
if err != nil {
log.Printf("Error: %v\n", err)
continue
}
fmt.Printf("Result: %+v\n", result)
}
-
Parameter Validation
- Always validate required parameters
- Use descriptive error messages
- Add proper documentation using struct tags
-
Error Handling
- Return specific error types
- Handle both function-specific and system errors
- Provide context in error messages
-
Function Registration
- Use descriptive function names
- Provide clear function descriptions
- Document parameter requirements
-
Type Safety
- Use strongly-typed parameters and responses
- Leverage Go's type system for validation
- Avoid interface{} when possible
We welcome contributions! Please see our Contributing Guidelines for details.
For security concerns, please review our Security Policy.
This project is licensed under the MIT License - see the LICENSE file for details.
- π Documentation
- π Issue Tracker
- π¬ Discussions
- Thanks to all contributors who have helped shape GoPilot
- Special thanks to the Go community for their support and feedback