From 65b43da03b2bcb8794de2496a6a4af0af2cbbb11 Mon Sep 17 00:00:00 2001 From: kennethcheng Date: Tue, 14 Apr 2026 03:19:18 +0800 Subject: [PATCH] v0.0.6 Ollama --- .env | 11 +- README.md | 54 ++++++-- ollama/llm_benchmark_dashboard_v2.html | 178 +++++++++++++++++++++++++ ollama/llm_benchmark_report_v2.md | 27 ++++ ollama/ollama_rich_chat.py | 76 +++++++++++ ollama/tps_monitor.py | 58 ++++++++ 6 files changed, 390 insertions(+), 14 deletions(-) create mode 100644 ollama/llm_benchmark_dashboard_v2.html create mode 100644 ollama/llm_benchmark_report_v2.md create mode 100644 ollama/ollama_rich_chat.py create mode 100644 ollama/tps_monitor.py diff --git a/.env b/.env index 33b2068..7617490 100644 --- a/.env +++ b/.env @@ -1,4 +1,13 @@ # Qwen/Qwen3.5-4B # deepseek-ai/DeepSeek-R1-0528-Qwen3-8B SILICONFLOW_API_KEY = "sk-sylilrjrtxlvecwhfusjkutclmppzuzhncfcfxtekxrzyjee" -SILICONFLOW_BASE_URL = "https://api.siliconflow.cn/v1" \ No newline at end of file +SILICONFLOW_BASE_URL = "https://api.siliconflow.cn/v1" + +OLLAMA_API_KEY = "ollama" +OLLAMA_BASE_URL = "http://localhost:11434/v1" + +MINIMAX_API_KEY = "sk-cp-wWkzvRP-BiQia-6izxvqgehEsHSz8v4_PtDJAuT3OI0s8QFcEOsxIHcQoZC2cVQTK3L09EUuu5HDArYMvKXFnf91jk8LuZ0tteS7-Wd4Lk2zDm8RqrKkrd4" +MINIMAX_BASE_URL = "https://api.minimaxi.com/v1" + +BAILIAN_API_KEY = "sk-8c8bec7a613249dbbed08bc3affeef72" +BAILIAN_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1" \ No newline at end of file diff --git a/README.md b/README.md index c446613..00fb49a 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,21 @@ # LangChain Learning -[![](https://img.shields.io/badge/version-0.0.5-blue.svg)](https://github.com/your-repo/langchain-learning) +[![](https://img.shields.io/badge/version-0.0.6-blue.svg)](https://github.com/your-repo/langchain-learning) [![](https://img.shields.io/badge/python-3.11+-green.svg)](https://www.python.org/) [![](https://img.shields.io/badge/LangChain-v1.2-orange.svg)](https://www.langchain.com/) -> LangChain 框架学习项目,集成 SiliconFlow API +> LangChain 框架学习项目,集成 SiliconFlow & Ollama API ## 功能特性 -- **多 LLM 集成**:支持 OpenAI API、Silicon Flow 及 LangChain 抽象层 +- **多 LLM 集成**:支持 OpenAI API、SiliconFlow、Ollama 及 LangChain 抽象层 - **流式响应**:实时流式输出,带来更好的使用体验 - **Prompt 工程**:多种 Prompt 模板构建方式 - **输出解析**:支持 JSON 等格式解析 - **Token 用量追踪**:轻松监控 API 调用消耗 - **内存管理**:实现对话历史持久化(ConversationBufferMemory, SummaryMemory) +- **Rich 终端界面**:支持 Markdown 渲染、多行输入等高级交互 +- **模型测速工具**:测试模型的首字延迟 (TTFT) 和每秒生成速度 (TPS) - **实战示例**:从基础到进阶的使用模式 ## 快速开始 @@ -21,18 +23,21 @@ ### 1. 安装依赖 ```bash -pip install langchain>=1.2.15 langchain-community>=0.4.1 langchain-siliconflow>=1.0.0 requests>=2.33.1 +pip install langchain>=1.2.15 langchain-community>=0.4.1 langchain-siliconflow>=1.0.0 requests>=2.33.1 rich openai ``` -***注意:*** *如果需要完整的记忆功能和更高级的模型,你可能需要安装额外的库。* - ### 2. 配置环境变量 在项目根目录创建 `.env` 文件: ```env +# SiliconFlow SILICONFLOW_API_KEY=your_api_key_here SILICONFLOW_BASE_URL=https://api.siliconflow.cn/v1 + +# Ollama / 本地模型 +OLLAMA_BASE_URL=http://localhost:11434/v1 +OLLAMA_API_KEY=ollama ``` ### 3. 运行示例 @@ -70,8 +75,17 @@ SILICONFLOW_BASE_URL=https://api.siliconflow.cn/v1 | 示例 | 命令 | 说明 | |------|------|------| -| 基础记忆 | `python memory/memory_desc.py` | 演示不同类型的 Memory 对象。| -| 带内存聊天 | `python memory/with_memory_demo.py` | 在对话链中管理和利用聊天历史记录。 | +| 基础记忆 | `python memory/memory_desc.py` | 演示不同类型的 Memory 对象 | +| 带内存聊天 | `python memory/memory_demo.py` | 使用 ConversationBufferMemory 进行多轮对话 | +| 无内存聊天 | `python memory/without_memory_demo.py` | 基础 LLM 聊天,无历史上下文 | +| Rich 界面聊天 | `python memory/without_memory_demo_rich.py` | 使用 Rich 美化的无内存聊天界面 | + +**Ollama 示例** + +| 示例 | 命令 | 说明 | +|------|------|------| +| Rich 流式聊天 | `python ollama/ollama_rich_chat.py` | 支持 Markdown 渲染、多行输入的流式聊天 | +| 模型测速工具 | `python ollama/tps_monitor.py` | 测量模型的 TTFT 和 TPS 性能 | ## 项目结构 @@ -86,14 +100,21 @@ langchain-learning/ │ ├── prompt_demo.py # PromptTemplate 模板示例 │ ├── fewshot_demo.py # Few-shot Learning 示例 │ ├── promt_from_file.py # 从文件加载 Prompt -│ └── prompt_from_file.yaml # Prompt 模板文件 +│ ├── prompt_from_file.yaml # Prompt YAML 模板文件 +│ └── prompt_from_file.json # Prompt JSON 模板文件 ├── parser/ │ └── json_parser_demo.py # JSON 输出解析示例 ├── token/ │ └── token_demo.py # Token 用量追踪示例 -├── memory/ # 记忆管理模块 +├── memory/ │ ├── memory_desc.py # 演示 Memory 对象类型 -│ └── with_memory_do.py # 演示使用带内存的聊天循环 +│ ├── memory_demo.py # 带内存的对话链示例 +│ ├── with_memory_demo.py # 手动管理内存的聊天示例 +│ ├── without_memory_demo.py # 无内存的基础聊天 +│ └── without_memory_demo_rich.py # Rich 界面的无内存聊天 +├── ollama/ +│ ├── ollama_rich_chat.py # Ollama 流式聊天(Rich 界面) +│ └── tps_monitor.py # 模型性能测速工具 ├── main.py # 入口文件 ├── pyproject.toml # 项目配置 └── README.md @@ -101,17 +122,24 @@ langchain-learning/ ## 可用模型 +**SiliconFlow** - `deepseek-ai/DeepSeek-R1-0528-Qwen3-8B` - `Qwen/Qwen3.5-4B` +- `Qwen/Qwen3-8B` + +**Ollama (本地)** +- `gemma4:26b` +- `deepseek-v3.1:671b-cloud` ## 技术栈 | 类别 | 技术 | |------|------| | 框架 | LangChain | -| LLM 提供商 | SiliconFlow | +| LLM 提供商 | SiliconFlow, Ollama | +| 终端美化 | Rich | | 语言 | Python 3.11+ | ## 许可证 -MIT License +MIT License \ No newline at end of file diff --git a/ollama/llm_benchmark_dashboard_v2.html b/ollama/llm_benchmark_dashboard_v2.html new file mode 100644 index 0000000..5d37737 --- /dev/null +++ b/ollama/llm_benchmark_dashboard_v2.html @@ -0,0 +1,178 @@ + + + + + + LLM Benchmark Dashboard V2 + + + + +
+
+
+

