diff --git a/README.md b/README.md index 00bafb0..fa77707 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,11 @@ 本课程通过 AI 代码编辑器(如 Cursor、Windsurf)进行 **Vibe Coding**,让学生体验"用自然语言编程"的全新开发方式。但更重要的是,在这个过程中**思考人与 AI 的协作边界**,培养 AI 时代真正不可替代的能力。 **技术栈**: -- 🐍 **Python 3.10+** -- 🤖 **DeepSeek API**(大语言模型) -- 🎨 **Streamlit**(Web 界面框架) -- 🛠️ **Cursor / Windsurf**(AI 代码编辑器) +- 🐍 **Python 3.14+** (2026 Stable) +- ⚡ **uv** (极速 Python 项目管理) +- 🤖 **DeepSeek API** + **PydanticAI** (Agent 框架) +- 🎨 **Streamlit** (Data Apps) / **Chainlit** (Chatbots) +- 🛠️ **Cursor / Windsurf** (AI 代码编辑器) --- @@ -32,6 +33,27 @@ --- +## 🛠️ 第0天:环境预备 (Day 0) + +> [!IMPORTANT] +> **请在正式上课前完成以下准备**。这能让你在第一天直接进入"Vibe Coding"状态,而不是卡在安装软件上。 + +### 1. 软件安装清单 +- **Code Editor**: 推荐 [Cursor](https://cursor.com) (自带 AI) 或 VS Code + Windsurf 插件, [TRAE CN](https://www.trae.cn)。 +- **Python 3.14+**: 访问 [python.org](https://www.python.org/downloads/) 下载。 +- **uv**: 极速 Python 包管理器 (比 pip 快 10-100 倍)。 + - Mac/Linux: `curl -LsSf https://astral.sh/uv/install.sh | sh` + - Windows: `powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"` + +### 2. 验证环境 +在终端 (Terminal) 输入以下命令,看到版本号即成功: +```bash +python --version # 应显示 Python 3.14.x +uv --version # 应显示 uv 0.x.x +``` + +--- + ## 📚 第1天:课程讲解与演示(3学时) ### 1.1 课程导入(30分钟) @@ -41,6 +63,21 @@ - **核心逻辑**:"描述你想要什么,而不是告诉计算机怎么做"。 - **演示**:用自然语言在 3 分钟内创建一个完整应用。 +#### 为什么要学 Python 基础?(The "Why" in AI Era) + +很多同学会问:*"既然 AI 能写代码,我为什么还要学基础语法?"* + +> **即使是法拉利,也需要懂驾驶原理的赛车手。** + +在 Vibe Coding 中,你需要具备**两种核心能力**才能驾驭 AI: +1. **准确描述 (Prompting)**: 你需要懂一点术语 (如 "List", "Loop", "Function") 才能精准指挥 AI。 +2. **验证结果 (Auditing)**: AI 会犯错 (幻觉)。你需要能读懂代码,判断它是不是在"一本正经地胡说八道"。 + +**重点掌握:** +* **0-Based Indexing**: 为什么计算机从 0 开始数数?(因为偏移量的概念)。 +* **逻辑控制**: `if`, `for`, `while` 是所有程序的骨架。 +* **函数思维**: 把大问题拆解成小模块 (Input -> Process -> Output)。 + #### AI 时代,什么能力真正属于你? > **AI 能做的事越来越多:** 语法查询、代码生成、Bug 修复、文档撰写、测试创建、架构建议、代码重构... @@ -57,14 +94,53 @@ #### AI 代码编辑器介绍 - **Cursor**:[https://cursor.com](https://cursor.com) - **Windsurf**:[https://codeium.com/windsurf](https://codeium.com/windsurf) +- **TRAE CN**:[https://www.trae.cn](https://www.trae.cn) - **核心模式**: - **Approve/Reject**:人是最终的决策者。 - **Context Awareness**:如何让 AI "看见"你的整个项目。 -### 1.2 技术栈讲解(60分钟) +### 1.2 Vibe Coding 快速上手:新手四步法 (The 4-Step Loop) -#### DeepSeek API 快速入门 +对于 0 基础的新手,不要试图一次性写出完美代码。请遵循 **"D-P-R-I"** 循环: + +1. **Define (定义)**:用一句话说清楚你要做什么。 + * ❌ *"写个程序"* + * ✅ *"写一个倒计时器,要有开始/暂停按钮,时间到了会弹窗提示"* +2. **Prompt (提示)**:扮演产品经理,给 AI 下指令。 + * **公式**:`角色 + 任务 + 限制条件` + * *例:"你是一个 Python 专家。请用 Streamlit 写一个 番茄钟应用。要求:界面简洁,背景是黑色,使用 Session State 记录时间。"* +3. **Review (审查)**:AI 写完后,不要盲目运行。 + * **一眼定真**:代码里有没有显然的红色波浪线 (报错)? + * **结构检查**:有没有 `import`?有没有主函数? +4. **Iterate (迭代)**:运行 -> 报错 -> 把报错扔给 AI。 + * *"Vibe Coding 的精髓不在于一次写对,而在于快速试错。"* + * **黄金法则**:如果 AI 连续改 3 次还没修好,**停下来**!这通常意味着你的 Prompt 逻辑有问题,或者方向错了。 + +### 1.3 技术栈讲解(60分钟) + +#### ⚡ 2026 现代 Python 工作流 (uv) + +我们将告别繁琐的 `pip` 和虚拟环境配置,使用 Rust 编写的 **uv** 作为唯一工具。 + +**核心三步走 (The 3-Step Vibe)**: + +1. **初始化 (Init)**: 创建一个干净的"代码工作台"。 + ```bash + uv init my-ai-app + cd my-ai-app + ``` +2. **添加工具 (Add)**: 就像给手机装 App 一样简单。 + ```bash + uv add streamlit chainlit openai python-dotenv + ``` +3. **运行 (Run)**: 一键启动,无需担心环境冲突。 + ```bash + uv run main.py + ``` + +#### DeepSeek API 快速入门 (使用 OpenAI SDK) ```python +# 推荐使用 uv 管理依赖: uv add openai from openai import OpenAI # 初始化客户端 @@ -73,75 +149,188 @@ client = OpenAI( base_url="https://api.deepseek.com" ) -# 发送请求 +# ... (代码保持不变) +``` + +> [!TIP] +> **进阶选择**:对于复杂的 Agent 开发,推荐使用 **PydanticAI**,它能提供更好的类型安全和结构化输出支持。 + +#### Streamlit vs Chainlit + +- **Streamlit**: 适合构建 **数据仪表板**、**工具类应用** (如 Excel 处理、图表分析)。 +- **Chainlit**: 适合构建 **聊天机器人**、**多轮对话 Agent** (自带优美的聊天界面)。 + +**Streamlit 示例 (数据应用)**: +```python +import streamlit as st + +st.title("数据分析看板") +st.line_chart([1, 5, 2, 6]) +``` + +**Chainlit 示例 (对话应用)**: +```python +import chainlit as cl + +@cl.on_message +async def main(message: cl.Message): + # 这里调用 DeepSeek API + await cl.Message(content=f"你说了: {message.content}").send() +``` + +### 1.4 动手实践:三个"最小可运行"示例 (MVP Hands-on) + +接下来的 45 分钟,请跟随老师在你的电脑上运行这三个示例。这是你迈向 Vibe Coding 的第一步。 + +> [!NOTE] +> **准备工作**: +> 确保你已经初始化了项目并填入了 Key: +> ```bash +> mkdir day1-demo +> cd day1-demo +> uv init +> uv add openai python-dotenv streamlit chainlit +> # 创建 .env 文件并填入: DEEPSEEK_API_KEY=sk-xxxxxx +> ``` + +#### 示例 A: Hello AI (CLI 脚本) +**目标**:理解 OpenAI SDK 的最基本调用方式。 +**文件**:`main.py` + +```python +import os +from openai import OpenAI +from dotenv import load_dotenv + +# 1. 加载环境变量 (.env) +load_dotenv() +api_key = os.getenv("DEEPSEEK_API_KEY") + +if not api_key: + print("❌ 错误:未找到 DEEPSEEK_API_KEY,请检查 .env 文件") + exit() + +# 2. 初始化客户端 +client = OpenAI(api_key=api_key, base_url="https://api.deepseek.com") + +# 3. 发送请求 +print("🤖 AI 正在思考...") response = client.chat.completions.create( - model="deepseek-chat", # 使用 V3 模型 + model="deepseek-chat", messages=[ - {"role": "system", "content": "你是一个有帮助的助手"}, - {"role": "user", "content": "你好!"} + {"role": "system", "content": "你是一个赛博朋克风格的诗人。"}, + {"role": "user", "content": "用两句话描述代码的魅力。"}, ], stream=False ) +# 4. 输出结果 +print("\n" + "="*30) print(response.choices[0].message.content) +print("="*30 + "\n") +``` +**运行**: +```bash +uv run main.py ``` -> [!WARNING] -> **API Key 安全**: -> 绝对不要按将 API Key 直接提交到 GitHub 等公共仓库!请使用 `.env` 文件配合 `.gitignore` 管理。 +#### 示例 B: 魔法文案生成器 (Streamlit) +**目标**:不写 HTML/CSS,用 Python 5分钟构建可视化的 AI 应用。 +**文件**:`app_gui.py` -**关键概念**: -- **API Key**:你的"通行证",注意保密。 -- **Messages**:对话历史的列表,包含 system(人设)、user(用户)、assistant(AI)。 -- **Stream**:流式输出,提升用户体验(像打字机一样显示)。 - -#### Streamlit 快速入门 ```python import streamlit as st +import os +from openai import OpenAI +from dotenv import load_dotenv -st.title("我的第一个 Streamlit 应用") +load_dotenv() +client = OpenAI(api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com") -# 侧边栏 +# 1. 页面配置 +st.set_page_config(page_title="魔法文案生成器", page_icon="✨") +st.title("✨ 魔法文案生成器") + +# 2. 左侧侧边栏 with st.sidebar: - st.write("这是侧边栏") + st.header("配置") + style = st.selectbox("选择风格", ["文艺风", "幽默风", "硬核科技风", "发疯文学"]) + length = st.slider("字数限制", 50, 200, 100) -# 输入框 -user_input = st.text_input("请输入你的问题:") +# 3. 主界面输入 +theme = st.text_input("你想写关于什么主题的文案?", placeholder="例如:周五下班、喝咖啡、新发型") -# 按钮与交互 -if st.button("提交"): - if user_input: - st.write(f"你输入了:{user_input}") +# 4. 按钮与 AI 调用 +if st.button("🪄 生成文案"): + if not theme: + st.warning("请先输入主题!") else: - st.warning("请输入内容!") + with st.spinner("AI 正在榨干脑汁..."): + try: + prompt = f"请用{style}写一段关于'{theme}'的朋友圈文案,带Emoji,{length}字以内。" + + response = client.chat.completions.create( + model="deepseek-chat", + messages=[{"role": "user", "content": prompt}] + ) + result = response.choices[0].message.content + + st.success("生成成功!") + st.markdown(f"### 📝 结果:\n{result}") + except Exception as e: + st.error(f"发生错误:{e}") +``` +**运行**: +```bash +uv run streamlit run app_gui.py ``` -**常用组件**: -- 🛠️ **输入**:`st.text_input`, `st.text_area`, `st.slider` -- 📄 **输出**:`st.write`, `st.markdown`, `st.chat_message` -- 🎒 **状态**:`st.session_state` (用于记住对话历史) +#### 示例 C: 会聊天的猫 (Chainlit) +**目标**:构建像 ChatGPT 一样的对话界面,支持流式输出 (Streaming)。 +**文件**:`app_chat.py` -### 1.3 完整示例演示(45分钟) +```python +import chainlit as cl +import os +from openai import OpenAI +from dotenv import load_dotenv -#### 现场演示:用 Vibe Coding 构建一个 AI 聊天应用 +load_dotenv() +client = OpenAI(api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com") -**演示步骤**: -1. **Init**:新建文件夹,用自然语言让 AI 初始化环境。 -2. **Draft**:描述核心需求,生成 1.0 版本代码。 -3. **Refine**: - - 添加对话历史记忆(Session State)。 - - 开启流式输出(Streaming)。 - - 优化 UI(添加侧边栏设置)。 -4. **Deploy**:运行并测试。 +@cl.on_message +async def main(message: cl.Message): + # 1. 准备消息历史 + # (注意:实际项目中需要维护 st.session_state 或 cl.user_session 来保留上下文,这里仅演示单轮回复) + msg_history = [ + {"role": "system", "content": "你是一只高冷的猫,说话句尾要带'喵'。"}, + {"role": "user", "content": message.content} + ] + + # 2. 创建回复消息容器 + msg = cl.Message(content="") + await msg.send() + + # 3. 调用 AI 并流式(stream)接收 + stream = client.chat.completions.create( + model="deepseek-chat", + messages=msg_history, + stream=True + ) + + for chunk in stream: + if token := chunk.choices[0].delta.content: + await msg.stream_token(token) + + # 4. 完成更新 + await msg.update() +``` +**运行**: +```bash +uv run chainlit run app_chat.py -w +``` -**示例 Prompt**: -> "帮我创建一个基于 DeepSeek API 的聊天应用,使用 Streamlit 构建界面。要求: -> 1. 支持多轮对话,保留对话历史 -> 2. 使用流式输出,打字机效果显示回复 -> 3. 左侧边栏可以设置系统提示词 -> 4. 界面美观,有清空对话的按钮" - -### 1.4 项目要求说明(15分钟) +### 1.5 项目要求说明(15分钟) #### 项目选题(任选其一或自拟) @@ -161,6 +350,27 @@ if st.button("提交"): > 💡 **选题思考**:不只是"我能做什么",更要思考"这个项目**对谁有价值**?解决什么**真实问题**?" +#### 🚀 从 0 到 1:如何开始?(Starter Kit) + +面对空白的代码编辑器感到迷茫?请按以下步骤操作: + +**Step 1: 只要写出 README.md,你就完成了一半** +不要急着写代码。先用自然语言在 `Project_Design.md` (或草稿纸) 上写下: +1. **一句话描述**:我的应用叫什么?它是给谁用的? +2. **核心功能**:它*必须*有的 3 个功能是什么?(MVP) +3. **交互流程**:用户打开 App -> 点击什么 -> 看到什么? + +**Step 2: 让 AI 写第一行代码** +把Step 1的内容喂给 Cursor/Windsurf: +> *"我正在开发一个[项目名]。请阅读我的设计思路:[粘贴你的描述]。请帮我生成项目结构,并创建最基础的 app.py 框架。"* + +**Step 3: 最小可行性验证** +* 生成的代码能跑吗?(Run it) +* 界面上能看到按钮吗?(See it) +* 如果报错,直接把报错信息截图或复制给 AI。 + +> **记住**:你是在搭建积木,不是在烧制砖块。先搭出轮廓,再修饰细节。 + --- ## 🔧 第2天:自主开发 @@ -281,7 +491,7 @@ AI 不是神,它需要知道你的代码、你的报错、你的意图。 ### 1. 提交材料 1. **源代码**:完整项目文件夹。 2. **README.md**:项目说明文档。 -3. **requirements.txt**:`pip freeze > requirements.txt` 生成。 +3. **依赖文件**:包含 `pyproject.toml` 和 `uv.lock` (确保别人可以用 `uv sync` 还原你的环境)。 4. **开发心得**:Markdown 格式,**不少于 500 字**。 ### 2. README.md 模板 @@ -292,9 +502,9 @@ AI 不是神,它需要知道你的代码、你的报错、你的意图。 这句话介绍你的项目是做什么的,解决了什么问题。 ## 如何运行 -1. 安装依赖:`pip install -r requirements.txt` +1. 安装依赖:`uv sync` 2. 配置 Key:复制 `.env.example` 为 `.env` 并填入 Key。 -3. 运行:`streamlit run app.py` +3. 运行:`uv run streamlit run app.py` ## 功能列表 - [x] 功能 A @@ -321,21 +531,28 @@ AI 不是神,它需要知道你的代码、你的报错、你的意图。 ## 🔗 附录:环境配置指南 ### 1. 基础环境 -- **Python**:推荐 3.10+ ([官网下载](https://www.python.org/downloads/)) -- **编辑器**:推荐 Cursor 或 VS Code + Windsurf 插件。 +- **Python**: 推荐 3.14+ (2026 Stable) +- **依赖管理**: **uv** (强烈推荐,替代 pip/venv) +- **编辑器**: 推荐 Cursor 或 VS Code + Windsurf 插件。 -### 2. 项目初始化命令 +### 2. 项目初始化 (使用 uv) ```bash -# 1. 创建虚拟环境 (Windows) -python -m venv venv -.\venv\Scripts\activate +# 1. 安装 uv (MacOS/Linux) +curl -LsSf https://astral.sh/uv/install.sh | sh +# Windows: powershell -c "irm https://astral.sh/uv/install.ps1 | iex" -# 1. 创建虚拟环境 (Mac/Linux) -python3 -m venv venv -source venv/bin/activate +# 2. 初始化项目 +mkdir my-ai-app +cd my-ai-app +uv init -# 2. 安装核心库 -pip install streamlit openai python-dotenv +# 3. 添加依赖 +uv add streamlit chainlit openai python-dotenv + +# 4. 运行应用 +uv run streamlit run app.py +# 或 +uv run chainlit run app.py -w ``` ### 3. API Key 管理示例 (`.env`) @@ -347,6 +564,7 @@ DEEPSEEK_API_KEY=sk-xxxxxxx ```python # app.py import os +# uv add python-dotenv from dotenv import load_dotenv load_dotenv() # 加载 .env diff --git a/示例项目-AI数据分析师/.env-example b/示例项目-AI数据分析师/.env-example deleted file mode 100644 index 9b9185e..0000000 --- a/示例项目-AI数据分析师/.env-example +++ /dev/null @@ -1,9 +0,0 @@ -# DeepSeek API Key 配置示例 -# ================================ -# 使用方法: -# 1. 将此文件复制并重命名为 .env -# 2. 将下面的 sk-xxx... 替换为你的真实 API Key -# ================================ - -DEEPSEEK_API_KEY=sk-xxxxx - diff --git a/示例项目-AI数据分析师/.gitignore b/示例项目-AI数据分析师/.gitignore deleted file mode 100644 index b7fca19..0000000 --- a/示例项目-AI数据分析师/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# 环境变量(包含敏感信息) -.env - -# Python -__pycache__/ -*.py[cod] -*$py.class -*.so -.Python -venv/ -ENV/ - -# IDE -.vscode/ -.idea/ -*.swp -*.swo - -# macOS -.DS_Store - -# 临时文件 -*.tmp -*.log - diff --git a/示例项目-AI数据分析师/README.md b/示例项目-AI数据分析师/README.md deleted file mode 100644 index ee38b9a..0000000 --- a/示例项目-AI数据分析师/README.md +++ /dev/null @@ -1,314 +0,0 @@ -# 📊 AI 数据分析师 - -一个基于 DeepSeek API + Streamlit 的智能数据分析平台,上传 CSV 数据即可获得 AI 驱动的深度洞察和可视化报告。 - - - - - - -## ✨ 功能特性 - -| 功能 | 描述 | -|:---|:---| -| 📈 **数据预览** | 数据表格展示、统计摘要、列信息分析 | -| 📊 **智能可视化** | 根据数据类型自动生成直方图、散点图、箱线图、热力图 | -| 🤖 **AI 深度分析** | 综合分析、相关性分析、异常检测三种模式 | -| 💬 **自然语言问答** | 用中文直接询问关于数据的任何问题 | -| 📝 **报告生成** | 一键生成完整的 Markdown 格式分析报告并下载 | - -## 🖼️ 界面预览 - -``` -┌────────────────────────────────────────────────────────────────────┐ -│ 📊 AI 数据分析师 │ -│ 上传数据,让 AI 帮你发现数据中的故事 │ -├────────────────────────────────────────────────────────────────────┤ -│ [📈 数据预览] [📊 智能可视化] [🤖 AI 分析] [💬 数据问答] [📝 生成报告] │ -├────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ -│ │ 100 │ │ 7 │ │ 0 │ │ 5 │ │ -│ │ 数据行 │ │ 数据列 │ │ 缺失值 │ │ 数值列 │ │ -│ └──────┘ └──────┘ └──────┘ └──────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────┐ │ -│ │ 姓名 │ 部门 │ 年龄 │ 工龄 │ 月薪 │ 绩效评分 │ 满意度 │ │ -│ │ 张三 │ 技术部 │ 28 │ 3 │ 15000 │ 85.5 │ 4.2 │ │ -│ │ 李四 │ 市场部 │ 32 │ 5 │ 18000 │ 78.3 │ 3.8 │ │ -│ │ ... │ ... │ ... │ ... │ ... │ ... │ ... │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ │ -└────────────────────────────────────────────────────────────────────┘ -``` - -## 🚀 快速开始 - -### 1. 进入项目目录 - -```bash -cd 示例项目-AI数据分析师 -``` - -### 2. 创建虚拟环境(推荐) - -```bash -python -m venv venv - -# Windows -venv\Scripts\activate - -# macOS/Linux -source venv/bin/activate -``` - -### 3. 安装依赖 - -```bash -pip install -r requirements.txt -``` - -### 4. 配置 API Key - -创建 `.env` 文件: - -```bash -echo "DEEPSEEK_API_KEY=sk-your-api-key" > .env -``` - -或直接在应用界面的侧边栏输入 API Key。 - -### 5. 运行应用 - -```bash -streamlit run app.py -``` - -浏览器会自动打开 http://localhost:8501 - -## 📁 项目结构 - -``` -示例项目-AI数据分析师/ -├── app.py # 主程序 (~600行) -├── requirements.txt # 项目依赖 -├── sample_data.csv # 示例数据(员工信息) -├── .env # 环境变量(需自行创建) -├── .gitignore # Git 忽略文件 -└── README.md # 项目说明 -``` - -## 🛠️ 技术架构 - -``` -┌─────────────────────────────────────────────────────────┐ -│ Streamlit UI │ -│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ -│ │数据预览 │ │智能可视化│ │ AI分析 │ │数据问答 │ │ -│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ -│ │ │ │ │ │ -├───────┼───────────┼───────────┼───────────┼─────────────┤ -│ ▼ ▼ ▼ ▼ │ -│ ┌─────────────────────────────────────────────────┐ │ -│ │ Pandas DataFrame │ │ -│ │ (数据处理与统计分析) │ │ -│ └─────────────────────────────────────────────────┘ │ -│ │ │ │ -│ ▼ ▼ │ -│ ┌─────────┐ ┌─────────────────────────────────────┐ │ -│ │ Altair │ │ DeepSeek API │ │ -│ │ (可视化)│ │ (AI 分析 / 问答 / 报告生成) │ │ -│ └─────────┘ └─────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────┘ -``` - -## 🔑 核心技术点 - -### 1. 数据处理与摘要生成 - -```python -def get_data_summary(df: pd.DataFrame) -> str: - """生成数据摘要供 AI 分析""" - summary = [] - - # 基本信息 - summary.append(f"数据集包含 {len(df)} 行和 {len(df.columns)} 列。") - - # 数值列统计 - numeric_cols = df.select_dtypes(include=['number']).columns - stats = df[numeric_cols].describe().to_string() - - # ... 更多统计信息 - return "\n".join(summary) -``` - -### 2. AI 分析的 Prompt 工程 - -```python -def analyze_with_ai(client, data_summary, analysis_type): - prompts = { - "general": """你是一个专业的数据分析师... -请从以下几个方面进行分析: -1. 📊 数据概况 -2. 🔍 关键发现 -3. 📈 建议可视化 -4. ⚠️ 注意事项 -5. 💡 进一步分析建议""", - - "correlation": """分析变量之间的相关性...""", - "anomaly": """检测数据中的异常值...""" - } - - response = client.chat.completions.create( - model="deepseek-chat", - messages=[ - {"role": "system", "content": prompts[analysis_type]}, - {"role": "user", "content": f"数据摘要:\n{data_summary}"} - ] - ) - return response.choices[0].message.content -``` - -### 3. 自动可视化生成 - -```python -def create_visualizations(df): - """根据数据类型自动选择合适的图表""" - charts = [] - numeric_cols = df.select_dtypes(include=['number']).columns - cat_cols = df.select_dtypes(include=['object']).columns - - # 数值分布 -> 直方图 - if numeric_cols: - hist_chart = alt.Chart(df).mark_bar().encode( - x=alt.X(f'{col}:Q', bin=True), - y='count()' - ) - charts.append(hist_chart) - - # 多数值变量 -> 散点图 + 相关性热力图 - # 分类+数值 -> 箱线图 - # ... - - return charts -``` - -### 4. 多轮对话的上下文管理 - -```python -def ask_data_question(client, data_summary, question, chat_history): - messages = [ - {"role": "system", "content": "你是数据分析助手..."}, - {"role": "user", "content": f"数据摘要:\n{data_summary}"}, - {"role": "assistant", "content": "我已了解数据,请问您想知道什么?"} - ] - - # 添加历史对话 - for msg in chat_history: - messages.append(msg) - - # 添加当前问题 - messages.append({"role": "user", "content": question}) - - return client.chat.completions.create( - model="deepseek-chat", - messages=messages - ) -``` - -### 5. Session State 管理 - -```python -# 初始化状态 -if "df" not in st.session_state: - st.session_state.df = None -if "analyses" not in st.session_state: - st.session_state.analyses = {} -if "qa_history" not in st.session_state: - st.session_state.qa_history = [] - -# 跨 Tab 共享数据 -df = st.session_state.df -``` - -## 📊 使用的 Streamlit 组件 - -| 组件 | 用途 | -|:---|:---| -| `st.tabs` | 多标签页布局 | -| `st.columns` | 统计卡片布局 | -| `st.file_uploader` | CSV 文件上传 | -| `st.dataframe` | 交互式数据表格 | -| `st.altair_chart` | Altair 图表渲染 | -| `st.chat_message` | 问答对话界面 | -| `st.chat_input` | 聊天输入框 | -| `st.session_state` | 状态管理 | -| `st.download_button` | 报告下载 | -| `st.spinner` | 加载动画 | -| `st.expander` | 可折叠区域 | - -## 🎨 Vibe Coding 开发过程 - -### 初始 Prompt - -> "帮我创建一个 AI 数据分析师应用,使用 DeepSeek API 和 Streamlit。 -> -> 功能需求: -> 1. 上传 CSV 文件,显示数据预览和统计 -> 2. 自动根据数据类型生成可视化图表(用 Altair) -> 3. AI 分析功能:综合分析、相关性分析、异常检测 -> 4. 自然语言问答,可以问关于数据的问题 -> 5. 生成 Markdown 格式的分析报告 -> -> 技术要求: -> - 使用 st.tabs 做多标签页布局 -> - 使用 st.session_state 管理状态 -> - 界面要美观,使用自定义 CSS" - -### 迭代优化 - -``` -Prompt 1: "给数据预览页添加统计卡片,显示行数、列数、缺失值等" - -Prompt 2: "让可视化更智能,根据数据类型自动选择图表类型" - -Prompt 3: "问答功能要支持多轮对话,AI 要记住之前的问题" - -Prompt 4: "报告生成功能要把之前的分析结果都整合进去" - -Prompt 5: "加一个示例数据选项,方便没有数据的用户体验" -``` - -## 🔧 扩展建议 - -如果你想进一步完善这个项目,可以考虑: - -1. **支持更多文件格式**:Excel、JSON、Parquet -2. **添加数据清洗功能**:缺失值处理、异常值处理 -3. **更丰富的可视化**:时间序列图、地理图 -4. **导出更多格式**:PDF、HTML、Word -5. **添加数据筛选器**:让用户选择分析哪些列/行 -6. **机器学习预测**:简单的回归/分类预测功能 - -## ⚠️ 注意事项 - -1. **数据大小**:大数据集(>10万行)可能导致界面卡顿 -2. **API 成本**:长文本分析和多轮问答会消耗更多 Token -3. **隐私安全**:敏感数据请在本地使用,不要上传到公共服务器 -4. **API Key 安全**:不要将 `.env` 提交到代码仓库 - -## 📚 参考资料 - -- [Streamlit 官方文档](https://docs.streamlit.io) -- [Altair 可视化文档](https://altair-viz.github.io) -- [Pandas 数据分析](https://pandas.pydata.org/docs/) -- [DeepSeek API 文档](https://platform.deepseek.com/api-docs) - -## 👤 作者 - -Python 程序设计课程设计 - 高级示例项目 - ---- - -**让数据说话,用 AI 倾听!** 📊🤖 - diff --git a/示例项目-AI数据分析师/app.py b/示例项目-AI数据分析师/app.py deleted file mode 100644 index 21ac70b..0000000 --- a/示例项目-AI数据分析师/app.py +++ /dev/null @@ -1,735 +0,0 @@ -""" -📊 AI 数据分析师 -================== -一个基于 DeepSeek API + Streamlit 的智能数据分析应用 - -功能特性: -- 📁 上传 CSV 数据文件 -- 📈 自动生成可视化图表 -- 🤖 AI 智能分析数据特征 -- 💬 自然语言问答数据 -- 📝 生成分析报告 - -技术栈: -- Streamlit: Web 界面 -- Pandas: 数据处理 -- Altair: 数据可视化 -- DeepSeek API: AI 分析 -""" - -import streamlit as st -import pandas as pd -import altair as alt -import json -from openai import OpenAI -import os -from dotenv import load_dotenv -from io import StringIO - -# 加载环境变量 -load_dotenv() - -# ============== 配置 ============== - -API_KEY = os.getenv("DEEPSEEK_API_KEY", "") -BASE_URL = "https://api.deepseek.com" -MODEL = "deepseek-chat" - -# ============== 页面配置 ============== - -st.set_page_config( - page_title="AI 数据分析师", - page_icon="📊", - layout="wide", - initial_sidebar_state="expanded" -) - -# ============== 自定义样式 ============== - -st.markdown(""" - -""", unsafe_allow_html=True) - -# ============== 辅助函数 ============== - -def get_data_summary(df: pd.DataFrame) -> str: - """生成数据摘要文本供 AI 分析""" - summary = [] - - # 基本信息 - summary.append(f"数据集包含 {len(df)} 行和 {len(df.columns)} 列。") - summary.append(f"\n列名:{', '.join(df.columns.tolist())}") - - # 数据类型 - summary.append(f"\n\n各列数据类型:") - for col in df.columns: - dtype = str(df[col].dtype) - null_count = df[col].isnull().sum() - summary.append(f"- {col}: {dtype}, 缺失值: {null_count}") - - # 数值列统计 - numeric_cols = df.select_dtypes(include=['number']).columns.tolist() - if numeric_cols: - summary.append(f"\n\n数值列统计摘要:") - stats = df[numeric_cols].describe().to_string() - summary.append(stats) - - # 分类列信息 - cat_cols = df.select_dtypes(include=['object', 'category']).columns.tolist() - if cat_cols: - summary.append(f"\n\n分类列信息:") - for col in cat_cols[:5]: # 最多显示5个 - unique_count = df[col].nunique() - top_values = df[col].value_counts().head(5).to_dict() - summary.append(f"- {col}: {unique_count} 个唯一值, 前5个: {top_values}") - - # 样本数据 - summary.append(f"\n\n前3行数据样本:") - summary.append(df.head(3).to_string()) - - return "\n".join(summary) - - -def analyze_with_ai(client: OpenAI, data_summary: str, analysis_type: str = "general") -> str: - """使用 AI 分析数据""" - - prompts = { - "general": """你是一个专业的数据分析师。请根据以下数据摘要,提供全面的数据分析洞察。 - -请从以下几个方面进行分析: -1. 📊 数据概况:数据的整体情况和质量评估 -2. 🔍 关键发现:数据中的重要模式和特征 -3. 📈 建议可视化:推荐适合这个数据集的图表类型 -4. ⚠️ 注意事项:数据中可能存在的问题或需要注意的地方 -5. 💡 进一步分析建议:可以深入探索的方向 - -请用清晰的结构和通俗易懂的语言回答。""", - - "correlation": """你是一个专业的数据分析师。请分析以下数据中各变量之间可能存在的相关性和关联。 - -请重点分析: -1. 哪些变量之间可能存在正相关或负相关? -2. 是否存在明显的因果关系假设? -3. 建议做哪些相关性分析? - -请用通俗易懂的语言解释。""", - - "anomaly": """你是一个专业的数据分析师。请分析以下数据中可能存在的异常值或异常模式。 - -请关注: -1. 数值是否有明显的异常值? -2. 数据分布是否有异常? -3. 是否存在数据质量问题? -4. 建议如何处理这些异常? - -请给出具体的分析和建议。""" - } - - system_prompt = prompts.get(analysis_type, prompts["general"]) - - response = client.chat.completions.create( - model=MODEL, - messages=[ - {"role": "system", "content": system_prompt}, - {"role": "user", "content": f"数据摘要:\n\n{data_summary}"} - ], - max_tokens=2000, - temperature=0.7 - ) - - return response.choices[0].message.content - - -def ask_data_question(client: OpenAI, data_summary: str, question: str, chat_history: list) -> str: - """根据数据回答用户问题""" - - system_prompt = """你是一个专业的数据分析助手。用户会就数据集提出问题,你需要根据提供的数据摘要来回答。 - -回答要求: -1. 基于数据事实回答,不要编造数据中没有的信息 -2. 如果数据摘要中没有足够信息回答问题,请诚实说明 -3. 尽可能提供具体的数字和分析 -4. 可以给出进一步分析的建议""" - - messages = [{"role": "system", "content": system_prompt}] - messages.append({"role": "user", "content": f"数据摘要:\n{data_summary}\n\n请记住这个数据摘要,我接下来会问你关于这个数据的问题。"}) - messages.append({"role": "assistant", "content": "好的,我已经了解了这个数据集的情况。请问您想了解什么?"}) - - # 添加对话历史 - for msg in chat_history: - messages.append(msg) - - # 添加当前问题 - messages.append({"role": "user", "content": question}) - - response = client.chat.completions.create( - model=MODEL, - messages=messages, - max_tokens=1500, - temperature=0.7 - ) - - return response.choices[0].message.content - - -def generate_report(client: OpenAI, data_summary: str, analyses: dict) -> str: - """生成完整的分析报告""" - - system_prompt = """你是一个专业的数据分析师,请根据数据摘要和已有的分析结果,生成一份完整的数据分析报告。 - -报告格式要求: -1. 使用 Markdown 格式 -2. 包含标题、摘要、详细分析、结论和建议 -3. 结构清晰,层次分明 -4. 语言专业但易懂 -5. 适当使用 emoji 增加可读性""" - - user_content = f"""数据摘要: -{data_summary} - -已有分析结果: -{json.dumps(analyses, ensure_ascii=False, indent=2)} - -请生成一份完整的数据分析报告。""" - - response = client.chat.completions.create( - model=MODEL, - messages=[ - {"role": "system", "content": system_prompt}, - {"role": "user", "content": user_content} - ], - max_tokens=3000, - temperature=0.7 - ) - - return response.choices[0].message.content - - -def create_visualizations(df: pd.DataFrame): - """根据数据自动生成可视化图表""" - charts = [] - - numeric_cols = df.select_dtypes(include=['number']).columns.tolist() - cat_cols = df.select_dtypes(include=['object', 'category']).columns.tolist() - - # 1. 数值分布直方图(第一个数值列) - if numeric_cols: - col = numeric_cols[0] - hist_chart = alt.Chart(df).mark_bar( - opacity=0.7, - color='#667eea' - ).encode( - alt.X(f'{col}:Q', bin=alt.Bin(maxbins=30), title=col), - alt.Y('count()', title='频数'), - tooltip=[alt.Tooltip(f'{col}:Q', bin=alt.Bin(maxbins=30)), 'count()'] - ).properties( - title=f'📊 {col} 分布直方图', - height=300 - ) - charts.append(('distribution', hist_chart, f'{col} 的数值分布')) - - # 2. 分类计数柱状图(第一个分类列) - if cat_cols: - col = cat_cols[0] - if df[col].nunique() <= 20: # 类别不要太多 - bar_chart = alt.Chart(df).mark_bar( - color='#764ba2' - ).encode( - x=alt.X(f'{col}:N', sort='-y', title=col), - y=alt.Y('count()', title='计数'), - tooltip=[col, 'count()'] - ).properties( - title=f'📈 {col} 分类计数', - height=300 - ) - charts.append(('category', bar_chart, f'{col} 各类别的计数')) - - # 3. 散点图(如果有多个数值列) - if len(numeric_cols) >= 2: - col1, col2 = numeric_cols[0], numeric_cols[1] - color_col = cat_cols[0] if cat_cols and df[cat_cols[0]].nunique() <= 10 else None - - scatter_encoding = { - 'x': alt.X(f'{col1}:Q', title=col1), - 'y': alt.Y(f'{col2}:Q', title=col2), - 'tooltip': [col1, col2] - } - - if color_col: - scatter_encoding['color'] = alt.Color(f'{color_col}:N', title=color_col) - scatter_encoding['tooltip'].append(color_col) - - scatter_chart = alt.Chart(df).mark_circle( - size=60, - opacity=0.6 - ).encode( - **scatter_encoding - ).properties( - title=f'🔵 {col1} vs {col2} 散点图', - height=350 - ).interactive() - - charts.append(('scatter', scatter_chart, f'{col1} 与 {col2} 的关系')) - - # 4. 箱线图(数值列按分类) - if numeric_cols and cat_cols: - num_col = numeric_cols[0] - cat_col = cat_cols[0] - if df[cat_col].nunique() <= 10: - box_chart = alt.Chart(df).mark_boxplot( - color='#11998e' - ).encode( - x=alt.X(f'{cat_col}:N', title=cat_col), - y=alt.Y(f'{num_col}:Q', title=num_col), - color=alt.Color(f'{cat_col}:N', legend=None) - ).properties( - title=f'📦 {num_col} 按 {cat_col} 分组箱线图', - height=300 - ) - charts.append(('boxplot', box_chart, f'{num_col} 在不同 {cat_col} 下的分布')) - - # 5. 相关性热力图(如果有多个数值列) - if len(numeric_cols) >= 3: - corr_df = df[numeric_cols].corr().reset_index().melt(id_vars='index') - corr_df.columns = ['var1', 'var2', 'correlation'] - - heatmap = alt.Chart(corr_df).mark_rect().encode( - x=alt.X('var1:N', title=''), - y=alt.Y('var2:N', title=''), - color=alt.Color('correlation:Q', - scale=alt.Scale(scheme='redblue', domain=[-1, 1]), - title='相关系数'), - tooltip=['var1', 'var2', alt.Tooltip('correlation:Q', format='.2f')] - ).properties( - title='🔥 相关性热力图', - height=300 - ) - charts.append(('heatmap', heatmap, '各数值变量间的相关性')) - - return charts - - -# ============== 初始化 Session State ============== - -if "df" not in st.session_state: - st.session_state.df = None - -if "data_summary" not in st.session_state: - st.session_state.data_summary = None - -if "analyses" not in st.session_state: - st.session_state.analyses = {} - -if "qa_history" not in st.session_state: - st.session_state.qa_history = [] - -# ============== 侧边栏 ============== - -with st.sidebar: - st.markdown("## 🔧 设置") - - # API Key 输入 - api_key_input = st.text_input( - "DeepSeek API Key", - value=API_KEY, - type="password", - help="输入你的 DeepSeek API Key" - ) - - if api_key_input: - API_KEY = api_key_input - - st.divider() - - # 文件上传 - st.markdown("## 📁 数据上传") - - uploaded_file = st.file_uploader( - "上传 CSV 文件", - type=['csv'], - help="支持 CSV 格式的数据文件" - ) - - # 或使用示例数据 - use_sample = st.checkbox("使用示例数据", value=False) - - if use_sample: - # 生成示例数据 - import numpy as np - np.random.seed(42) - - sample_df = pd.DataFrame({ - '姓名': [f'员工{i}' for i in range(1, 101)], - '部门': np.random.choice(['技术部', '市场部', '财务部', '人事部', '运营部'], 100), - '年龄': np.random.randint(22, 55, 100), - '工龄': np.random.randint(1, 20, 100), - '月薪': np.random.randint(8000, 50000, 100), - '绩效评分': np.round(np.random.uniform(60, 100, 100), 1), - '满意度': np.round(np.random.uniform(1, 5, 100), 1) - }) - - st.session_state.df = sample_df - st.session_state.data_summary = get_data_summary(sample_df) - st.success("✅ 已加载示例数据") - - elif uploaded_file is not None: - try: - df = pd.read_csv(uploaded_file) - st.session_state.df = df - st.session_state.data_summary = get_data_summary(df) - st.session_state.analyses = {} # 重置分析结果 - st.session_state.qa_history = [] # 重置问答历史 - st.success(f"✅ 成功加载 {len(df)} 行数据") - except Exception as e: - st.error(f"❌ 文件加载失败: {str(e)}") - - # 显示数据信息 - if st.session_state.df is not None: - st.divider() - st.markdown("### 📊 数据概览") - df = st.session_state.df - st.markdown(f"- **行数**: {len(df)}") - st.markdown(f"- **列数**: {len(df.columns)}") - st.markdown(f"- **数值列**: {len(df.select_dtypes(include=['number']).columns)}") - st.markdown(f"- **分类列**: {len(df.select_dtypes(include=['object', 'category']).columns)}") - -# ============== 主界面 ============== - -st.markdown('
数据行数
-数据列数
-缺失值数量
-数值列数量
-{config['system_prompt'][:100]}...
-