一只用 AI Agent 搭副业产线的程序员模块一结束了。10 篇文章从「AI 能帮程序员做什么」到「AI 的边界在哪」。但你可能有个问题每次写代码都要重新搭环境——注册 API Key、配置环境变量、装各种依赖。能不能一次性搭好这篇给你答案一个 Docker Compose 文件把 AI 开发需要的所有基础设施拉起来。你需要什么一个完整的 AI 开发环境包含这些组件组件作用你会用到的场景DeepSeek 代理统一 API 入口避免硬编码 Key所有调用Ollama本地模型运行环境高频调用 / 隐私敏感Open WebUI本地版 ChatGPT 界面Prompt 调试Qdrant向量数据库存储和搜索 Embedding 向量模块三 RAGRedis缓存 API 响应省 TokenAgent 开发一键部署# docker-compose.ymlversion:3.8services:# 1. 本地模型引擎ollama:image:ollama/ollama:latestcontainer_name:ai-ollamaports:-11434:11434volumes:-ollama_data:/root/.ollamaenvironment:-OLLAMA_KEEP_ALIVE24hdeploy:resources:reservations:devices:-driver:nvidiacount:1capabilities:[gpu]restart:unless-stopped# 2. 本地 ChatGPT 界面调试 Prompt 巨方便open-webui:image:ghcr.io/open-webui/open-webui:maincontainer_name:ai-webuiports:-13000:8080environment:-OLLAMA_BASE_URLhttp://ollama:11434-WEBUI_SECRET_KEYchange-me-to-random-stringvolumes:-webui_data:/app/backend/datadepends_on:-ollamarestart:unless-stopped# 3. 向量数据库模块三用qdrant:image:qdrant/qdrant:latestcontainer_name:ai-qdrantports:-6333:6333-6334:6334volumes:-qdrant_data:/qdrant/storagerestart:unless-stopped# 4. RedisToken 缓存、Agent 状态redis:image:redis:7-alpinecontainer_name:ai-redisports:-6379:6379command:redis-server--appendonly yesvolumes:-redis_data:/datarestart:unless-stoppedvolumes:ollama_data:webui_data:qdrant_data:redis_data:# 启动全家桶首次启动会拉取镜像耐心等几分钟dockercompose up-d# 拉一个本地模型可选不需要本地模型可以跳过dockerexec-itai-ollama ollama pull qwen2.5-coder:7b# 确认各组件状态dockercomposeps启动完成后服务地址用途Ollama APIhttp://localhost:11434本地模型 APIOpen WebUIhttp://localhost:13000聊天调试界面Qdranthttp://localhost:6333向量数据库Redislocalhost:6379缓存配置你的 Go 项目模板有了基础设施还需要一个趁手的 Go 项目模板。我整理了一个ai-project/ ├── main.go ├── go.mod ├── .env.example ├── internal/ │ ├── llm/ │ │ └── client.go # LLM 调用客户端 │ ├── embed/ │ │ └── embeddings.go # Embedding 工具 │ ├── cache/ │ │ └── redis.go # Redis 缓存层 │ └── config/ │ └── config.go # 配置管理 └── scripts/ └── setup.sh # 初始化脚本核心配置// internal/config/config.gopackageconfigimportostypeConfigstruct{// API 配置DeepSeekAPIKeystringDeepSeekBaseURLstring// 本地服务OllamaURLstringQdrantURLstringRedisAddrstring// 默认参数DefaultModelstringDefaultTempfloat64DefaultMaxTokenint}funcLoad()*Config{returnConfig{DeepSeekAPIKey:getEnv(DEEPSEEK_API_KEY,),DeepSeekBaseURL:getEnv(DEEPSEEK_BASE_URL,https://api.deepseek.com/anthropic),OllamaURL:getEnv(OLLAMA_URL,http://localhost:11434),QdrantURL:getEnv(QDRANT_URL,http://localhost:6334),RedisAddr:getEnv(REDIS_ADDR,localhost:6379),DefaultModel:getEnv(DEFAULT_MODEL,deepseek-v4-flash),DefaultTemp:getEnvFloat(DEFAULT_TEMP,0.1),DefaultMaxToken:getEnvInt(DEFAULT_MAX_TOKENS,500),}}funcgetEnv(key,defaultValstring)string{ifv:os.Getenv(key);v!{returnv}returndefaultVal}LLM 客户端支持多后端切换// internal/llm/client.gopackagellmimport(bytesencoding/jsonfmtnet/http)typeClientstruct{BaseURLstringAPIKeystringModelstringHTTP*http.Client}typeMessagestruct{Rolestringjson:roleContentstringjson:content}funcNewClient(baseURL,apiKey,modelstring)*Client{returnClient{BaseURL:baseURL,APIKey:apiKey,Model:model,HTTP:http.Client{},}}func(c*Client)Chat(messages[]Message,tempfloat64,maxTokensint)(string,error){body:map[string]interface{}{model:c.Model,max_tokens:maxTokens,temperature:temp,messages:messages,}jsonBody,_:json.Marshal(body)req,_:http.NewRequest(POST,c.BaseURL/v1/messages,bytes.NewReader(jsonBody))req.Header.Set(x-api-key,c.APIKey)req.Header.Set(anthropic-version,2023-06-01)req.Header.Set(Content-Type,application/json)resp,err:c.HTTP.Do(req)iferr!nil{return,fmt.Errorf(请求失败: %w,err)}deferresp.Body.Close()varresultmap[string]interface{}json.NewDecoder(resp.Body).Decode(result)ifcontent,ok:result[content].([]interface{});oklen(content)0{iftext,ok:content[0].(map[string]interface{})[text].(string);ok{returntext,nil}}return,fmt.Errorf(无法解析响应)}// 快速切换后端funcNewDeepSeekClient(apiKeystring)*Client{returnNewClient(https://api.deepseek.com/anthropic,apiKey,deepseek-v4-flash)}funcNewOllamaClient(modelstring)*Client{returnNewClient(http://localhost:11434/api,,model)}验证环境跑一个集成测试packagemainimport(fmtosai-project/internal/configai-project/internal/llm)funcmain(){cfg:config.Load()client:llm.NewDeepSeekClient(cfg.DeepSeekAPIKey)messages:[]llm.Message{{Role:user,Content:请验证环境是否正常回复 AI 开发环境已就绪。},}result,err:client.Chat(messages,0.1,100)iferr!nil{fmt.Printf(环境验证失败: %v\n,err)os.Exit(1)}fmt.Println(result)fmt.Println(\n✅ 所有组件正常运行)}go run main.go# AI 开发环境已就绪。# ✅ 所有组件正常运行模块一知识地图篇核心知识你的武器15 个真实可用场景样板代码生成、注释、审查、日志分析、自动化2LLM 工作原理50 行 Go 对话程序3Token/温度/上下文三参数对照实验4主流模型横评4 任务 × 5 模型的完整数据5第一个 LLM 程序5 分钟从零到运行6API 价格真相100 次调用的真实账单7本地 vs 云端Ollama 部署 混合策略8Embedding50 行语义相似度计算9AI 的边界6 个翻车案例 防御策略10开发环境Docker Compose 全家桶 Go 模板接下来 —— 模块二Prompt Engineering 实战你已经知道 AI 怎么调了。接下来 10 篇文章我们要把 Prompt 当代码写不再把 Prompt 写在.txt里复制粘贴用 JSON 配置驱动 Prompt变量替换、条件分支、模板继承自动化测试——同一个 Prompt 跑 100 次统计通过率安全防御——Prompt 注入攻防下一篇Prompt 的本质不是「聊天」是「编程」。用同一个任务的好 Prompt vs 烂 Prompt让你直观看到差距。关注我别错过。 一只用 AI Agent 搭副业产线的程序员全平台同名虾哥不加班需要定制 AI 工具来聊聊 → lob_ai源码 模板GitHub - lobster-bujiaban/ai-starter
模块一总结:一个 Docker Compose 搭好你的 AI 开发环境
一只用 AI Agent 搭副业产线的程序员模块一结束了。10 篇文章从「AI 能帮程序员做什么」到「AI 的边界在哪」。但你可能有个问题每次写代码都要重新搭环境——注册 API Key、配置环境变量、装各种依赖。能不能一次性搭好这篇给你答案一个 Docker Compose 文件把 AI 开发需要的所有基础设施拉起来。你需要什么一个完整的 AI 开发环境包含这些组件组件作用你会用到的场景DeepSeek 代理统一 API 入口避免硬编码 Key所有调用Ollama本地模型运行环境高频调用 / 隐私敏感Open WebUI本地版 ChatGPT 界面Prompt 调试Qdrant向量数据库存储和搜索 Embedding 向量模块三 RAGRedis缓存 API 响应省 TokenAgent 开发一键部署# docker-compose.ymlversion:3.8services:# 1. 本地模型引擎ollama:image:ollama/ollama:latestcontainer_name:ai-ollamaports:-11434:11434volumes:-ollama_data:/root/.ollamaenvironment:-OLLAMA_KEEP_ALIVE24hdeploy:resources:reservations:devices:-driver:nvidiacount:1capabilities:[gpu]restart:unless-stopped# 2. 本地 ChatGPT 界面调试 Prompt 巨方便open-webui:image:ghcr.io/open-webui/open-webui:maincontainer_name:ai-webuiports:-13000:8080environment:-OLLAMA_BASE_URLhttp://ollama:11434-WEBUI_SECRET_KEYchange-me-to-random-stringvolumes:-webui_data:/app/backend/datadepends_on:-ollamarestart:unless-stopped# 3. 向量数据库模块三用qdrant:image:qdrant/qdrant:latestcontainer_name:ai-qdrantports:-6333:6333-6334:6334volumes:-qdrant_data:/qdrant/storagerestart:unless-stopped# 4. RedisToken 缓存、Agent 状态redis:image:redis:7-alpinecontainer_name:ai-redisports:-6379:6379command:redis-server--appendonly yesvolumes:-redis_data:/datarestart:unless-stoppedvolumes:ollama_data:webui_data:qdrant_data:redis_data:# 启动全家桶首次启动会拉取镜像耐心等几分钟dockercompose up-d# 拉一个本地模型可选不需要本地模型可以跳过dockerexec-itai-ollama ollama pull qwen2.5-coder:7b# 确认各组件状态dockercomposeps启动完成后服务地址用途Ollama APIhttp://localhost:11434本地模型 APIOpen WebUIhttp://localhost:13000聊天调试界面Qdranthttp://localhost:6333向量数据库Redislocalhost:6379缓存配置你的 Go 项目模板有了基础设施还需要一个趁手的 Go 项目模板。我整理了一个ai-project/ ├── main.go ├── go.mod ├── .env.example ├── internal/ │ ├── llm/ │ │ └── client.go # LLM 调用客户端 │ ├── embed/ │ │ └── embeddings.go # Embedding 工具 │ ├── cache/ │ │ └── redis.go # Redis 缓存层 │ └── config/ │ └── config.go # 配置管理 └── scripts/ └── setup.sh # 初始化脚本核心配置// internal/config/config.gopackageconfigimportostypeConfigstruct{// API 配置DeepSeekAPIKeystringDeepSeekBaseURLstring// 本地服务OllamaURLstringQdrantURLstringRedisAddrstring// 默认参数DefaultModelstringDefaultTempfloat64DefaultMaxTokenint}funcLoad()*Config{returnConfig{DeepSeekAPIKey:getEnv(DEEPSEEK_API_KEY,),DeepSeekBaseURL:getEnv(DEEPSEEK_BASE_URL,https://api.deepseek.com/anthropic),OllamaURL:getEnv(OLLAMA_URL,http://localhost:11434),QdrantURL:getEnv(QDRANT_URL,http://localhost:6334),RedisAddr:getEnv(REDIS_ADDR,localhost:6379),DefaultModel:getEnv(DEFAULT_MODEL,deepseek-v4-flash),DefaultTemp:getEnvFloat(DEFAULT_TEMP,0.1),DefaultMaxToken:getEnvInt(DEFAULT_MAX_TOKENS,500),}}funcgetEnv(key,defaultValstring)string{ifv:os.Getenv(key);v!{returnv}returndefaultVal}LLM 客户端支持多后端切换// internal/llm/client.gopackagellmimport(bytesencoding/jsonfmtnet/http)typeClientstruct{BaseURLstringAPIKeystringModelstringHTTP*http.Client}typeMessagestruct{Rolestringjson:roleContentstringjson:content}funcNewClient(baseURL,apiKey,modelstring)*Client{returnClient{BaseURL:baseURL,APIKey:apiKey,Model:model,HTTP:http.Client{},}}func(c*Client)Chat(messages[]Message,tempfloat64,maxTokensint)(string,error){body:map[string]interface{}{model:c.Model,max_tokens:maxTokens,temperature:temp,messages:messages,}jsonBody,_:json.Marshal(body)req,_:http.NewRequest(POST,c.BaseURL/v1/messages,bytes.NewReader(jsonBody))req.Header.Set(x-api-key,c.APIKey)req.Header.Set(anthropic-version,2023-06-01)req.Header.Set(Content-Type,application/json)resp,err:c.HTTP.Do(req)iferr!nil{return,fmt.Errorf(请求失败: %w,err)}deferresp.Body.Close()varresultmap[string]interface{}json.NewDecoder(resp.Body).Decode(result)ifcontent,ok:result[content].([]interface{});oklen(content)0{iftext,ok:content[0].(map[string]interface{})[text].(string);ok{returntext,nil}}return,fmt.Errorf(无法解析响应)}// 快速切换后端funcNewDeepSeekClient(apiKeystring)*Client{returnNewClient(https://api.deepseek.com/anthropic,apiKey,deepseek-v4-flash)}funcNewOllamaClient(modelstring)*Client{returnNewClient(http://localhost:11434/api,,model)}验证环境跑一个集成测试packagemainimport(fmtosai-project/internal/configai-project/internal/llm)funcmain(){cfg:config.Load()client:llm.NewDeepSeekClient(cfg.DeepSeekAPIKey)messages:[]llm.Message{{Role:user,Content:请验证环境是否正常回复 AI 开发环境已就绪。},}result,err:client.Chat(messages,0.1,100)iferr!nil{fmt.Printf(环境验证失败: %v\n,err)os.Exit(1)}fmt.Println(result)fmt.Println(\n✅ 所有组件正常运行)}go run main.go# AI 开发环境已就绪。# ✅ 所有组件正常运行模块一知识地图篇核心知识你的武器15 个真实可用场景样板代码生成、注释、审查、日志分析、自动化2LLM 工作原理50 行 Go 对话程序3Token/温度/上下文三参数对照实验4主流模型横评4 任务 × 5 模型的完整数据5第一个 LLM 程序5 分钟从零到运行6API 价格真相100 次调用的真实账单7本地 vs 云端Ollama 部署 混合策略8Embedding50 行语义相似度计算9AI 的边界6 个翻车案例 防御策略10开发环境Docker Compose 全家桶 Go 模板接下来 —— 模块二Prompt Engineering 实战你已经知道 AI 怎么调了。接下来 10 篇文章我们要把 Prompt 当代码写不再把 Prompt 写在.txt里复制粘贴用 JSON 配置驱动 Prompt变量替换、条件分支、模板继承自动化测试——同一个 Prompt 跑 100 次统计通过率安全防御——Prompt 注入攻防下一篇Prompt 的本质不是「聊天」是「编程」。用同一个任务的好 Prompt vs 烂 Prompt让你直观看到差距。关注我别错过。 一只用 AI Agent 搭副业产线的程序员全平台同名虾哥不加班需要定制 AI 工具来聊聊 → lob_ai源码 模板GitHub - lobster-bujiaban/ai-starter