LLM 推理效能大看板 V2

+

多維度對比:本地部署 vs 雲端 API | 數據驅動決策

+ 更新日期: 2026-04-14 +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
模型名稱首字延遲 (TTFT) ↓生成速度 (TPS)總耗時總字數速度視覺化
local-gemma4:26b (128K)
Local
87.99s10.79131.7s717
local-gemma4:26b (32K)
Local
78.67s10.16127.7s722
local-gemma4:e4b
Local
39.93s12.34110.4s1338
ollama-deepseek-v3.1:671b-cloud
Cloud (Ollama)
1.04s51.747.3s479
ollama-gemma4:31b-cloud
Cloud
0.85s31.7914.2s613
ollama-glm-5:cloud
Cloud (Ollama)
13.58s102.2519.5s779
ollama-kimi-k2.5:cloud
Cloud (Ollama)
15.91s29.6723.3s505
ollama-minimax-m2.7:cloud
Cloud (Ollama)
40.40s3.7540.9s508
百煉-qwen3-max
Cloud
0.86s6.1814.1s595
百煉-qwen3.5-35b-a3b
Cloud
37.64s69.1539.2s543
百煉-qwen3.6-plus
Cloud
77.35s15.2583.3s507
百煉-qwen3.6-plus-v2
Cloud
47.14s15.5853.1s503
直連-MiniMax-M2.7
Cloud (Direct)
1.19s1.9713.9s842
硅基流動-DeepSeek-R1-Qwen-8B
Cloud
10.15s75.5713.4s398
+
+
+
+ +
+ + diff --git a/ollama/llm_benchmark_report_v2.md b/ollama/llm_benchmark_report_v2.md new file mode 100644 index 0000000..8216ae9 --- /dev/null +++ b/ollama/llm_benchmark_report_v2.md @@ -0,0 +1,27 @@ +# LLM 推理性能基準測試報告 V2 (2026-04) + +## 1. 全模型性能對比表 +| 模型名稱 | 部署類型 | TTFT (秒) | TPS (tokens/s) | 總耗時 (秒) | 總字數 | +| :--- | :--- | :--- | :--- | :--- | :--- | +| local-gemma4:26b (128K) | Local | 87.99 | 10.79 | 131.74 | 717 | +| local-gemma4:26b (32K) | Local | 78.67 | 10.16 | 127.70 | 722 | +| local-gemma4:e4b | Local | 39.93 | 12.34 | 110.43 | 1338 | +| ollama-deepseek-v3.1:671b-cloud | Cloud (Ollama) | 1.04 | 51.74 | 7.30 | 479 | +| ollama-gemma4:31b-cloud | Cloud | 0.85 | 31.79 | 14.22 | 613 | +| ollama-glm-5:cloud | Cloud (Ollama) | 13.58 | 102.25 | 19.53 | 779 | +| ollama-kimi-k2.5:cloud | Cloud (Ollama) | 15.91 | 29.67 | 23.29 | 505 | +| ollama-minimax-m2.7:cloud | Cloud (Ollama) | 40.40 | 3.75 | 40.94 | 508 | +| 百煉-qwen3-max | Cloud | 0.86 | 6.18 | 14.13 | 595 | +| 百煉-qwen3.5-35b-a3b | Cloud | 37.64 | 69.15 | 39.22 | 543 | +| 百煉-qwen3.6-plus | Cloud | 77.35 | 15.25 | 83.32 | 507 | +| 百煉-qwen3.6-plus-v2 | Cloud | 47.14 | 15.58 | 53.11 | 503 | +| 直連-MiniMax-M2.7 | Cloud (Direct) | 1.19 | 1.97 | 13.90 | 842 | +| 硅基流動-DeepSeek-R1-Qwen-8B | Cloud | 10.15 | 75.57 | 13.40 | 398 | + +## 2. 數據分析結論 +- **雲端極速化**:`GLM-5` (102 t/s) 與 `DeepSeek v3.1` (51 t/s) 展現了極致的雲端吞吐能力。 +- **本地 e4b 觀察**:即使是 4B 規模模型,在本地冷啟動仍需約 40 秒,說明啟動瓶頸(硬碟與 Ollama 服務初始化)與模型參數量的相關性較低,更受系統底層 IO 影響。 +- **穩定性提升**:直連 API 的 TTFT 普遍穩定在 1 秒左右,相比之下,各類中轉或代理層(如部分百煉接口)波動較大。 + +--- +*報告生成時間: 2026-04-14* diff --git a/ollama/ollama_rich_chat.py b/ollama/ollama_rich_chat.py new file mode 100644 index 0000000..7ccabad --- /dev/null +++ b/ollama/ollama_rich_chat.py @@ -0,0 +1,76 @@ +import os +from dotenv import load_dotenv +from openai import OpenAI +from rich.console import Console +from rich.panel import Panel +from rich.markdown import Markdown +from rich.live import Live + +load_dotenv() + +# 1. 初始化 Rich 控制台 +console = Console() + +# 2. 初始化 OpenAI 客戶端 (指向本地 Ollama 或 SiliconFlow) +client = OpenAI( + base_url=os.getenv("OLLAMA_BASE_URL"), + api_key=os.getenv("OLLAMA_API_KEY") +) + +# 【核心架構 1】:維護一個對話歷史列表 (這就是 AI 的大腦記憶區) +# 確保一開始把人設 (System Prompt) 塞進去 +chat_history = [ + {"role": "system", "content": "你是一個精通 Python 的高級工程師,請保持專業且友善的語氣。"} +] + +# 印出漂亮的歡迎畫面 +console.print(Panel("✨ 歡迎使用流式 AI 助手!輸入 'quit' 退出。", border_style="green")) + +# 進入「你問我答」的無限循環 +while True: +# 替换原来的单行 input() + console.print("\n👤 [bold green]你 (支持多行输入,输入 '/send' 并回车发送,输入 'quit' 退出):[/bold green]") + lines = [] + while True: + line = input() + if line.strip().lower() == 'quit': + console.print("[dim]👋 再见![/dim]") + exit() # 直接退出程序 + if line.strip() == '/send': + break # 结束输入,跳出收集循环 + lines.append(line) + + # 将多行列表拼接成一个包含真正换行符的完整字符串 + user_input = "\n".join(lines) + + # 將使用者的新問題,追加進對話歷史中 + chat_history.append({"role": "user", "content": user_input}) + + # 呼叫大模型,並開啟流式輸出 (stream=True) + # 注意這裡的 messages 傳入的是完整的 chat_history + response_stream = client.chat.completions.create( + model="gemma4:26b", # 替換成你實際運行的模型名稱 + messages=chat_history, + stream=True + ) + + full_response = "" + + # 【核心架構 3】:使用 Live 區塊進行 UI 即時渲染 + with Live(Panel("思考中...", title="🤖 AI", border_style="cyan"), refresh_per_second=15) as live: + for chunk in response_stream: + content = chunk.choices[0].delta.content + if content is not None: + full_response += content + # 即時更新青色的對話框 + live.update( + Panel( + Markdown(full_response), + title="🤖 AI", + border_style="cyan" + ) + ) + + # 【核心架構 4】:將 AI 剛剛吐出來的完整回答,存回對話歷史中 + # 這樣下一輪對話時,AI 才會「記得」它自己剛剛說過什麼 + chat_history.append({"role": "assistant", "content": full_response}) \ No newline at end of file diff --git a/ollama/tps_monitor.py b/ollama/tps_monitor.py new file mode 100644 index 0000000..bea0a09 --- /dev/null +++ b/ollama/tps_monitor.py @@ -0,0 +1,58 @@ +import os +import time +from openai import OpenAI +from dotenv import load_dotenv + +load_dotenv() + +# 配置你的環境 +client = OpenAI( + base_url=os.getenv("OLLAMA_BASE_URL", "你的URL"), + api_key=os.getenv("OLLAMA_API_KEY", "你的APIKEY") +) + +def test_model_speed(model_name, prompt="請寫一篇關於未來AI發展的500字文章。"): + print(f"🚀 正在測試模型: {model_name} ...") + + start_time = time.time() + first_token_time = None + tokens_count = 0 + full_response = "" + + try: + stream = client.chat.completions.create( + model=model_name, + messages=[{"role": "user", "content": prompt}], + stream=True + ) + + for chunk in stream: + if chunk.choices[0].delta.content: + if first_token_time is None: + # 紀錄首字時間 (TTFT) + first_token_time = time.time() - start_time + + content = chunk.choices[0].delta.content + full_response += content + # 粗略計算法:中文大約 1 字 = 0.6~1 token,英文 1 詞 = 1.3 token + # 這裡直接用字數估算,或者如果你想更準確,可以計算 chunk 的數量 + tokens_count += 1 + + total_time = time.time() - start_time + generation_time = total_time - first_token_time + tps = tokens_count / generation_time if generation_time > 0 else 0 + + print("-" * 30) + print(f"📊 測試結果:") + print(f"⏱️ 首字延遲 (TTFT): {first_token_time:.2f} 秒") + print(f"⚡ 生成速度 (TPS): {tps:.2f} tokens/s") + print(f"🕒 總耗時: {total_time:.2f} 秒") + print(f"📝 總字數: {len(full_response)} 字") + print("-" * 30) + + except Exception as e: + print(f"❌ 測試出錯: {e}") + +if __name__ == "__main__": + # 替換成你實際想測的模型名稱 + test_model_speed("deepseek-v3.1:671b-cloud") \ No newline at end of file