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
This commit is contained in:
13
.env.example
Normal file
13
.env.example
Normal file
@@ -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
|
||||||
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@@ -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
|
||||||
767
AGENTS.md
Normal file
767
AGENTS.md
Normal file
@@ -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/)
|
||||||
85
changelog.md
Normal file
85
changelog.md
Normal file
@@ -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`:重大架构变更
|
||||||
43
configs/config.yaml
Normal file
43
configs/config.yaml
Normal file
@@ -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: "请用简单易懂的语言翻译以下内容。"
|
||||||
166
memory.md
Normal file
166
memory.md
Normal file
@@ -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记录经验
|
||||||
88
taolun.md
Normal file
88
taolun.md
Normal file
@@ -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)
|
||||||
33
why.md
Normal file
33
why.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# 项目初衷 (why.md)
|
||||||
|
|
||||||
|
> 本文档记录YOYO翻译工具项目的初衷、愿景和目标。
|
||||||
|
> **注意:此文档只能由项目所有者编辑。**
|
||||||
|
|
||||||
|
## 项目愿景
|
||||||
|
创建一个高效、易用的命令行翻译工具,支持多个大模型厂商,提供多样化的翻译特色。
|
||||||
|
|
||||||
|
## 核心问题
|
||||||
|
1. 现有翻译工具功能单一,缺乏定制化
|
||||||
|
2. 不同翻译场景需要不同的Prompt策略
|
||||||
|
3. 需要一个统一的CLI工具集成多个翻译API
|
||||||
|
|
||||||
|
## 目标用户
|
||||||
|
- 开发者:需要翻译技术文档
|
||||||
|
- 写作者:需要翻译创意内容
|
||||||
|
- 学生:需要翻译学术论文
|
||||||
|
- 普通用户:日常翻译需求
|
||||||
|
|
||||||
|
## 期望功能
|
||||||
|
- [ ] 支持多个大模型厂商
|
||||||
|
- [ ] 可配置的Prompt模板
|
||||||
|
- [ ] 批量翻译文件
|
||||||
|
- [ ] 翻译历史记录
|
||||||
|
- [ ] 本地缓存减少API调用
|
||||||
|
|
||||||
|
## 个人笔记
|
||||||
|
(在此记录您的个人想法、灵感和笔记)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*最后更新:2026-03-28*
|
||||||
|
*版本:0.0.1*
|
||||||
Reference in New Issue
Block a user