Files
metona-ollama-desktop/README.md
T
thzxx 2fa274e1b1 docs: README.md 全面重写
- 新增 Ollama API 调用清单(接口/方法/调用位置/用途)
- 新增流式聊天 NDJSON 数据格式说明
- 新增聊天请求参数完整示例
- 新增强制停止机制流程图
- 更新版本号至 v2.0.0
- 功能特性改为表格
- 设置项关联 API 参数
2026-04-03 13:21:34 +08:00

214 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🦙 Metona Ollama Client
基于原生 JavaScript 的 [Ollama](https://ollama.com) AI 聊天客户端。零依赖、无构建步骤,开箱即用。
支持流式对话、多模态图片输入、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 推理模式 | 可展开/收起的思考过程展示(需模型支持) |
| 多模态输入 | 支持图片上传,兼容视觉模型 |
| 强制停止 | 真正中止 Ollama 接口请求,双重保险(fetch abort + reader cancel |
| 历史管理 | IndexedDB 持久化,支持搜索、分页、导出 |
| 数据导出 | Markdown / HTML / TXT / JSON 多格式 |
| PWA 离线 | Service Worker 缓存,可安装到桌面 |
| 连接检测 | 实时状态指示,CORS 问题自动提示 |
| 显存管理 | 一键卸载模型释放显存 |
---
## 🚀 快速开始
### 前置条件
1. 安装 [Ollama](https://ollama.com) 并启动服务
2. 下载至少一个模型:
```bash
ollama pull qwen2.5
```
### 启动
```bash
# 克隆仓库
git clone https://gitee.com/thzxx/metona-ollama.git
cd metona-ollama
# 方式一:直接用浏览器打开
open index.html
# 方式二:用 HTTP 服务器托管
python3 -m http.server 8080
# 访问 http://localhost:8080
```
### 跨域配置
如果 Ollama 和页面不在同一域,需要设置环境变量:
```bash
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 # 入口页面(纯 HTML 模板)
├── manifest.json # PWA 清单
├── sw.js # Service Worker (PWA 缓存)
├── LICENSE
├── README.md
├── assets/
│ └── icons/
│ ├── llama.ico # 网站图标
│ └── llama.png # PWA 图标
├── css/
│ └── style.css # 全局样式(暗色主题 + 响应式)
└── js/
├── 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 # 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 # 图片预览灯箱
```
---
## ⚙️ 设置项
| 设置 | 说明 | 默认值 | 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` |
---
## 🛠️ 技术栈
- **纯原生 JavaScript (ES Modules)** — 零构建步骤,`<script type="module">` 直接加载
- **IndexedDB** — 异步持久化,支持大数据(如 base64 图片)
- **Fetch API + ReadableStream** — 流式 NDJSON 解析,支持 AbortController 中止
- **PWA** — Service Worker 离线缓存
- **CSS Variables** — 暗色主题,响应式布局,渐变 + 毛玻璃效果
---
## 🔒 安全
- 内置 HTML 净化器(白名单标签 + 属性过滤 + URI 协议检查)
- Markdown 链接仅允许 `http:` / `https:` / `mailto:` / `tel:` 协议
- 阻止 `javascript:` / `vbscript:` / `data:` 协议注入
- 输入内容自动转义,防御 XSS 攻击
---
## 📄 License
MIT