From 2fa274e1b1eef210d02f7e8c075cf36a45af39d4 Mon Sep 17 00:00:00 2001 From: thzxx Date: Fri, 3 Apr 2026 13:21:34 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20README.md=20=E5=85=A8=E9=9D=A2=E9=87=8D?= =?UTF-8?q?=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 Ollama API 调用清单(接口/方法/调用位置/用途) - 新增流式聊天 NDJSON 数据格式说明 - 新增聊天请求参数完整示例 - 新增强制停止机制流程图 - 更新版本号至 v2.0.0 - 功能特性改为表格 - 设置项关联 API 参数 --- README.md | 200 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 144 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 70784a6..b776cff 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,41 @@ # 🦙 Metona Ollama Client -基于原生 JavaScript 的 [Ollama](https://ollama.com) AI 聊天客户端,支持流式对话、多模态图片、Think 推理模式、历史管理,可安装为 PWA 离线使用。 +基于原生 JavaScript 的 [Ollama](https://ollama.com) AI 聊天客户端。零依赖、无构建步骤,开箱即用。 -![版本](https://img.shields.io/badge/version-1.1.0-brightgreen) +支持流式对话、多模态图片输入、Think 深度推理、历史记录管理,可安装为 PWA 离线使用。 + +![版本](https://img.shields.io/badge/version-2.0.0-brightgreen) ![平台](https://img.shields.io/badge/platform-Web-blue) ![协议](https://img.shields.io/badge/license-MIT-green) +--- + ## ✨ 功能特性 -- **流式对话** — 基于 ReadableStream 的实时打字机效果 -- **多模型支持** — 自动加载 Ollama 已安装模型,一键切换 -- **Think 推理模式** — 可展开/收起的思考过程展示 -- **多模态输入** — 支持图片上传,兼容视觉模型 -- **历史管理** — IndexedDB 持久化,支持搜索、分页、导出(Markdown/HTML/TXT/JSON) -- **PWA 离线** — Service Worker 缓存,可安装到桌面 -- **连接检测** — 实时状态指示,CORS 问题自动提示 -- **显存管理** — 一键卸载模型释放显存 -- **XSS 防护** — 内置 HTML 净化器,安全渲染 Markdown +| 功能 | 说明 | +|------|------| +| 流式对话 | 基于 ReadableStream 的实时打字机效果,支持强制停止 | +| 多模型支持 | 自动加载 Ollama 已安装模型,一键切换 | +| Think 推理模式 | 可展开/收起的思考过程展示(需模型支持) | +| 多模态输入 | 支持图片上传,兼容视觉模型 | +| 强制停止 | 真正中止 Ollama 接口请求,双重保险(fetch abort + reader cancel) | +| 历史管理 | IndexedDB 持久化,支持搜索、分页、导出 | +| 数据导出 | Markdown / HTML / TXT / JSON 多格式 | +| PWA 离线 | Service Worker 缓存,可安装到桌面 | +| 连接检测 | 实时状态指示,CORS 问题自动提示 | +| 显存管理 | 一键卸载模型释放显存 | + +--- ## 🚀 快速开始 ### 前置条件 1. 安装 [Ollama](https://ollama.com) 并启动服务 -2. 下载至少一个模型(例如 `ollama pull qwen2.5`) +2. 下载至少一个模型: + ```bash + ollama pull qwen2.5 + ``` ### 启动 @@ -32,12 +44,12 @@ git clone https://gitee.com/thzxx/metona-ollama.git cd metona-ollama -# 直接用浏览器打开 +# 方式一:直接用浏览器打开 open index.html -# 或用任意 HTTP 服务器托管 +# 方式二:用 HTTP 服务器托管 python3 -m http.server 8080 -# 然后访问 http://localhost:8080 +# 访问 http://localhost:8080 ``` ### 跨域配置 @@ -48,77 +60,153 @@ python3 -m http.server 8080 OLLAMA_ORIGINS="*" ollama serve ``` +--- + +## 🔌 Ollama API 调用清单 + +Metona 通过 `js/ollama-api.js` 封装了 Ollama REST API,以下是所有调用的接口: + +### 模型管理 + +| 接口 | 方法 | 函数 | 调用位置 | 用途 | +|------|------|------|----------|------| +| `/api/tags` | `GET` | `listModels()` | model-bar.js | 获取已安装模型列表,填充下拉选择框 | +| `/api/ps` | `GET` | `psModels()` | header.js | 获取运行中的模型列表,展示在设置面板 | +| `/api/version` | `GET` | `getVersion()` | header.js | 获取 Ollama 版本号,用于连接检测和版本显示 | +| `/api/show` | `POST` | `showModel(model)` | model-bar.js | 查询模型详情,检测 Think/Vision 等能力 | + +### 聊天 + +| 接口 | 方法 | 函数 | 调用位置 | 用途 | +|------|------|------|----------|------| +| `/api/chat` | `POST` | `chatStream(params, onChunk, abortController)` | input-area.js | **核心接口**。流式聊天(`stream: true`),通过 NDJSON 流实时返回 AI 回复,支持 AbortController 强制中止 | +| `/api/chat` | `POST` | `chat(params)` | settings-modal.js | 非流式聊天(`stream: false`)。用于释放显存:发送空消息并设置 `keep_alive: 0` 强制卸载模型 | +| `/api/generate` | `POST` | `generateStream(params, onChunk)` | — (未使用) | 单轮流式生成,预留接口 | +| `/api/embed` | `POST` | `embed(model, input)` | — (未使用) | 生成嵌入向量,预留接口 | + +### 流式聊天数据格式 (NDJSON) + +`/api/chat` 流式响应为 NDJSON(每行一个 JSON): + +```json +{"model":"qwen2.5","message":{"role":"assistant","content":"Hello"},"done":false} +{"model":"qwen2.5","message":{"role":"assistant","content":" world"},"done":false} +{"model":"qwen2.5","message":{"role":"assistant","content":"!"},"done":true,"eval_count":42,"total_duration":1234567890} +``` + +### 聊天请求参数 + +```javascript +{ + model: "qwen2.5", // 模型名称 + messages: [ // 对话历史 + { role: "user", content: "你好", images: ["base64..."] }, + { role: "assistant", content: "你好!" } + ], + stream: true, // 是否流式 + think: true, // 是否启用 Think 推理(需模型支持) + system: "你是一个助手", // 系统提示词 + keep_alive: "5m", // 模型在内存中保持时间 + options: { + num_ctx: 24576 // 上下文窗口大小(tokens) + } +} +``` + +### 强制停止机制 + +用户点击停止按钮时的完整流程: + +``` +用户点击 ■ → abortController.abort() + ├── fetch signal → 浏览器取消 HTTP 连接 → Ollama 停止推理 + ├── abort listener → reader.cancel() → 中断 ReadableStream + └── catch AbortError → 保留已有内容 → 标记 [已停止] → 恢复 UI +``` + +--- + ## 📁 项目结构 ``` metona-ollama/ -├── index.html # 入口页面(纯模板) -├── manifest.json # PWA 清单 -├── sw.js # Service Worker (PWA) +├── index.html # 入口页面(纯 HTML 模板) +├── manifest.json # PWA 清单 +├── sw.js # Service Worker (PWA 缓存) ├── LICENSE ├── README.md │ ├── assets/ -│ └── icons/ # 图标资源 -│ ├── llama.ico -│ └── llama.png +│ └── icons/ +│ ├── llama.ico # 网站图标 +│ └── llama.png # PWA 图标 │ ├── css/ -│ └── style.css # 暗色主题样式 +│ └── style.css # 全局样式(暗色主题 + 响应式) │ └── js/ - ├── app.js # 主入口 / 初始化协调 - ├── ollama-api.js # Ollama REST API 封装 - ├── chat-db.js # IndexedDB 持久化层 - ├── state.js # 响应式状态管理 - ├── utils.js # 通用工具函数 - ├── sanitizer.js # HTML XSS 净化器 - ├── marked-config.js # Markdown 渲染器配置 + ├── app.js # 主入口:初始化所有组件、事件绑定、生命周期管理 + ├── ollama-api.js # Ollama REST API 封装(见上方 API 清单) + ├── chat-db.js # IndexedDB 持久化层(会话 CRUD + 设置存储) + ├── state.js # 响应式状态管理(发布-订阅模式) + ├── utils.js # 工具函数(ID生成、格式化、防抖、Base64) + ├── sanitizer.js # HTML XSS 净化器(白名单策略) + ├── marked-config.js # Markdown 渲染器配置(自定义链接/图片安全检查) ├── lib/ - │ └── marked.esm.js # Markdown 渲染器(第三方) + │ └── marked.esm.js # marked.js v15 (Markdown 解析器) └── components/ - ├── chat-area.js # 消息渲染 / 流式更新 / 导出 - ├── input-area.js # 文本输入 / 图片上传 / 发送 - ├── history-modal.js # 历史记录面板 / 搜索 / 分页 - ├── settings-modal.js # 设置面板 / 数据管理 - ├── header.js # 顶部导航 / 连接状态 - ├── model-bar.js # 模型选择栏 - ├── toast.js # Toast 通知 - └── lightbox.js # 图片预览 + ├── chat-area.js # 消息渲染、流式更新、导出功能 + ├── input-area.js # 文本输入、图片上传、发送/停止逻辑 + ├── history-modal.js # 历史记录面板、搜索、分页 + ├── settings-modal.js # 设置面板、模型管理、数据管理 + ├── header.js # 顶部导航、连接状态检测 + ├── model-bar.js # 模型选择栏、能力检测 + ├── toast.js # Toast 通知组件 + └── lightbox.js # 图片预览灯箱 ``` +--- + ## ⚙️ 设置项 -| 设置 | 说明 | 默认值 | -|------|------|--------| -| Ollama 服务地址 | API 端点 | `http://127.0.0.1:11434` | -| 系统提示词 | 全局 System Prompt | 关闭 | -| 上下文长度 | `num_ctx` 参数 | 24576 tokens | -| Think 模式 | 启用深度推理(需要模型支持) | 关闭 | +| 设置 | 说明 | 默认值 | API 参数 | +|------|------|--------|----------| +| Ollama 服务地址 | API 端点 | `http://127.0.0.1:11434` | — | +| 系统提示词 | 全局 System Prompt | 关闭 | `system` | +| 上下文长度 | 上下文窗口大小 | 24576 tokens | `options.num_ctx` | +| Think 模式 | 启用深度推理 | 关闭 | `think` | + +--- ## 📦 数据导出 -支持以下导出格式: +| 格式 | 说明 | 文件后缀 | +|------|------|----------| +| Markdown | 单会话导出,便于阅读和编辑 | `.md` | +| HTML | 带暗色主题样式的离线页面 | `.html` | +| TXT | 纯文本备份 | `.txt` | +| JSON | 全量备份/迁移,可跨设备导入 | `.json` | -- **Markdown** — 单会话导出,便于阅读 -- **HTML** — 带样式的离线页面 -- **TXT** — 纯文本备份 -- **JSON** — 全量备份/迁移,可跨设备导入 +--- ## 🛠️ 技术栈 -- **纯原生 JS** — 零依赖(除 marked.js),无构建步骤 -- **IndexedDB** — 异步持久化,支持大数据存储 -- **Fetch API + ReadableStream** — 流式 NDJSON 解析 +- **纯原生 JavaScript (ES Modules)** — 零构建步骤,`