【AI实战日记-手搓情感聊天机器人】Day 1:15天手搓情感机器人?我的详细路线图与技术选型
为了系统性地掌握AI大模型技术,我决定开启一个“情感聊天机器人”实战项目。不只是简单的调包,而是按照软件工程的标准,从架构设计到分阶段落地。本文详细梳理了项目的5个开发阶段、基于LangChain的技术栈选型,文末附带了Day 1的环境搭建与基础对话代码。
1. 为什么要做这个项目?
-
痛点:碎片化学习AI效率太低,不如直接做一个完整的应用。
-
目标:构建一个不仅仅会回答问题,还能记住上下文、感知情绪、拥有个性化人设的AI伴侣。
2. 项目路线图
为了保证学习过程条理清晰,我将开发计划拆解为 5 个阶段,共计15天 的冲刺计划:
图1 项目路线图
Phase 1: 基础设施搭建
-
目标:配置 Python 环境,打通大模型 API,实现最基础的单轮对话。
-
关键点:环境隔离 (Conda)、API 密钥安全管理 (.env)、Request/Response 封装。
| 时间 | 任务模块 | 详细任务描述 | 预计产出 |
| Day 1 | 环境与API | 1. 安装 Miniconda & VS Code 2. 申请 阿里通义千问/OpenAI API Key 3. 编写 LLMClient 基础类 | 能够与AI进行单轮对话的控制台程序 |
| Day 2 | Prompt工程 | 1. 设计 System Prompt (系统提示词) 2. 定义 AI 的基础人设 (如: 毒舌、温柔) 3. 测试不同 Prompt 对回答的影响 | 具备固定性格特征的对话机器人 |
| Day 3 | 工程重构 | 1. 规范化目录结构 (src, tests, config) 2. 引入 Log 日志模块 3. 封装异常处理机制 | 结构清晰、健壮的 Python 工程项目 |
⚪ Phase 2: 记忆与状态管理
-
目标:解决 LLM 的“失忆”问题,实现连续对话。
-
关键点:LangChain Memory 组件、上下文窗口(Context Window)管理、Token 优化。
| 时间 | 任务模块 | 详细任务描述 | 预计产出 |
| Day 4 | 短期记忆 | 1. 引入 LangChain 框架 2. 接入 ConversationBufferMemory 3. 实现多轮对话测试 | 能记住上一句话的聊天机器人 |
| Day 5 | 情绪识别 | 1. 设计情绪分析 Prompt 2. 在对话中提取用户情绪标签 (开心/愤怒/悲伤) 3. 根据情绪动态调整回复语气 | 能感知用户情绪并做出反应的 AI |
| Day 6 | 持久化存储 | 1. 将聊天记录保存到本地 JSON/SQLite 2. 实现对话历史的回溯与加载 | 重启程序后依然记得你的 AI |
⚪ Phase 3: 赋予灵魂与知识
-
目标:设定“女友/男友”或“导师”人设,并挂载私人知识库(如日记、文档)。
-
关键点:System Prompt 设计、向量数据库(Vector DB)、RAG(检索增强生成)架构。
| 时间 | 任务模块 | 详细任务描述 | 预计产出 |
| Day 7 | 向量环境 | 1. 安装 ChromaDB (向量数据库) 2. 选定 Embedding 模型 (如 text-embedding-3-small) | 向量数据库基础环境 |
| Day 8 | 文档处理 | 1. 准备私人文档 (PDF/TXT) 2. 使用 TextSplitter 进行文本切片 3. 将文本向量化存入 ChromaDB | 包含个人知识的向量索引库 |
| Day 9 | RAG链路 | 1. 构建 RetrievalQA 链 2. 将检索到的上下文注入 Prompt 3. 调试检索相关性 | 能回答私人领域问题的 AI |
| Day 10 | 效果优化 | 1. 优化 Prompt 模板以融合检索内容与人设 2. 处理检索为空的情况 | 回答更加自然、准确的知识库助手 |
⚪ Phase 4: 多模态交互 (Voice & Emotion)
-
目标:从“文字聊天”升级为“语音通话”,并根据用户情绪调整语气。
-
关键点:TTS (文本转语音)、STT (语音转文本)、简单的情感分析逻辑。
| 时间 | 任务模块 | 详细任务描述 | 预计产出 |
| Day 11 | 让AI说话 (TTS) | 1. 接入 Edge-TTS (免费) 或 OpenAI TTS 2. 实现文字转音频文件的播放 | 能发出声音的机器人 |
| Day 12 | 听懂语音 (STT) | 1. 使用 Whisper 或相关 API 进行语音识别 2. 实现麦克风录音功能 | 支持语音输入的交互模块 |
| Day 13 | 全链路集成 | 1. 串联 STT -> LLM -> TTS 2. 优化语音互动的延迟 | 具备实时语音通话功能的 Demo |
⚪ Phase 5: 全栈应用与部署
-
目标:开发可视化 Web 界面,部署上线。
-
关键点:Vue前端开发、Docker 容器化、云端部署。
| 时间 | 任务模块 | 详细任务描述 | 预计产出 |
| Day 14 | Web界面 | 1. 使用 Vue搭建聊天界面 2. 美化 UI (气泡对话框样式) 3. 集成侧边栏设置 (参数调节) | 漂亮的网页版聊天应用 |
| Day 15 | 部署上线 | 1. 编写 Dockerfile 2. 部署到 HuggingFace Spaces 或云服务器 3. 项目总结与开源 | 可供他人访问的在线服务 |
3. 系统架构设计
在开始写代码之前,我先梳理了系统的逻辑架构。

