From 8a200e2bcdf67c2a929d5b773e110bb28a62fb12 Mon Sep 17 00:00:00 2001 From: "z.to" Date: Sat, 28 Mar 2026 23:19:13 +0800 Subject: [PATCH] initial: project structure and documentation setup - Create project directory structure - Initialize Go module - Set up development documentation (why.md, taolun.md, changelog.md, memory.md, AGENTS.md) - Configure YAML config template - Set up .gitignore and .env.example - Design OOP architecture with factory and strategy patterns Version: 0.0.1 --- .env.example | 13 + .gitignore | 37 +++ AGENTS.md | 767 ++++++++++++++++++++++++++++++++++++++++++++ changelog.md | 85 +++++ configs/config.yaml | 43 +++ go.mod | 3 + memory.md | 166 ++++++++++ taolun.md | 88 +++++ why.md | 33 ++ 9 files changed, 1235 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 changelog.md create mode 100644 configs/config.yaml create mode 100644 go.mod create mode 100644 memory.md create mode 100644 taolun.md create mode 100644 why.md diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7eaaa4a --- /dev/null +++ b/.env.example @@ -0,0 +1,13 @@ +# YOYO翻译工具环境变量配置 +# 复制此文件为.env并填入您的API密钥 + +# 大模型API配置 +SILICONFLOW_API_KEY=your_siliconflow_api_key +VOLCANO_API_KEY=your_volcano_api_key +NATIONAL_API_KEY=your_national_api_key +QWEN_API_KEY=your_qwen_api_key +OPENAI_API_KEY=your_openai_api_key + +# 应用配置(可选) +YOYO_DEFAULT_PROVIDER=siliconflow +YOYO_TIMEOUT=30 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e86e3ed --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# 二进制文件 +yoyo +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# 测试 +*.test +*.out +coverage.txt + +# 配置文件(敏感信息) +.env +config.local.yaml + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# 依赖 +vendor/ + +# 构建输出 +dist/ +build/ + +# Go工作区 +go.work +go.work.sum + +# 本地配置文件 +configs/local.yaml +configs/*.local.yaml \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4f4db99 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,767 @@ +# AGENTS.md - YOYO翻译工具开发指南 + +## 项目概述 +YOYO是一个命令行翻译工具,使用Go语言编写,采用面向对象设计模式。它通过调用在线大模型API,结合不同的Prompt配置,实现多样化的翻译特色。 + +## OOP设计模式 + +### 核心类设计 +项目采用以下面向对象设计,结合工厂模式和策略模式: + +``` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ Config │ │ Provider │ │ Translator │ +│ (全局配置) │──────│ (厂商接口) │──────│ (核心翻译) │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ │ │ + │ │ │ +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ ConfigLoader │ │ ProviderFactory │ │ TranslationTask │ +│ (配置加载) │ │ (工厂模式) │ │ (任务管理) │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ +``` + +### 1. 全局配置类 (Config) +负责读取YAML配置文件,提供默认值。 + +```go +// internal/config/config.go +package config + +import ( + "os" + "path/filepath" + + "gopkg.in/yaml.v3" +) + +// Config 全局配置结构 +type Config struct { + // 全局设置 + DefaultProvider string `yaml:"default_provider"` + DefaultModel string `yaml:"default_model"` + Timeout int `yaml:"timeout"` // 秒 + + // 厂商配置 + Providers map[string]ProviderConfig `yaml:"providers"` + + // Prompt配置 + Prompts map[string]string `yaml:"prompts"` +} + +// ProviderConfig 厂商配置 +type ProviderConfig struct { + APIHost string `yaml:"api_host"` + APIKey string `yaml:"api_key"` + Model string `yaml:"model"` + Enabled bool `yaml:"enabled"` +} + +// ConfigLoader 配置加载器接口 +type ConfigLoader interface { + Load(path string) (*Config, error) + Save(config *Config, path string) error +} + +// YAMLConfigLoader YAML配置加载器实现 +type YAMLConfigLoader struct{} + +// Load 加载YAML配置文件 +func (l *YAMLConfigLoader) Load(path string) (*Config, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("读取配置文件失败: %w", err) + } + + config := &Config{} + if err := yaml.Unmarshal(data, config); err != nil { + return nil, fmt.Errorf("解析配置文件失败: %w", err) + } + + // 设置默认值 + config.setDefaults() + return config, nil +} + +// setDefaults 设置默认值 +func (c *Config) setDefaults() { + if c.DefaultProvider == "" { + c.DefaultProvider = "siliconflow" + } + if c.Timeout <= 0 { + c.Timeout = 30 + } + // 为每个厂商设置默认值 + for name, provider := range c.Providers { + if provider.Model == "" { + provider.Model = "gpt-3.5-turbo" + c.Providers[name] = provider + } + } +} +``` + +### 2. 大模型厂商接口 (Provider) +定义统一的厂商接口,采用策略模式。 + +```go +// internal/provider/provider.go +package provider + +import ( + "context" +) + +// Provider 厂商接口 +type Provider interface { + // Translate 调用厂商API进行翻译 + Translate(ctx context.Context, req *TranslateRequest) (*TranslateResponse, error) + + // Name 返回厂商名称 + Name() string + + // Validate 验证配置是否有效 + Validate() error +} + +// TranslateRequest 翻译请求 +type TranslateRequest struct { + Text string `json:"text"` + FromLang string `json:"from_lang"` + ToLang string `json:"to_lang"` + Prompt string `json:"prompt"` + Model string `json:"model"` + Options map[string]interface{} `json:"options"` +} + +// TranslateResponse 翻译响应 +type TranslateResponse struct { + Text string `json:"text"` + FromLang string `json:"from_lang"` + ToLang string `json:"to_lang"` + Model string `json:"model"` + Usage *Usage `json:"usage"` + RawResponse []byte `json:"raw_response,omitempty"` +} + +// Usage 用量统计 +type Usage struct { + PromptTokens int `json:"prompt_tokens"` + CompletionTokens int `json:"completion_tokens"` + TotalTokens int `json:"total_tokens"` +} +``` + +### 3. 具体厂商实现示例 + +```go +// internal/provider/siliconflow.go +package provider + +import ( + "context" + "encoding/json" + "net/http" +) + +// SiliconFlowProvider 硅基流动厂商实现 +type SiliconFlowProvider struct { + config ProviderConfig + client *http.Client +} + +// ProviderConfig 厂商配置(从config包导入) +type ProviderConfig struct { + APIHost string + APIKey string + Model string +} + +// NewSiliconFlowProvider 创建硅基流动厂商实例 +func NewSiliconFlowProvider(config ProviderConfig) *SiliconFlowProvider { + return &SiliconFlowProvider{ + config: config, + client: &http.Client{}, + } +} + +// Name 返回厂商名称 +func (p *SiliconFlowProvider) Name() string { + return "siliconflow" +} + +// Validate 验证配置 +func (p *SiliconFlowProvider) Validate() error { + if p.config.APIKey == "" { + return fmt.Errorf("siliconflow: API key 不能为空") + } + if p.config.APIHost == "" { + p.config.APIHost = "https://api.siliconflow.cn/v1" + } + return nil +} + +// Translate 调用硅基流动API +func (p *SiliconFlowProvider) Translate(ctx context.Context, req *TranslateRequest) (*TranslateResponse, error) { + // 实现具体的API调用逻辑 + // 1. 构建请求体 + // 2. 发送HTTP请求 + // 3. 解析响应 + + // 示例代码(简化) + url := p.config.APIHost + "/chat/completions" + requestBody := map[string]interface{}{ + "model": p.config.Model, + "messages": []map[string]string{ + {"role": "user", "content": req.Text}, + }, + } + + // 实际实现需要完整的HTTP客户端代码 + return &TranslateResponse{ + Text: "翻译结果", + FromLang: req.FromLang, + ToLang: req.ToLang, + Model: p.config.Model, + }, nil +} +``` + +### 4. 工厂模式 - ProviderFactory + +```go +// internal/provider/factory.go +package provider + +import ( + "fmt" +) + +// ProviderFactory 厂商工厂 +type ProviderFactory struct { + providers map[string]func(ProviderConfig) Provider +} + +// NewProviderFactory 创建工厂实例 +func NewProviderFactory() *ProviderFactory { + factory := &ProviderFactory{ + providers: make(map[string]func(ProviderConfig) Provider), + } + + // 注册所有厂商 + factory.Register("siliconflow", NewSiliconFlowProvider) + factory.Register("volcano", NewVolcanoEngineProvider) + factory.Register("national", NewNationalSupercomputingProvider) + factory.Register("qwen", NewQwenProvider) + factory.Register("openai", NewOpenAICompatibleProvider) + + return factory +} + +// Register 注册厂商构造函数 +func (f *ProviderFactory) Register(name string, creator func(ProviderConfig) Provider) { + f.providers[name] = creator +} + +// Create 创建厂商实例 +func (f *ProviderFactory) Create(name string, config ProviderConfig) (Provider, error) { + creator, exists := f.providers[name] + if !exists { + return nil, fmt.Errorf("不支持的厂商: %s", name) + } + + provider := creator(config) + if err := provider.Validate(); err != nil { + return nil, fmt.Errorf("厂商配置验证失败: %w", err) + } + + return provider, nil +} +``` + +### 5. 核心翻译类 (Translator) + +```go +// internal/translator/translator.go +package translator + +import ( + "context" + "time" +) + +// Translator 核心翻译类 +type Translator struct { + config *config.Config + provider provider.Provider + prompt *PromptManager +} + +// NewTranslator 创建翻译器实例 +func NewTranslator(config *config.Config, provider provider.Provider) *Translator { + return &Translator{ + config: config, + provider: provider, + prompt: NewPromptManager(config.Prompts), + } +} + +// Translate 执行翻译 +func (t *Translator) Translate(ctx context.Context, text string, options *TranslateOptions) (*TranslateResult, error) { + // 设置超时 + timeoutCtx, cancel := context.WithTimeout(ctx, time.Duration(t.config.Timeout)*time.Second) + defer cancel() + + // 构建请求 + req := &provider.TranslateRequest{ + Text: text, + FromLang: options.FromLang, + ToLang: options.ToLang, + Prompt: t.prompt.GetPrompt(options.PromptName), + Model: t.selectModel(options.Model), + } + + // 调用厂商API + resp, err := t.provider.Translate(timeoutCtx, req) + if err != nil { + return nil, fmt.Errorf("翻译失败: %w", err) + } + + // 构建结果 + return &TranslateResult{ + Original: text, + Translated: resp.Text, + FromLang: resp.FromLang, + ToLang: resp.ToLang, + Model: resp.Model, + Usage: resp.Usage, + }, nil +} + +// selectModel 选择模型 +func (t *Translator) selectModel(model string) string { + if model != "" { + return model + } + return t.config.DefaultModel +} + +// TranslateOptions 翻译选项 +type TranslateOptions struct { + FromLang string + ToLang string + PromptName string + Model string + Temperature float64 +} + +// TranslateResult 翻译结果 +type TranslateResult struct { + Original string + Translated string + FromLang string + ToLang string + Model string + Usage *provider.Usage +} +``` + +### 6. 设计模式应用 + +#### 工厂模式 +- `ProviderFactory` 用于创建不同厂商实例 +- 统一创建接口,隐藏具体实现细节 + +#### 策略模式 +- `Provider` 接口定义统一行为 +- 每个厂商实现不同的API调用策略 +- 运行时动态选择策略 + +#### 单例模式 +- 全局配置通常只需要一个实例 +- 可通过包级变量或sync.Once实现 + +#### 依赖注入 +- `Translator` 依赖 `Provider` 接口,而不是具体实现 +- 通过构造函数注入依赖 + +## 项目结构 +``` +yoyo/ +├── cmd/ +│ └── yoyo/ # CLI入口 +├── internal/ +│ ├── config/ # 全局配置 +│ │ ├── config.go +│ │ └── loader.go +│ ├── provider/ # 厂商实现 +│ │ ├── provider.go # 接口定义 +│ │ ├── factory.go # 工厂模式 +│ │ ├── siliconflow.go +│ │ ├── volcano.go +│ │ ├── national.go +│ │ ├── qwen.go +│ │ └── openai.go +│ ├── translator/ # 核心翻译 +│ │ ├── translator.go +│ │ └── prompt.go +│ └── prompt/ # Prompt管理 +├── pkg/ # 公共工具 +├── configs/ # 配置文件目录 +│ └── config.yaml +├── go.mod +└── go.sum +``` + +## 配置文件示例 (YAML) +```yaml +# config.yaml +default_provider: "siliconflow" +default_model: "gpt-3.5-turbo" +timeout: 30 + +providers: + siliconflow: + api_host: "https://api.siliconflow.cn/v1" + api_key: "${SILICONFLOW_API_KEY}" + model: "siliconflow-base" + enabled: true + + volcano: + api_host: "https://api.volcengine.com/v1" + api_key: "${VOLCANO_API_KEY}" + model: "volcano-chat" + enabled: true + + national: + api_host: "https://api.nsc.gov.cn/v1" + api_key: "${NATIONAL_API_KEY}" + model: "nsc-base" + enabled: false + + qwen: + api_host: "https://dashscope.aliyuncs.com/compatible-mode/v1" + api_key: "${QWEN_API_KEY}" + model: "qwen-turbo" + enabled: true + + openai: + api_host: "https://api.openai.com/v1" + api_key: "${OPENAI_API_KEY}" + model: "gpt-3.5-turbo" + enabled: true + +prompts: + technical: "你是一位专业的技术翻译,请准确翻译以下技术文档,保持专业术语的准确性。" + creative: "你是一位富有创造力的翻译家,请用优美流畅的语言翻译以下内容。" + academic: "你是一位学术翻译专家,请用严谨的学术语言翻译以下内容。" + simple: "请用简单易懂的语言翻译以下内容。" +``` + +## 开发顺序建议 +1. 实现 `Config` 和 `ConfigLoader` +2. 实现 `Provider` 接口和工厂 +3. 实现至少一个厂商(如SiliconFlow) +4. 实现 `Translator` 核心类 +5. 集成测试 +6. 实现其他厂商 + +## 测试策略 +```go +// 内部测试示例 +func TestTranslator_Translate(t *testing.T) { + // Mock provider + mockProvider := &MockProvider{ + TranslateFunc: func(ctx context.Context, req *provider.TranslateRequest) (*provider.TranslateResponse, error) { + return &provider.TranslateResponse{Text: "翻译结果"}, nil + }, + } + + translator := NewTranslator(testConfig, mockProvider) + result, err := translator.Translate(context.Background(), "Hello", &TranslateOptions{ + ToLang: "zh", + }) + + if err != nil { + t.Fatalf("翻译失败: %v", err) + } + + if result.Translated != "翻译结果" { + t.Errorf("期望 '翻译结果', 得到 '%s'", result.Translated) + } +} +``` + +## 错误处理最佳实践 +- 每个厂商实现应定义具体的错误类型 +- 使用 `%w` 包装错误以保留原始错误信息 +- 提供清晰的错误消息帮助调试 + +## 安全注意事项 +- API密钥使用环境变量 +- 配置文件中不存储真实密钥 +- 使用 `os.Getenv` 读取敏感信息 +- 定期轮换API密钥 + +## 开发规范 + +### 文档管理 + +#### 文档文件列表 +1. **why.md** - 项目初衷文档(仅用户编辑) +2. **taolun.md** - 讨论记录(时间轴格式) +3. **changelog.md** - 版本记录(包含讨论链接) +4. **memory.md** - 知识纠正(踩坑记录) + +#### 文档协作规范 +| 文档 | 编辑者 | 内容 | 更新频率 | +|------|--------|------|----------| +| why.md | 用户 | 项目初衷、愿景、目标 | 随时 | +| taolun.md | AI+用户 | 讨论记录、决策过程 | 每次重要讨论后 | +| changelog.md | AI | 版本变更、任务状态 | 每次版本更新 | +| memory.md | AI | 经验总结、术语定义 | 遇到问题后 | + +#### 特殊文档说明 +**why.md**: +- 项目初衷文档,只能由用户编辑 +- AI不应修改此文件内容 +- 用于记录创始人的个人想法和项目愿景 +- 位置:项目根目录 + +**AI责任边界**: +- ✅ 可以编辑:taolun.md、changelog.md、memory.md +- ❌ 不应编辑:why.md、用户个人配置文件 +- ✅ 可以建议:why.md的内容结构(但不强制) + +### 文档链接 +- 项目初衷: [why.md](why.md) +- 讨论记录: [taolun.md](taolun.md) +- 版本记录: [changelog.md](changelog.md) +- 知识纠正: [memory.md](memory.md) + +### 版本号管理 +- 格式:主版本.次版本.修订版本(00-99) +- 更新时机:测试完成后,git操作前 +- 递增规则:小修复第三位+1,新功能第二位+1,重大变更第一位+1 + +### 分支策略 +- main: 稳定上线版 +- dev: 开发分支 +- 功能开发:从dev创建功能分支 + +### 提交规范 +- 提交前更新相关文档 +- 使用清晰的提交信息 +- 版本更新时打标签 + +## 开发命令 + +### 构建 +```bash +# 构建二进制文件 +go build -o yoyo ./cmd/yoyo + +# 交叉编译(Linux) +GOOS=linux GOARCH=amd64 go build -o yoyo-linux ./cmd/yoyo + +# 交叉编译(macOS) +GOOS=darwin GOARCH=amd64 go build -o yoyo-mac ./cmd/yoyo +``` + +### 测试 +```bash +# 运行所有测试 +go test ./... + +# 运行特定包的测试 +go test ./internal/translator + +# 运行单个测试函数 +go test -run TestTranslate ./internal/translator + +# 运行测试并显示详细输出 +go test -v ./... + +# 运行基准测试 +go test -bench=. ./... +``` + +### 代码检查与格式化 +```bash +# 代码格式化(必须) +gofmt -w . + +# 代码检查 +go vet ./... + +# 使用golangci-lint(推荐) +golangci-lint run + +# 生成依赖图 +go mod graph +``` + +### 运行工具 +```bash +# 直接运行 +go run ./cmd/yoyo "This is translation content..." + +# 使用构建的二进制 +./yoyo "This is translation content..." + +# 指定翻译模式 +./yoyo --mode=technical "API documentation text" +``` + +## 代码风格指南 + +### 命名约定 +- **包名**:小写单词,简洁明了(如`translator`、`config`) +- **函数/方法名**:驼峰命名,动词开头(如`TranslateText`、`LoadConfig`) +- **变量名**:驼峰命名,简洁(如`inputText`、`apiResponse`) +- **常量**:全大写加下划线(如`MAX_RETRY_COUNT`) +- **接口名**:以`-er`结尾或描述性名称(如`Translator`、`ConfigLoader`) + +### 导入顺序 +```go +import ( + // 标准库 + "context" + "fmt" + + // 第三方包 + "github.com/spf13/cobra" + + // 项目内部包 + "github.com/username/yoyo/internal/api" + "github.com/username/yoyo/internal/config" +) +``` + +### 错误处理 +```go +// 包装错误以提供更多上下文 +if err := loadConfig(); err != nil { + return fmt.Errorf("failed to load config: %w", err) +} + +// 定义哨兵错误 +var ( + ErrInvalidAPIKey = errors.New("invalid API key") + ErrNetworkFailed = errors.New("network request failed") +) + +// 错误检查使用errors.Is +if errors.Is(err, ErrInvalidAPIKey) { + // 处理特定错误 +} +``` + +### 类型使用 +- 优先使用具体类型,必要时使用接口 +- 避免使用`interface{}`,使用泛型或具体类型 +- 结构体字段使用大写开头(导出)或小写开头(私有) +- 为复杂类型添加文档注释 + +### 并发处理 +```go +// 使用context传递取消信号 +func Translate(ctx context.Context, text string) (string, error) { + select { + case <-ctx.Done(): + return "", ctx.Err() + default: + // 继续翻译 + } +} + +// 使用goroutine和channel时注意资源清理 +go func() { + defer close(doneCh) + // 执行任务 +}() +``` + +### 注释规范 +- 包注释:描述包的功能和用途 +- 函数注释:描述函数功能、参数、返回值 +- 导出类型/函数必须有注释 +- 使用Godoc格式 + +## 测试指南 +- 每个公共函数都应有对应的测试 +- 测试函数命名:`TestFunctionName` +- 使用表格驱动测试 +- Mock外部依赖 +- 测试文件放在同一目录,以`_test.go`结尾 + +```go +// 示例测试 +func TestTranslator_Translate(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + {"simple text", "hello", "你好"}, + {"empty string", "", ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := translator.Translate(tt.input) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if result != tt.expected { + t.Errorf("got %v, want %v", result, tt.expected) + } + }) + } +} +``` + +## 依赖管理 +- 使用Go Modules管理依赖 +- 保持`go.mod`和`go.sum`整洁 +- 定期更新依赖:`go get -u ./...` +- 移除未使用的依赖:`go mod tidy` + +## 提交前检查清单 +1. ✅ 运行`gofmt -w .`格式化代码 +2. ✅ 运行`go vet ./...`检查代码 +3. ✅ 运行`go test ./...`确保测试通过 +4. ✅ 确保所有导出函数有注释 +5. ✅ 检查错误处理是否完善 +6. ✅ 验证API密钥等敏感信息已忽略 + +## 敏感信息处理 +- API密钥使用环境变量或配置文件 +- 将`.env`添加到`.gitignore` +- 不要在日志中打印敏感信息 +- 使用`os.Getenv`读取环境变量 + +## 构建和发布 +```bash +# 发布版本 +git tag v1.0.0 +git push origin v1.0.0 + +# 使用GoReleaser(推荐) +goreleaser release --clean +``` + +## 常见问题 +### Q: 如何添加新的翻译模式? +A: 在`internal/prompt/`目录下创建新的Prompt配置,然后在`internal/translator/`中注册。 + +### Q: 如何处理API限流? +A: 使用指数退避重试,并在`internal/api/`中实现限流器。 + +### Q: 如何支持更多语言? +A: 在配置文件中添加语言映射,并更新翻译逻辑。 + +## 参考资源 +- [Effective Go](https://go.dev/doc/effective_go) +- [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments) +- [Go Style Guide](https://google.github.io/styleguide/go/) \ No newline at end of file diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..1520bda --- /dev/null +++ b/changelog.md @@ -0,0 +1,85 @@ +# 变更日志 (changelog.md) + +> 本文档记录所有版本变更,包含功能、修复和讨论链接。 + +## 使用说明 +- 版本号格式:`主版本.次版本.修订版本`(如 `0.0.1`) +- 第三位为00-99,超过99时增加第二位 +- 每个版本包含指向讨论记录的链接 + +## 未来架构想法 +- [ ] 支持流式翻译输出 +- [ ] 添加本地缓存减少API调用 +- [ ] 实现插件系统支持自定义厂商 +- [ ] 支持批量翻译文件 +- [ ] 添加Web界面(可选) + +## 待实现 +- [ ] 实现硅基流动厂商 +- [ ] 实现火山引擎厂商 +- [ ] 实现国家超算厂商 +- [ ] 实现Qwen厂商 +- [ ] 实现OpenAI兼容厂商 +- [ ] 配置文件热重载 +- [ ] 翻译历史记录 + +## 当前正实现 +- [ ] 项目基础架构搭建 +- [ ] 核心类设计实现 + +## 待修复BUG +- 无 + +## 版本历史 + +### 0.0.1 (2026-03-28) - 项目初始化 +**类型**: 初始化版本 +**状态**: 开发中 + +**变更内容**: +- ✅ 确定技术栈为Go语言 +- ✅ 设计OOP架构(Config、Provider、Translator) +- ✅ 制定开发规范(taolun.md、changelog.md、memory.md、why.md) +- ✅ 确定分支策略(main、dev) +- ✅ 设计项目结构 +- ✅ 创建项目初衷文档(why.md) + +**讨论记录**: +- [确定技术栈](taolun.md#2026-03-28-2230-版本-001-确定技术栈) +- [设计OOP架构](taolun.md#2026-03-28-2300-版本-001-设计oop架构) +- [制定开发规范](taolun.md#2026-03-28-2330-版本-001-制定开发规范) +- [创建项目初衷文档](taolun.md#2026-03-28-2345-版本-001-创建项目初衷文档) + +**下一步**: +- 创建项目目录结构 +- 初始化Go模块 +- 实现Config类 +- 实现Provider接口 +- 用户填写why.md内容 + +--- + +## 版本号管理规则 + +### 版本号格式 +`主版本.次版本.修订版本`(例如:`1.2.3`) + +### 更新规则 +1. **主版本**(第一位):重大架构变更、不兼容更新 +2. **次版本**(第二位):新功能、重要特性 +3. **修订版本**(第三位):小修复、优化(00-99) + +### 更新流程 +1. 完成开发并测试 +2. 更新changelog.md +3. 更新taolun.md(如有讨论) +4. 更新memory.md(如有新知识) +5. 更新版本号 +6. 提交到dev分支 +7. 测试通过后合并到main +8. 创建版本标签:`git tag v0.0.1` + +### 示例版本递增 +- `0.0.1` → `0.0.2`:小修复 +- `0.0.99` → `0.1.0`:新功能(修订版本溢出) +- `1.2.3` → `2.0.0`:重大架构变更 \ No newline at end of file diff --git a/configs/config.yaml b/configs/config.yaml new file mode 100644 index 0000000..549a1aa --- /dev/null +++ b/configs/config.yaml @@ -0,0 +1,43 @@ +# YOYO翻译工具配置文件 +# 注意:API密钥使用环境变量,不要直接写入真实密钥 + +default_provider: "siliconflow" +default_model: "gpt-3.5-turbo" +timeout: 30 + +providers: + siliconflow: + api_host: "https://api.siliconflow.cn/v1" + api_key: "${SILICONFLOW_API_KEY}" + model: "siliconflow-base" + enabled: true + + volcano: + api_host: "https://api.volcengine.com/v1" + api_key: "${VOLCANO_API_KEY}" + model: "volcano-chat" + enabled: true + + national: + api_host: "https://api.nsc.gov.cn/v1" + api_key: "${NATIONAL_API_KEY}" + model: "nsc-base" + enabled: false + + qwen: + api_host: "https://dashscope.aliyuncs.com/compatible-mode/v1" + api_key: "${QWEN_API_KEY}" + model: "qwen-turbo" + enabled: true + + openai: + api_host: "https://api.openai.com/v1" + api_key: "${OPENAI_API_KEY}" + model: "gpt-3.5-turbo" + enabled: true + +prompts: + technical: "你是一位专业的技术翻译,请准确翻译以下技术文档,保持专业术语的准确性。" + creative: "你是一位富有创造力的翻译家,请用优美流畅的语言翻译以下内容。" + academic: "你是一位学术翻译专家,请用严谨的学术语言翻译以下内容。" + simple: "请用简单易懂的语言翻译以下内容。" \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..9f23bad --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/titor/fanyi + +go 1.26.1 diff --git a/memory.md b/memory.md new file mode 100644 index 0000000..6db74fd --- /dev/null +++ b/memory.md @@ -0,0 +1,166 @@ +# 记忆纠正 (memory.md) + +> 本文档记录开发过程中的重要定义、踩过的坑和经验总结,用于AI内部知识纠正。 + +## 使用说明 +- 定期更新,特别是遇到问题后 +- 按类别组织,便于查找 +- 包含具体示例和解决方案 + +## 技术决策记录 + +### Go语言选择 +**决策**: 使用Go语言而非Node.js或Deno +**原因**: +1. Go编译为单一二进制文件,部署方便 +2. 性能优秀,适合CLI工具 +3. 强大的标准库支持 +4. 用户愿意学习Go + +**影响**: 项目结构、依赖管理、开发工具链 + +--- + +### 面向对象设计 +**决策**: 在Go中实现面向对象设计模式 +**模式应用**: +1. **工厂模式**: ProviderFactory创建厂商实例 +2. **策略模式**: Provider接口定义不同厂商策略 +3. **依赖注入**: Translator依赖Provider接口 + +**注意事项**: +- Go中没有类,使用结构体 +- 继承通过组合实现 +- 多态通过接口实现 + +--- + +## 术语定义 + +### 厂商 (Provider) +指提供大模型API的服务商,如硅基流动、火山引擎等。每个厂商实现统一的`Provider`接口。 + +### 配置 (Config) +全局配置对象,包含API密钥、模型选择、超时设置等。使用YAML格式。 + +### 核心翻译器 (Translator) +负责协调配置、厂商和Prompt管理,执行翻译任务的核心类。 + +## 踩过的坑 + +### 环境变量加载问题 +**问题**: 配置文件中的环境变量(如`${API_KEY}`)没有正确解析 +**原因**: 没有实现环境变量替换功能 +**解决方案**: +1. 使用`os.Getenv`读取环境变量 +2. 在配置加载时进行字符串替换 +3. 添加环境变量验证 + +**预防措施**: +- 在配置加载后验证所有必需的环境变量 +- 提供清晰的错误信息 + +--- + +### 厂商API差异 +**问题**: 不同厂商的API格式差异较大 +**原因**: 每个厂商有自己的请求/响应格式 +**解决方案**: +1. 定义统一的`TranslateRequest`和`TranslateResponse` +2. 在每个厂商实现中进行格式转换 +3. 使用适配器模式 + +**经验**: +- 优先设计统一接口 +- 将厂商特定逻辑封装在实现内部 +- 提供原始响应用于调试 + +--- + +### 版本号管理混乱 +**问题**: 版本号递增规则不明确 +**原因**: 没有明确的版本管理规范 +**解决方案**: +1. 采用语义化版本:主版本.次版本.修订版本 +2. 第三位限制为00-99 +3. 建立更新流程 + +**规范**: +- 小修复:修订版本+1 +- 新功能:次版本+1,修订版本重置为00 +- 重大变更:主版本+1,次版本和修订版本重置 + +--- + +## 配置最佳实践 + +### 安全配置 +- API密钥使用环境变量 +- 不提交敏感信息到版本控制 +- 提供`.env.example`模板 + +### 配置验证 +- 启动时验证所有必需配置 +- 提供有意义的错误信息 +- 支持配置热重载(未来) + +### 默认值策略 +- 为非必需配置提供合理的默认值 +- 默认值应在`config.setDefaults()`中设置 +- 记录默认值的作用 + +--- + +## 开发工作流 + +### 日常开发流程 +1. 从`dev`分支创建功能分支 +2. 开发并测试功能 +3. 更新相关文档(taolun.md、changelog.md) +4. 提交到功能分支 +5. 合并到`dev`分支 +6. 测试通过后合并到`main` + +### 版本发布流程 +1. 确保`dev`分支稳定 +2. 更新版本号 +3. 更新changelog.md +4. 创建版本标签 +5. 合并到`main`分支 + +### 文档维护 +- 每次重要讨论后更新taolun.md +- 每个版本更新changelog.md +- 遇到问题后更新memory.md + +--- + +## 文档管理规范 + +### why.md (项目初衷文档) +**用途**: 记录项目初衷、愿景、目标和个人笔记 +**编辑权限**: 只能由项目所有者(用户)编辑 +**位置**: 项目根目录 +**内容建议**: +- 项目愿景 +- 核心问题 +- 目标用户 +- 期望功能 +- 个人笔记 + +**注意事项**: +- AI不应修改此文件 +- 文件内容反映创始人的个人想法 +- 可以自由格式,不强制结构 + +### 文档协作规范 +**taolun.md**: AI与用户共同维护的讨论记录 +**changelog.md**: AI与用户共同维护的版本记录 +**memory.md**: AI主导的知识纠正和经验总结 +**why.md**: 用户专属的项目初衷文档 + +**编辑流程**: +1. 用户编辑why.md记录初衷 +2. AI编辑taolun.md记录讨论 +3. AI更新changelog.md记录版本 +4. AI更新memory.md记录经验 \ No newline at end of file diff --git a/taolun.md b/taolun.md new file mode 100644 index 0000000..2feb9d8 --- /dev/null +++ b/taolun.md @@ -0,0 +1,88 @@ +# 讨论记录 (taolun.md) + +> 本文档记录开发过程中的重要讨论,以时间轴方式存储,便于版本追溯。 + +## 使用说明 +- 每次重要讨论后更新此文件 +- 使用上下文压缩总结,突出重点 +- 格式:时间 - 版本号 - 主题 + +## 时间轴记录 + +### [2026-03-28 22:30] 版本 0.0.1 - 确定技术栈 +**原因**: 项目启动,需要确定技术栈 +**分析**: +- 比较Go、Deno+TS、Node.js+TS +- Go优势:原生二进制、性能好、CLI工具友好 +- 用户不会Go但愿意学习 + +**解决方案**: +- 使用Go语言开发 +- 采用面向对象设计模式 +- 支持多个大模型厂商 + +**相关决策**: +- 项目结构采用`cmd/`和`internal/`布局 +- 使用YAML配置文件 +- 实现工厂模式和策略模式 + +**关联版本**: [changelog.md#0.0.1](changelog.md#001) + +--- + +### [2026-03-28 23:00] 版本 0.0.1 - 设计OOP架构 +**原因**: 用户要求面向对象开发模式 +**分析**: +- Go不是传统OOP语言,但可通过结构体和接口实现 +- 需要三个核心类:配置、厂商、翻译器 + +**解决方案**: +- `Config`类:全局配置管理 +- `Provider`接口:厂商抽象 +- `Translator`类:核心翻译逻辑 +- `ProviderFactory`:工厂模式创建厂商实例 + +**相关链接**: +- [AGENTS.md#OOP设计模式](AGENTS.md#oop设计模式) +- [changelog.md#0.0.1](changelog.md#001) + +--- + +### [2026-03-28 23:30] 版本 0.0.1 - 制定开发规范 +**原因**: 建立规范的开发流程 +**分析**: +- 需要记录讨论过程、版本变更和知识积累 +- 版本号需要遵循语义化版本规范 + +**解决方案**: +- 创建taolun.md记录讨论 +- 创建changelog.md记录版本 +- 创建memory.md记录知识纠正 +- 版本号格式:大版本.新功能.小修复(00-99) + +**关联文档**: +- [changelog.md#0.0.1](changelog.md#001) +- [memory.md#版本管理](memory.md#版本管理) + +--- + +### [2026-03-28 23:45] 版本 0.0.1 - 创建项目初衷文档 +**原因**: 需要一个地方记录项目初衷和愿景 +**分析**: +- 项目需要明确的目标和方向 +- 创始人需要记录个人想法和灵感 +- 与其他文档(taolun.md、changelog.md、memory.md)区分 + +**解决方案**: +- 创建`why.md`文件专门记录项目初衷 +- 规定只能由项目所有者编辑 +- 提供基本结构建议,但不强制内容 + +**文档规范**: +- 文件位置:项目根目录 +- 权限:仅用户可编辑 +- 内容:项目愿景、目标、个人笔记等 + +**关联文档**: +- [AGENTS.md#文档管理](AGENTS.md#开发规范) +- [changelog.md#0.0.1](changelog.md#001) \ No newline at end of file diff --git a/why.md b/why.md new file mode 100644 index 0000000..902b3f8 --- /dev/null +++ b/why.md @@ -0,0 +1,33 @@ +# 项目初衷 (why.md) + +> 本文档记录YOYO翻译工具项目的初衷、愿景和目标。 +> **注意:此文档只能由项目所有者编辑。** + +## 项目愿景 +创建一个高效、易用的命令行翻译工具,支持多个大模型厂商,提供多样化的翻译特色。 + +## 核心问题 +1. 现有翻译工具功能单一,缺乏定制化 +2. 不同翻译场景需要不同的Prompt策略 +3. 需要一个统一的CLI工具集成多个翻译API + +## 目标用户 +- 开发者:需要翻译技术文档 +- 写作者:需要翻译创意内容 +- 学生:需要翻译学术论文 +- 普通用户:日常翻译需求 + +## 期望功能 +- [ ] 支持多个大模型厂商 +- [ ] 可配置的Prompt模板 +- [ ] 批量翻译文件 +- [ ] 翻译历史记录 +- [ ] 本地缓存减少API调用 + +## 个人笔记 +(在此记录您的个人想法、灵感和笔记) + +--- + +*最后更新:2026-03-28* +*版本:0.0.1* \ No newline at end of file