sync of changes
This commit is contained in:
		
							
								
								
									
										131
									
								
								cmd/answer.go
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								cmd/answer.go
									
									
									
									
									
								
							| @@ -1,15 +1,33 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"answer/pkg/answer" | ||||
| 	"answer/pkg/cache" | ||||
| 	"answer/pkg/search" | ||||
| 	"context" | ||||
| 	gollm "gitea.stevedudenhoeffer.com/steve/go-llm" | ||||
| 	"github.com/urfave/cli" | ||||
| 	"log/slog" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| func getKey(key string, env string) string { | ||||
| 	if key != "" { | ||||
| 		return key | ||||
| 	} | ||||
|  | ||||
| 	return os.Getenv(env) | ||||
| } | ||||
|  | ||||
| func main() { | ||||
| 	ctx := context.Background() | ||||
| 	// Usage: go run cmd/answer.go question... | ||||
| 	// - flags: | ||||
| 	//   --model=[model string such as openai/gpt-4o, anthropic/claude..., google/gemini-1.5.  Default: openai/gpt-4o] | ||||
| 	//   --search-provider=[search provider string such as google, duckduckgo.  Default: google] | ||||
| 	//	 --cache-provider=[cache provider string such as memory, redis, file.  Default: memory] | ||||
|  | ||||
| 	var app = cli.App{ | ||||
| 		Name:        "answer", | ||||
| @@ -17,20 +35,123 @@ func main() { | ||||
| 		Version:     "0.1", | ||||
| 		Description: "", | ||||
|  | ||||
| 		Flags: []cli.Flag{ | ||||
| 			&cli.StringFlag{ | ||||
| 				Name:  "model", | ||||
| 				Value: "openai/gpt-4o", | ||||
| 				Usage: "model to use for answering the question, syntax: provider/model such as openai/gpt-4o", | ||||
| 			}, | ||||
|  | ||||
| 			&cli.StringFlag{ | ||||
| 				Name:  "llm-key", | ||||
| 				Value: "", | ||||
| 				Usage: "key for the llm model (if empty, will use env var of PROVIDER_API_KEY, such as OPENAI_API_KEY)", | ||||
| 			}, | ||||
|  | ||||
| 			&cli.StringFlag{ | ||||
| 				Name:  "search-provider", | ||||
| 				Value: "google", | ||||
| 				Usage: "search provider to use for searching the web", | ||||
| 			}, | ||||
|  | ||||
| 			&cli.StringFlag{ | ||||
| 				Name:  "cache-provider", | ||||
| 				Value: "memory", | ||||
| 				Usage: "cache provider to use for caching search results", | ||||
| 			}, | ||||
| 		}, | ||||
|  | ||||
| 		Action: func(c *cli.Context) error { | ||||
| 			// if there is no question to answer, print usage | ||||
| 			if c.NArg() == 0 { | ||||
| 				return cli.ShowAppHelp(c) | ||||
| 			} | ||||
| 			var question answer.Question | ||||
|  | ||||
| 			// get the question | ||||
| 			fmt.Println("Head: ", c.Args().First()) | ||||
| 			fmt.Println("Tail: ", c.Args().Tail()) | ||||
| 			question.Question = strings.Join(c.Args(), " ") | ||||
|  | ||||
| 			switch c.String("cache-provider") { | ||||
| 			case "memory": | ||||
| 				panic("not implemented") | ||||
|  | ||||
| 			case "redis": | ||||
| 				panic("not implemented") | ||||
|  | ||||
| 			case "file": | ||||
| 				question.Cache = &cache.Directory{ | ||||
| 					BaseFolder: "cache", | ||||
| 					MaxLife:    1 * 24 * time.Hour, | ||||
| 				} | ||||
|  | ||||
| 			default: | ||||
| 				panic("unknown cache provider") | ||||
| 			} | ||||
|  | ||||
| 			if question.Cache == nil { | ||||
| 				panic("cache is nil") | ||||
| 			} | ||||
| 			// wrap the cache in a hasher | ||||
| 			question.Cache = cache.ShaWrapper{ | ||||
| 				Cache: question.Cache, | ||||
| 			} | ||||
|  | ||||
| 			switch c.String("search-provider") { | ||||
| 			case "google": | ||||
| 				question.Search = search.Google{Cache: question.Cache} | ||||
|  | ||||
| 			default: | ||||
| 				panic("unknown search provider") | ||||
| 			} | ||||
|  | ||||
| 			var llm gollm.LLM | ||||
|  | ||||
| 			model := c.String("model") | ||||
|  | ||||
| 			a := strings.Split(model, "/") | ||||
|  | ||||
| 			if len(a) != 2 { | ||||
| 				panic("invalid model, expected: provider/model (such as openai/gpt-4o)") | ||||
| 			} | ||||
|  | ||||
| 			switch a[0] { | ||||
| 			case "openai": | ||||
| 				llm = gollm.OpenAI(getKey(c.String("llm-key"), "OPENAI_API_KEY")) | ||||
|  | ||||
| 			case "anthropic": | ||||
| 				llm = gollm.Anthropic(getKey(c.String("llm-key"), "ANTHROPI_API_KEY")) | ||||
|  | ||||
| 			case "google": | ||||
| 				llm = gollm.Google(getKey(c.String("llm-key"), "GOOGLE_API_KEY")) | ||||
|  | ||||
| 			default: | ||||
| 				panic("unknown model provider") | ||||
| 			} | ||||
|  | ||||
| 			m, err := llm.ModelVersion(a[1]) | ||||
|  | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
|  | ||||
| 			question.Model = m | ||||
|  | ||||
| 			answers, err := answer.Answer(ctx, question) | ||||
|  | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
|  | ||||
| 			for i, a := range answers { | ||||
| 				slog.Info("answer", "index", i, "answer", a) | ||||
| 			} | ||||
|  | ||||
| 			return nil | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	app.Run() | ||||
| 	err := app.Run(os.Args) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		slog.Error("Error: ", err) | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user