From 3801ffb744f03f82fc5b1c3d9bf041b1ccc3922e Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Thu, 20 Mar 2025 14:16:32 +0800 Subject: [PATCH] feat: load .env file from current working directory upward recursively --- internal/version/VERSION | 2 +- uixt/ai/env.go | 52 +++++++++++++++++++++++++++++++--------- uixt/ai/planner.go | 3 ++- uixt/ai/planner_test.go | 2 +- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/internal/version/VERSION b/internal/version/VERSION index 8fb242b1..28bf2276 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503192247 +v5.0.0-beta-2503201423 diff --git a/uixt/ai/env.go b/uixt/ai/env.go index ebb7fb2a..c089a89d 100644 --- a/uixt/ai/env.go +++ b/uixt/ai/env.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "os" + "path/filepath" "strconv" "time" @@ -31,6 +32,46 @@ const ( EnvOpenAIInitConfigJSON = "OPENAI_INIT_CONFIG_JSON" ) +func init() { + err := loadEnv() + if err != nil { + log.Warn().Err(err).Msg("load .env file failed") + } +} + +// loadEnv loads environment variables from .env file +// it will search for .env file from current working directory upward recursively +func loadEnv() error { + // get current working directory + cwd, err := os.Getwd() + if err != nil { + return fmt.Errorf("failed to get current working directory: %v", err) + } + + // locate .env file from current working directory upward recursively + envPath := cwd + for { + envFile := filepath.Join(envPath, ".env") + if _, err := os.Stat(envFile); err == nil { + // found .env file + // override existing env variables + err = godotenv.Overload(envFile) + if err != nil { + return fmt.Errorf("failed to load env file: %v", err) + } + log.Info().Str("path", envFile).Msg("load env success") + return nil + } + + // reached root directory + parent := filepath.Dir(envPath) + if parent == envPath { + return fmt.Errorf("no .env file found from current directory to root") + } + envPath = parent + } +} + func checkEnvLLM() error { openaiBaseURL := os.Getenv("OPENAI_BASE_URL") if openaiBaseURL == "" { @@ -50,17 +91,6 @@ func checkEnvLLM() error { return nil } -// loadEnv loads environment variables from a file -func loadEnv(envPath string) error { - err := godotenv.Load(envPath) - if err != nil { - return err - } - - log.Info().Str("path", envPath).Msg("load env success") - return nil -} - func GetEnvConfig(key string) string { return os.Getenv(key) } diff --git a/uixt/ai/planner.go b/uixt/ai/planner.go index 6aa3f672..d3e1fb26 100644 --- a/uixt/ai/planner.go +++ b/uixt/ai/planner.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/cloudwego/eino-ext/components/model/openai" + "github.com/cloudwego/eino/components/model" "github.com/cloudwego/eino/schema" "github.com/pkg/errors" "github.com/rs/zerolog/log" @@ -44,7 +45,7 @@ func NewPlanner(ctx context.Context) (*Planner, error) { type Planner struct { ctx context.Context - model *openai.ChatModel + model model.ChatModel parser *ActionParser } diff --git a/uixt/ai/planner_test.go b/uixt/ai/planner_test.go index 0eb506e3..cfad75b7 100644 --- a/uixt/ai/planner_test.go +++ b/uixt/ai/planner_test.go @@ -25,7 +25,7 @@ func TestVLMPlanning(t *testing.T) { 5. 得分机制: 每成功连接并消除一对图案,玩家会获得相应的分数。完成游戏后,根据剩余时间和消除效率计算总分。 6. 关卡设计: 游戏可能包含多个关卡,随着关卡的推进,图案的复杂度和数量会增加。` - userInstruction += "\n\n请基于以上游戏规则,给出消除所有图案的行动序列" + userInstruction += "\n\n请基于以上游戏规则,请依次点击两个可消除的相同图案" planner, err := NewPlanner(context.Background()) require.NoError(t, err)