图2 系统架构图
1. 前端交互层 (Frontend Layer)
这是用户直接接触的“皮囊”,我选择了 Vue.js ,主要包含两个核心模块:
-
Vue.js SPA (单页应用):
负责渲染聊天气泡、管理页面状态。Vue 的组件化开发让我能轻松定制“正在输入中...”的动画效果,以及未来多模态交互的复杂 UI。 -
Web Audio Module (音频处理):
这是一个隐藏在界面背后的模块。它直接调用浏览器的原生 Web Audio API,负责捕获麦克风的原始音频流(Stream),并播放后端返回的语音二进制数据。这是 Phase 4 实现“实时通话”的关键。
2. 后端应用层 (Application Layer)
这是系统的“中枢神经”,运行在 Python 环境中:
-
FastAPI Gateway (网关):
它是连接前端与后端的桥梁。负责处理 HTTP RESTful 请求(常规对话)和 WebSocket 连接(流式传输),并进行参数校验和鉴权。 -
LangChain Controller (编排控制器):
1)Memory Manager:去 Redis 里查阅上下文,看看我们之前聊了什么,防止 AI “断片”。
这是整个架构中最核心的代码。你可以把它理解为“业务逻辑层”。当它收到用户的消息时,它不急着调用大模型,而是先进行**“三步走”编排**:
2)RAG System:去向量库里检索有没有相关的私人知识(比如我的日记或文档),让回答更有依据。
3)Prompt Engineer:将上下文、知识和用户问题打包,填充进预设的“人设模板”中。
3. 基础设施层 (Infrastructure Layer)
最底层的基石,负责数据存储和算力供给:
-
Redis / Session Store:
用于存储“短期记忆”。对话过程中的上下文(Context)会暂存在这里,保证交互的低延迟。 -
ChromaDB (Vector Database):
用于存储“长期记忆”。所有的私人文档会被转化为**向量(Vector)**存放在此。大模型本身不懂我,但通过 ChromaDB,它能随时检索到关于我的信息。 -
阿里通义千问 API (Model Service):
最终的算力提供方。经过 Controller 精心打包的 Prompt 会发送到这里,生成最终的自然语言回复。
4. 数据流转逻辑
-
用户在 Vue 界面 输入(或语音说话)。
-
FastAPI 接收请求,解析数据。
-
LangChain 介入,提取 ChromaDB 中的知识,结合 Redis 中的历史记忆。
-
组合好的 Prompt 发送给 DeepSeek。
-
生成的回答经由原路返回,最终在浏览器上渲染出来。
4. 技术栈选型
作为有软件开发背景的学习者,我在选型时不仅看重“热门”,更看重工程落地能力和成本控制。
| 分层 (Layer) | 技术组件 (Component) | 选型理由 (Why?) |
| 语言环境 | Python 3.10 + Conda | AI 开发的事实标准,Conda 用于隔离复杂的依赖库(如 PyTorch)。 |
| 大模型 API | 阿里通义千问 | 性价比极高,有免费额度,代码能力强,兼容 OpenAI SDK,且无需魔法网络。 |
| 编排框架 | LangChain | AI 应用层的“Spring Boot”,提供了丰富的工具链(Memory, Chains, Agents)。 |
| 向量数据库 | ChromaDB | 轻量级、嵌入式,不需要单独部署服务器,非常适合单机项目入门。 |
| 前端框架 | Vue.js 3 | 前后端分离架构,提供更极致的 UI 定制能力和交互体验(替代 Streamlit)。 |
| API 网关 | FastAPI | 高性能 Python Web 框架,用于连接 Vue 前端与 LangChain 后端。 |
| 环境变量 | python-dotenv | 工程化规范,避免 API Key 硬编码在代码中,保证安全。 |
| 工具库 | Pydantic / Requests | 用于数据验证和网络请求,保证代码的健壮性。 |
Day 1 实战:环境搭建与 Hello World
今天的任务很简单:搭建一个干净、规范的 Python 工程环境,并成功调用大模型。
1. 环境安装
Python 和 VS Code 已经安装完毕,具体安装过程参考【AI开发日记】最新Miniconda+VSCode安装指南。
2. 规划目录结构:先把“抽屉”分好
在写逻辑之前,我先在项目文件夹 emotion_bot 里建好目录:
emotion_bot/
├── .env # 【核心机密】我把 API Key 藏在这里,绝对不能硬编码在代码里
├── main.py # 【启动器】程序的入口,负责把整个系统跑起来
└── src/ # 【逻辑核心】后续所有的功能模块(如记忆、RAG)我都打算放这里
├── __init__.py # (空文件) 加上它,Python 才知道 src 是一个包
└── llm_client.py # 【传话筒】今天只写这个,专门负责连接大模型
3. 第一步:解决“钥匙”的安全问题 (.env)
我这里沿用了后端开发的习惯,用 .env 文件来管理环境变量。
然后申请阿里通义千问的API Key:
1. 访问阿里云官网:https://www.aliyun.com/
2. 登录或注册阿里云账号
3. 进入阿里云控制台
4. 搜索"通义千问"或访问:https://dashscope.console.aliyun.com/
5. 在控制台中找到"API Key管理"
6. 点击"创建新的API Key"
7. 保存生成的API Key
在根目录下建了个 .env 文件,填入刚申请到的API Key:
# 阿里通义千问 API 配置
DASHSCOPE_API_KEY=sk-your-real-key-here
BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
4. 第二步:封装大模型客户端 (src/llm_client.py)
这里写了一个 LLMClient 类,因为现在的模型是 阿里通义千问,如果后期要换成 GPT-4 或者 Claude ,把变化隔离在这个类里,外面的代码就不用动了。
import os
from openai import OpenAI # 虽然用 阿里通义千问,但它兼容 OpenAI 的 SDK,这点很方便
from dotenv import load_dotenv # 专门用来读取 .env 文件的工具
class LLMClient:
def __init__(self):
"""
初始化:程序启动时,先把'电话线'插好
"""
# 1. 既然用了 .env,启动时得先把它加载到系统的环境变量里
load_dotenv()
# 2. 从环境变量里取阿里通义千问的钥匙
# 这样做的好处是,代码里没有任何敏感信息,发给谁都安全。
self.api_key = os.getenv("DASHSCOPE_API_KEY")
self.base_url = os.getenv("BASE_URL")
# 3. 实例化 OpenAI 客户端
# 这就是实际干活的'工人',以后所有请求都通过它发送
if not self.api_key:
# 如果没读到 Key,直接报错,别往下跑了
raise ValueError("❌ 坏了,找不到 API Key,快去检查 .env 文件!")
self.client = OpenAI(
api_key=self.api_key,
base_url=self.base_url
)
print("✅ 大模型连接通道已建立...")
def one_chat(self, user_input):
"""
定义最简单的单轮对话:我发一条,它回一条
"""
try:
# 这里的 create 方法是标准的 API 调用方式
response = self.client.chat.completions.create(
model="qwen-plus", # 阿里通义千问模型名称
# messages 是最关键的参数,是一个列表
# 后面几天我要重点在这个列表里做文章(比如加记忆、加Prompt)
messages=[
# system: 给 AI 设定情感聊天人设
{"role": "system", "content": "你是一个温暖贴心的情感陪伴AI助手,善于倾听和安慰他人。"},
# user: 把我说的话传给它
{"role": "user", "content": user_input}
]
)
# API 返回的是一坨很复杂的 JSON 数据
# 我们只需要拿到 content 字段,也就是 AI 真正说的话
return response.choices[0].message.content
except Exception as e:
# 作为一个老鸟,捕获异常是肌肉记忆
# 万一断网了,程序别崩,把错误打出来给我看
return f"❌ 调用翻车了: {str(e)}"
5. 第三步:跑通主流程 (main.py)
有了上面的 LLMClient,main.py 就变得非常清爽了。它的职责很简单:接受我的输入 -> 扔给 Client -> 打印 AI 的回复。
# 引入刚才写好的类
from src.llm_client import LLMClient
def main():
# 1. 初始化客户端
bot = LLMClient()
print("\n" + "="*50)
print("🤖 AI: 你好!我是你的情感机器人原型机 (v0.1)。")
print("💡 输入 'exit' 可以结束对话。")
print("="*50 + "\n")
# 2. 开启一个死循环,模拟聊天窗口
while True:
# 获取键盘输入
user_input = input("Me: ")
# 给自己留个后门,输入 exit 就能优雅退出
if user_input.lower() in ["exit", "quit"]:
print("🤖 AI: 溜了溜了,下次见!")
break
# 只要不是空话,就发给 AI 处理
if user_input.strip():
reply = bot.one_chat(user_input)
print(f"🤖 AI: {reply}\n")
# 标准的 Python 启动写法
if __name__ == "__main__":
main()
6. 激动的时刻:它活了!
做完这一切,我在终端敲下了 python main.py。
说实话,虽然做了十几年开发,但看到终端里蹦出 AI 回复的那一刻,还是有一种久违的兴奋感——这感觉就像当年第一次写出 Java 的 Hello World 一样。
✅ 大模型连接通道已建立...
==================================================
🤖 AI: 你好!我是你的情感机器人原型机 (v0.1)。
💡 输入 'exit' 可以结束对话。
==================================================
Me: 你好,你是谁?
🤖 AI: 你好!我是一个人工智能助手。虽然我现在还很简单,但我会不断学习的!
Me: exit
🤖 AI: 溜了溜了,下次见!
五、 从“复读机”到“智能体”
今天的代码其实逻辑很简单,本质就是调了一个 API。但通过目录分层、环境隔离和类封装,我为后面 14 天的“添砖加瓦”打下了一个干净的地基。
现在的它虽然能说话,但还只是个**“没有感情的杀手”**(记不住事,也没性格)。
明天(Day 2),我要通过 Prompt Engineering(提示词工程),给它注入“灵魂”。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)