- Electron + React + TypeScript 架构 - 三栏布局: Sidebar | ChatPanel | DetailPanel - 9 个内置工具 (文件系统/网络/记忆/命令) - SQLite 持久化 (better-sqlite3) - MUI 暗色/亮色主题系统 - Agent Loop ReAct 状态机引擎 - DeepSeek / Agnes AI / Ollama Provider 适配器 - MCP 协议集成 - 系统托盘 + 全局快捷键 - Tailwind CSS v4 + Tailwind Merge - 修复: Sidebar 缺失 TextField 导入导致黑屏
1877 lines
112 KiB
HTML
1877 lines
112 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Ollama API 完整接口文档 | 20260518</title>
|
||
<style>
|
||
:root {
|
||
--bg: #0f1117;
|
||
--bg-card: #1a1d27;
|
||
--bg-code: #12141c;
|
||
--bg-nav: #141620;
|
||
--text: #e1e4ed;
|
||
--text-dim: #8b8fa7;
|
||
--accent: #6c9eff;
|
||
--accent2: #a78bfa;
|
||
--green: #34d399;
|
||
--orange: #fb923c;
|
||
--red: #f87171;
|
||
--cyan: #22d3ee;
|
||
--border: #2a2d3a;
|
||
--get: #34d399;
|
||
--post: #6c9eff;
|
||
--delete: #f87171;
|
||
}
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||
background: var(--bg);
|
||
color: var(--text);
|
||
line-height: 1.7;
|
||
display: flex;
|
||
}
|
||
/* === SIDEBAR === */
|
||
.sidebar {
|
||
position: fixed;
|
||
top: 0; left: 0;
|
||
width: 280px;
|
||
height: 100vh;
|
||
background: var(--bg-nav);
|
||
border-right: 1px solid var(--border);
|
||
overflow-y: auto;
|
||
z-index: 100;
|
||
padding: 24px 0;
|
||
}
|
||
.sidebar-logo {
|
||
padding: 0 20px 20px;
|
||
border-bottom: 1px solid var(--border);
|
||
margin-bottom: 16px;
|
||
}
|
||
.sidebar-logo h2 {
|
||
font-size: 20px;
|
||
background: linear-gradient(135deg, var(--accent), var(--accent2));
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.sidebar-logo .badge {
|
||
font-size: 11px;
|
||
background: var(--accent);
|
||
color: #fff;
|
||
padding: 2px 8px;
|
||
border-radius: 10px;
|
||
-webkit-text-fill-color: #fff;
|
||
}
|
||
.sidebar-section {
|
||
padding: 8px 20px;
|
||
font-size: 11px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 1.2px;
|
||
color: var(--text-dim);
|
||
font-weight: 600;
|
||
}
|
||
.sidebar a {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 8px 20px;
|
||
color: var(--text-dim);
|
||
text-decoration: none;
|
||
font-size: 13.5px;
|
||
transition: all 0.15s;
|
||
}
|
||
.sidebar a:hover, .sidebar a.active {
|
||
color: var(--text);
|
||
background: rgba(108, 158, 255, 0.06);
|
||
}
|
||
.sidebar a .method {
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
padding: 1px 6px;
|
||
border-radius: 3px;
|
||
min-width: 42px;
|
||
text-align: center;
|
||
font-family: 'SF Mono', 'Fira Code', monospace;
|
||
}
|
||
.method-get { background: rgba(52,211,153,0.15); color: var(--get); }
|
||
.method-post { background: rgba(108,158,255,0.15); color: var(--post); }
|
||
.method-delete { background: rgba(248,113,113,0.15); color: var(--delete); }
|
||
|
||
/* === MAIN === */
|
||
.main {
|
||
margin-left: 280px;
|
||
flex: 1;
|
||
min-height: 100vh;
|
||
}
|
||
.hero {
|
||
background: linear-gradient(135deg, rgba(108,158,255,0.08), rgba(167,139,250,0.08));
|
||
border-bottom: 1px solid var(--border);
|
||
padding: 60px 60px 50px;
|
||
}
|
||
.hero h1 {
|
||
font-size: 36px;
|
||
font-weight: 800;
|
||
background: linear-gradient(135deg, var(--accent), var(--accent2));
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
margin-bottom: 12px;
|
||
}
|
||
.hero p {
|
||
color: var(--text-dim);
|
||
font-size: 16px;
|
||
max-width: 680px;
|
||
}
|
||
.hero-meta {
|
||
display: flex;
|
||
gap: 24px;
|
||
margin-top: 20px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.hero-meta span {
|
||
font-size: 13px;
|
||
color: var(--text-dim);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
.hero-meta .dot {
|
||
width: 6px; height: 6px;
|
||
border-radius: 50%;
|
||
display: inline-block;
|
||
}
|
||
.dot-green { background: var(--green); }
|
||
.dot-blue { background: var(--accent); }
|
||
.dot-orange { background: var(--orange); }
|
||
|
||
.content {
|
||
padding: 40px 60px 100px;
|
||
max-width: 1000px;
|
||
}
|
||
|
||
/* === SECTION === */
|
||
.api-section {
|
||
margin-bottom: 60px;
|
||
scroll-margin-top: 20px;
|
||
}
|
||
.api-section h2 {
|
||
font-size: 24px;
|
||
font-weight: 700;
|
||
margin-bottom: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
.api-section .desc {
|
||
color: var(--text-dim);
|
||
font-size: 15px;
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
/* === ENDPOINT BAR === */
|
||
.endpoint-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
background: var(--bg-code);
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
padding: 12px 18px;
|
||
margin-bottom: 24px;
|
||
font-family: 'SF Mono', 'Fira Code', monospace;
|
||
font-size: 14px;
|
||
}
|
||
.endpoint-bar .http-method {
|
||
font-weight: 700;
|
||
padding: 4px 10px;
|
||
border-radius: 5px;
|
||
font-size: 12px;
|
||
}
|
||
.endpoint-bar .url {
|
||
color: var(--text);
|
||
}
|
||
|
||
/* === PARAMS TABLE === */
|
||
.params-title {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: var(--accent);
|
||
margin-bottom: 10px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
table.params {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-bottom: 28px;
|
||
font-size: 13.5px;
|
||
}
|
||
table.params th {
|
||
text-align: left;
|
||
padding: 10px 14px;
|
||
background: var(--bg-card);
|
||
border-bottom: 1px solid var(--border);
|
||
color: var(--text-dim);
|
||
font-weight: 600;
|
||
font-size: 11px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.8px;
|
||
}
|
||
table.params td {
|
||
padding: 10px 14px;
|
||
border-bottom: 1px solid rgba(42,45,58,0.5);
|
||
vertical-align: top;
|
||
}
|
||
table.params tr:last-child td { border-bottom: none; }
|
||
.param-name {
|
||
font-family: 'SF Mono', 'Fira Code', monospace;
|
||
color: var(--cyan);
|
||
font-weight: 600;
|
||
font-size: 13px;
|
||
}
|
||
.param-type {
|
||
font-family: 'SF Mono', 'Fira Code', monospace;
|
||
color: var(--accent2);
|
||
font-size: 12px;
|
||
}
|
||
.param-required {
|
||
color: var(--red);
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
}
|
||
.param-optional {
|
||
color: var(--text-dim);
|
||
font-size: 11px;
|
||
}
|
||
.param-default {
|
||
color: var(--text-dim);
|
||
font-size: 12px;
|
||
}
|
||
|
||
/* === CODE BLOCK === */
|
||
.code-tabs {
|
||
display: flex;
|
||
gap: 0;
|
||
border-bottom: 1px solid var(--border);
|
||
margin-bottom: 0;
|
||
}
|
||
.code-tab {
|
||
padding: 10px 20px;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: var(--text-dim);
|
||
cursor: pointer;
|
||
border-bottom: 2px solid transparent;
|
||
transition: all 0.15s;
|
||
background: transparent;
|
||
border-top: none;
|
||
border-left: none;
|
||
border-right: none;
|
||
}
|
||
.code-tab:hover { color: var(--text); }
|
||
.code-tab.active {
|
||
color: var(--accent);
|
||
border-bottom-color: var(--accent);
|
||
}
|
||
.code-block {
|
||
background: var(--bg-code);
|
||
border: 1px solid var(--border);
|
||
border-top: none;
|
||
border-radius: 0 0 10px 10px;
|
||
padding: 20px;
|
||
overflow-x: auto;
|
||
margin-bottom: 24px;
|
||
}
|
||
.code-block pre {
|
||
margin: 0;
|
||
font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
|
||
font-size: 13px;
|
||
line-height: 1.65;
|
||
color: var(--text);
|
||
}
|
||
.code-panel { display: none; }
|
||
.code-panel.active { display: block; }
|
||
|
||
/* Syntax colors */
|
||
.hl-kw { color: var(--accent2); }
|
||
.hl-str { color: var(--green); }
|
||
.hl-num { color: var(--orange); }
|
||
.hl-cm { color: var(--text-dim); font-style: italic; }
|
||
.hl-fn { color: var(--accent); }
|
||
.hl-prop { color: var(--cyan); }
|
||
|
||
/* === RESPONSE === */
|
||
.response-title {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: var(--green);
|
||
margin-bottom: 10px;
|
||
}
|
||
.response-block {
|
||
background: var(--bg-code);
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
padding: 20px;
|
||
overflow-x: auto;
|
||
margin-bottom: 28px;
|
||
}
|
||
.response-block pre {
|
||
margin: 0;
|
||
font-family: 'SF Mono', 'Fira Code', monospace;
|
||
font-size: 13px;
|
||
line-height: 1.65;
|
||
color: var(--text);
|
||
}
|
||
|
||
/* === DIVIDER === */
|
||
.section-divider {
|
||
border: none;
|
||
height: 1px;
|
||
background: var(--border);
|
||
margin: 60px 0;
|
||
}
|
||
|
||
/* === OVERVIEW TABLE === */
|
||
.overview-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin: 24px 0 40px;
|
||
font-size: 13.5px;
|
||
}
|
||
.overview-table th {
|
||
text-align: left;
|
||
padding: 12px 16px;
|
||
background: var(--bg-card);
|
||
border-bottom: 2px solid var(--border);
|
||
color: var(--text-dim);
|
||
font-weight: 600;
|
||
font-size: 11px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.8px;
|
||
}
|
||
.overview-table td {
|
||
padding: 10px 16px;
|
||
border-bottom: 1px solid rgba(42,45,58,0.5);
|
||
}
|
||
.overview-table a {
|
||
color: var(--accent);
|
||
text-decoration: none;
|
||
}
|
||
.overview-table a:hover { text-decoration: underline; }
|
||
|
||
/* === SCROLLBAR === */
|
||
::-webkit-scrollbar { width: 6px; height: 6px; }
|
||
::-webkit-scrollbar-track { background: transparent; }
|
||
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
|
||
::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
|
||
|
||
/* === NOTE BOX === */
|
||
.note-box {
|
||
background: rgba(108,158,255,0.06);
|
||
border-left: 3px solid var(--accent);
|
||
border-radius: 0 8px 8px 0;
|
||
padding: 14px 18px;
|
||
margin-bottom: 24px;
|
||
font-size: 13.5px;
|
||
color: var(--text-dim);
|
||
}
|
||
.note-box strong { color: var(--accent); }
|
||
|
||
@media (max-width: 900px) {
|
||
.sidebar { display: none; }
|
||
.main { margin-left: 0; }
|
||
.hero { padding: 30px 24px; }
|
||
.content { padding: 24px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ========== SIDEBAR ========== -->
|
||
<nav class="sidebar">
|
||
<div class="sidebar-logo">
|
||
<h2>🦧 Ollama API <span class="badge">最新</span></h2>
|
||
</div>
|
||
|
||
<div class="sidebar-section">概述</div>
|
||
<a href="#overview">📋 接口总览</a>
|
||
<a href="#quickstart">⚡ 快速开始</a>
|
||
<a href="#model-options">⚙️ 模型参数 Options</a>
|
||
|
||
<div class="sidebar-section">生成接口</div>
|
||
<a href="#generate"><span class="method method-post">POST</span> /api/generate</a>
|
||
<a href="#chat"><span class="method method-post">POST</span> /api/chat</a>
|
||
<a href="#embed"><span class="method method-post">POST</span> /api/embed</a>
|
||
|
||
<div class="sidebar-section">模型管理</div>
|
||
<a href="#tags"><span class="method method-get">GET</span> /api/tags</a>
|
||
<a href="#show"><span class="method method-post">POST</span> /api/show</a>
|
||
<a href="#create"><span class="method method-post">POST</span> /api/create</a>
|
||
<a href="#copy"><span class="method method-post">POST</span> /api/copy</a>
|
||
<a href="#delete"><span class="method method-delete">DELETE</span> /api/delete</a>
|
||
<a href="#pull"><span class="method method-post">POST</span> /api/pull</a>
|
||
<a href="#push"><span class="method method-post">POST</span> /api/push</a>
|
||
|
||
<div class="sidebar-section">运行时</div>
|
||
<a href="#ps"><span class="method method-get">GET</span> /api/ps</a>
|
||
<a href="#version"><span class="method method-get">GET</span> /api/version</a>
|
||
</nav>
|
||
|
||
<!-- ========== MAIN CONTENT ========== -->
|
||
<div class="main">
|
||
|
||
<!-- HERO -->
|
||
<div class="hero">
|
||
<h1>Ollama API 完整接口文档</h1>
|
||
<p>基于官方文档 <a href="https://docs.ollama.com" style="color:var(--accent)">docs.ollama.com</a> 全面解析。覆盖所有 HTTP API 端点,每个接口均提供 <strong>JavaScript SDK</strong> 和 <strong>HTTP Fetch</strong> 两种调用方式的详细示例代码。</p>
|
||
<div class="hero-meta">
|
||
<span><span class="dot dot-green"></span> 支持模型: <strong>gpt-oss · Gemma 3 · DeepSeek-R1 · Qwen3 等</strong></span>
|
||
<span><span class="dot dot-blue"></span> 文档日期: <strong>2026-05-18</strong></span>
|
||
<span><span class="dot dot-orange"></span> 本地: <strong>http://localhost:11434</strong> · 云端: <strong>https://ollama.com/api</strong></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="content">
|
||
|
||
<!-- ========== 接口总览 ========== -->
|
||
<section class="api-section" id="overview">
|
||
<h2>📋 接口总览</h2>
|
||
<p class="desc">Ollama 提供 RESTful HTTP API,默认监听在 <code style="color:var(--cyan)">http://localhost:11434</code>。所有请求与响应均使用 JSON 格式。流式响应使用 NDJSON(newline-delimited JSON)。云端模型可通过 <code style="color:var(--cyan)">https://ollama.com/api</code> 访问相同的 API。</p>
|
||
|
||
<table class="overview-table">
|
||
<thead>
|
||
<tr><th>方法</th><th>接口路径</th><th>描述</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><span class="method method-post">POST</span></td><td><a href="#generate">/api/generate</a></td><td>生成文本响应(补全模式)</td></tr>
|
||
<tr><td><span class="method method-post">POST</span></td><td><a href="#chat">/api/chat</a></td><td>对话模式生成消息</td></tr>
|
||
<tr><td><span class="method method-post">POST</span></td><td><a href="#embed">/api/embed</a></td><td>生成文本向量嵌入</td></tr>
|
||
<tr><td><span class="method method-get">GET</span></td><td><a href="#tags">/api/tags</a></td><td>列出所有本地模型</td></tr>
|
||
<tr><td><span class="method method-post">POST</span></td><td><a href="#show">/api/show</a></td><td>查看模型详细信息</td></tr>
|
||
<tr><td><span class="method method-post">POST</span></td><td><a href="#create">/api/create</a></td><td>创建自定义模型</td></tr>
|
||
<tr><td><span class="method method-post">POST</span></td><td><a href="#copy">/api/copy</a></td><td>复制模型</td></tr>
|
||
<tr><td><span class="method method-delete">DELETE</span></td><td><a href="#delete">/api/delete</a></td><td>删除模型</td></tr>
|
||
<tr><td><span class="method method-post">POST</span></td><td><a href="#pull">/api/pull</a></td><td>从仓库拉取模型</td></tr>
|
||
<tr><td><span class="method method-post">POST</span></td><td><a href="#push">/api/push</a></td><td>推送模型到仓库</td></tr>
|
||
<tr><td><span class="method method-get">GET</span></td><td><a href="#ps">/api/ps</a></td><td>列出正在运行的模型</td></tr>
|
||
<tr><td><span class="method method-get">GET</span></td><td><a href="#version">/api/version</a></td><td>获取 Ollama 版本</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<!-- ========== 快速开始 ========== -->
|
||
<section class="api-section" id="quickstart">
|
||
<h2>⚡ 快速开始</h2>
|
||
<p class="desc">在开始之前,确保 Ollama 已安装并运行。安装 SDK 依赖后即可使用。</p>
|
||
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'qs-sdk')">JavaScript SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'qs-http')">HTTP Fetch</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="qs-sdk">
|
||
<pre><span class="hl-cm">// 安装: npm install ollama</span>
|
||
<span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
|
||
<span class="hl-cm">// 默认连接本地 http://localhost:11434</span>
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 也可以指定远程地址</span>
|
||
<span class="hl-kw">const</span> remoteOllama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>({ <span class="hl-prop">host</span>: <span class="hl-str">'http://192.168.1.100:11434'</span> });
|
||
|
||
<span class="hl-cm">// 使用云端模型 (ollama.com)</span>
|
||
<span class="hl-kw">const</span> cloudOllama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>({ <span class="hl-prop">host</span>: <span class="hl-str">'https://ollama.com/api'</span> });</pre>
|
||
</div>
|
||
<div class="code-panel" id="qs-http">
|
||
<pre><span class="hl-cm">// 无需安装任何依赖,使用原生 fetch 即可</span>
|
||
<span class="hl-kw">const</span> OLLAMA_BASE = <span class="hl-str">'http://localhost:11434'</span>;
|
||
|
||
<span class="hl-cm">// 所有请求都是 POST (除少数 GET 接口)</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">`${OLLAMA_BASE}/api/generate`</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">prompt</span>: <span class="hl-str">'你好,世界!'</span>,
|
||
}),
|
||
});
|
||
<span class="hl-kw">const</span> data = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(data.response);</pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ========== Model Options ========== -->
|
||
<section class="api-section" id="model-options">
|
||
<h2>⚙️ 模型参数 (Options)</h2>
|
||
<p class="desc">以下参数可在 <code style="color:var(--cyan)">options</code> 字段中传入,控制生成行为。适用于 <code>/api/generate</code> 和 <code>/api/chat</code> 等接口。</p>
|
||
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">seed</td><td class="param-type">integer</td><td>随机种子,用于可复现的输出</td></tr>
|
||
<tr><td class="param-name">temperature</td><td class="param-type">float</td><td>控制随机性,值越高越随机(默认约 0.8)</td></tr>
|
||
<tr><td class="param-name">top_k</td><td class="param-type">integer</td><td>限制下一个 token 从概率最高的 K 个中选取</td></tr>
|
||
<tr><td class="param-name">top_p</td><td class="param-type">float</td><td>核采样的累积概率阈值</td></tr>
|
||
<tr><td class="param-name">min_p</td><td class="param-type">float</td><td>token 选择的最低概率阈值</td></tr>
|
||
<tr><td class="param-name">stop</td><td class="param-type">string | string[]</td><td>停止序列,遇到时终止生成</td></tr>
|
||
<tr><td class="param-name">num_ctx</td><td class="param-type">integer</td><td>上下文窗口大小(token 数)</td></tr>
|
||
<tr><td class="param-name">num_predict</td><td class="param-type">integer</td><td>最大生成 token 数</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== GENERATE ==================== -->
|
||
<section class="api-section" id="generate">
|
||
<h2><span class="method method-post">POST</span> /api/generate</h2>
|
||
<p class="desc">生成文本响应(补全模式)。支持流式/非流式、结构化输出、图像输入、Thinking 模式、logprobs 等功能。适用于 gpt-oss、Gemma 3、DeepSeek-R1、Qwen3 等模型。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-post">POST</span>
|
||
<span class="url">http://localhost:11434/api/generate</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td class="param-required">必填</td><td>模型名称,如 "gemma3"</td></tr>
|
||
<tr><td class="param-name">prompt</td><td class="param-type">string</td><td class="param-optional">可选</td><td>提示文本。省略时仅加载模型</td></tr>
|
||
<tr><td class="param-name">suffix</td><td class="param-type">string</td><td class="param-optional">可选</td><td>中间填充模式 (FIM) 中,出现在 prompt 后、response 前的文本</td></tr>
|
||
<tr><td class="param-name">images</td><td class="param-type">string[]</td><td class="param-optional">可选</td><td>Base64 编码的图像数组(多模态模型)</td></tr>
|
||
<tr><td class="param-name">format</td><td class="param-type">string | object</td><td class="param-optional">可选</td><td>结构化输出格式,可传 "json" 或 JSON Schema 对象</td></tr>
|
||
<tr><td class="param-name">system</td><td class="param-type">string</td><td class="param-optional">可选</td><td>系统提示词</td></tr>
|
||
<tr><td class="param-name">stream</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否流式返回(默认 true)</td></tr>
|
||
<tr><td class="param-name">think</td><td class="param-type">boolean | string</td><td class="param-optional">可选</td><td>启用 Thinking 模式。可传 true/false 或 "high"/"medium"/"low"</td></tr>
|
||
<tr><td class="param-name">raw</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>跳过模板处理,返回模型原始输出</td></tr>
|
||
<tr><td class="param-name">keep_alive</td><td class="param-type">string | number</td><td class="param-optional">可选</td><td>模型保持加载时间,如 "5m"。传 0 立即卸载</td></tr>
|
||
<tr><td class="param-name">options</td><td class="param-type">object</td><td class="param-optional">可选</td><td>模型参数(见上方 Options 表格)</td></tr>
|
||
<tr><td class="param-name">logprobs</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否返回 token 的对数概率</td></tr>
|
||
<tr><td class="param-name">top_logprobs</td><td class="param-type">integer</td><td class="param-optional">可选</td><td>每个位置返回的候选 token 数(需 logprobs=true)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">📤 响应字段</div>
|
||
<table class="params">
|
||
<thead><tr><th>字段名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td>模型名称</td></tr>
|
||
<tr><td class="param-name">created_at</td><td class="param-type">string</td><td>ISO 8601 时间戳</td></tr>
|
||
<tr><td class="param-name">response</td><td class="param-type">string</td><td>模型生成的文本</td></tr>
|
||
<tr><td class="param-name">thinking</td><td class="param-type">string</td><td>Thinking 模式下的思考输出</td></tr>
|
||
<tr><td class="param-name">done</td><td class="param-type">boolean</td><td>是否生成完毕</td></tr>
|
||
<tr><td class="param-name">done_reason</td><td class="param-type">string</td><td>停止原因(如 "stop")</td></tr>
|
||
<tr><td class="param-name">total_duration</td><td class="param-type">integer</td><td>总耗时(纳秒)</td></tr>
|
||
<tr><td class="param-name">load_duration</td><td class="param-type">integer</td><td>模型加载耗时(纳秒)</td></tr>
|
||
<tr><td class="param-name">prompt_eval_count</td><td class="param-type">integer</td><td>输入 token 数</td></tr>
|
||
<tr><td class="param-name">prompt_eval_duration</td><td class="param-type">integer</td><td>Prompt 评估耗时(纳秒)</td></tr>
|
||
<tr><td class="param-name">eval_count</td><td class="param-type">integer</td><td>输出 token 数</td></tr>
|
||
<tr><td class="param-name">eval_duration</td><td class="param-type">integer</td><td>生成 token 耗时(纳秒)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="note-box"><strong>💡 提示:</strong>流式模式下,每个 chunk 都是独立的 NDJSON 事件,<code>response</code> 字段为当前片段文本,最后一个 chunk 的 <code>done</code> 为 true 并包含统计信息。</div>
|
||
|
||
<!-- 示例 -->
|
||
<div class="params-title">💻 代码示例</div>
|
||
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'gen-sdk-1')">SDK · 流式生成</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'gen-http-1')">HTTP · 流式生成</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'gen-sdk-2')">SDK · 非流式 + 结构化输出</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'gen-http-2')">HTTP · 结构化输出</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'gen-sdk-3')">SDK · 图像识别</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'gen-http-3')">HTTP · 图像识别</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="gen-sdk-1">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 流式生成</span>
|
||
<span class="hl-kw">const</span> stream = <span class="hl-kw">await</span> ollama.<span class="hl-fn">generate</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">prompt</span>: <span class="hl-str">'用简单的语言解释量子计算'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">true</span>,
|
||
<span class="hl-prop">options</span>: {
|
||
<span class="hl-prop">temperature</span>: <span class="hl-num">0.7</span>,
|
||
<span class="hl-prop">num_predict</span>: <span class="hl-num">512</span>,
|
||
},
|
||
});
|
||
|
||
<span class="hl-kw">for await</span> (<span class="hl-kw">const</span> chunk <span class="hl-kw">of</span> stream) {
|
||
process.stdout.<span class="hl-fn">write</span>(chunk.response);
|
||
<span class="hl-kw">if</span> (chunk.done) {
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`\n\n[完成] 总耗时: ${(chunk.total_duration / 1e9).toFixed(2)}s`</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`[统计] 输入: ${chunk.prompt_eval_count} tokens, 输出: ${chunk.eval_count} tokens`</span>);
|
||
}
|
||
}</pre>
|
||
</div>
|
||
<div class="code-panel" id="gen-http-1">
|
||
<pre><span class="hl-cm">// 流式生成(逐行读取 NDJSON)</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/generate'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">prompt</span>: <span class="hl-str">'用简单的语言解释量子计算'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">true</span>,
|
||
<span class="hl-prop">options</span>: { <span class="hl-prop">temperature</span>: <span class="hl-num">0.7</span> },
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> reader = response.body.getReader();
|
||
<span class="hl-kw">const</span> decoder = <span class="hl-kw">new</span> <span class="hl-fn">TextDecoder</span>();
|
||
<span class="hl-kw">let</span> buffer = <span class="hl-str">''</span>;
|
||
|
||
<span class="hl-kw">while</span> (<span class="hl-kw">true</span>) {
|
||
<span class="hl-kw">const</span> { done, value } = <span class="hl-kw">await</span> reader.<span class="hl-fn">read</span>();
|
||
<span class="hl-kw">if</span> (done) <span class="hl-kw">break</span>;
|
||
|
||
buffer += decoder.<span class="hl-fn">decode</span>(value, { <span class="hl-prop">stream</span>: <span class="hl-kw">true</span> });
|
||
<span class="hl-kw">const</span> lines = buffer.<span class="hl-fn">split</span>(<span class="hl-str">'\n'</span>);
|
||
buffer = lines.<span class="hl-fn">pop</span>(); <span class="hl-cm">// 保留不完整行</span>
|
||
|
||
<span class="hl-kw">for</span> (<span class="hl-kw">const</span> line <span class="hl-kw">of</span> lines) {
|
||
<span class="hl-kw">if</span> (!line.<span class="hl-fn">trim</span>()) <span class="hl-kw">continue</span>;
|
||
<span class="hl-kw">const</span> chunk = JSON.<span class="hl-fn">parse</span>(line);
|
||
process.stdout.<span class="hl-fn">write</span>(chunk.response);
|
||
<span class="hl-kw">if</span> (chunk.done) console.<span class="hl-fn">log</span>(<span class="hl-str">'\n[流结束]'</span>);
|
||
}
|
||
}</pre>
|
||
</div>
|
||
<div class="code-panel" id="gen-sdk-2">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 非流式 + 结构化 JSON 输出</span>
|
||
<span class="hl-kw">const</span> result = <span class="hl-kw">await</span> ollama.<span class="hl-fn">generate</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">prompt</span>: <span class="hl-str">'列出中国人口最多的5个城市,包含城市名和人口数'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
<span class="hl-prop">format</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'object'</span>,
|
||
<span class="hl-prop">properties</span>: {
|
||
<span class="hl-prop">cities</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'array'</span>,
|
||
<span class="hl-prop">items</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'object'</span>,
|
||
<span class="hl-prop">properties</span>: {
|
||
<span class="hl-prop">name</span>: { <span class="hl-prop">type</span>: <span class="hl-str">'string'</span> },
|
||
<span class="hl-prop">population</span>: { <span class="hl-prop">type</span>: <span class="hl-str">'integer'</span> },
|
||
},
|
||
<span class="hl-prop">required</span>: [<span class="hl-str">'name'</span>, <span class="hl-str">'population'</span>],
|
||
},
|
||
},
|
||
},
|
||
<span class="hl-prop">required</span>: [<span class="hl-str">'cities'</span>],
|
||
},
|
||
});
|
||
|
||
<span class="hl-kw">const</span> data = JSON.<span class="hl-fn">parse</span>(result.response);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'结构化结果:'</span>, JSON.<span class="hl-fn">stringify</span>(data, <span class="hl-kw">null</span>, <span class="hl-num">2</span>));</pre>
|
||
</div>
|
||
<div class="code-panel" id="gen-http-2">
|
||
<pre><span class="hl-cm">// HTTP 非流式 + 结构化输出</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/generate'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">prompt</span>: <span class="hl-str">'列出中国人口最多的5个城市'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
<span class="hl-prop">format</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'object'</span>,
|
||
<span class="hl-prop">properties</span>: {
|
||
<span class="hl-prop">cities</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'array'</span>,
|
||
<span class="hl-prop">items</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'object'</span>,
|
||
<span class="hl-prop">properties</span>: {
|
||
<span class="hl-prop">name</span>: { <span class="hl-prop">type</span>: <span class="hl-str">'string'</span> },
|
||
<span class="hl-prop">population</span>: { <span class="hl-prop">type</span>: <span class="hl-str">'integer'</span> },
|
||
},
|
||
<span class="hl-prop">required</span>: [<span class="hl-str">'name'</span>, <span class="hl-str">'population'</span>],
|
||
},
|
||
},
|
||
},
|
||
<span class="hl-prop">required</span>: [<span class="hl-str">'cities'</span>],
|
||
},
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> data = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(JSON.<span class="hl-fn">parse</span>(data.response));</pre>
|
||
</div>
|
||
<div class="code-panel" id="gen-sdk-3">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">import</span> { readFileSync } <span class="hl-kw">from</span> <span class="hl-str">'fs'</span>;
|
||
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 读取图片并转为 Base64</span>
|
||
<span class="hl-kw">const</span> imageBuffer = <span class="hl-fn">readFileSync</span>(<span class="hl-str">'./photo.jpg'</span>);
|
||
<span class="hl-kw">const</span> imageBase64 = imageBuffer.<span class="hl-fn">toString</span>(<span class="hl-str">'base64'</span>);
|
||
|
||
<span class="hl-cm">// 多模态图像识别</span>
|
||
<span class="hl-kw">const</span> result = <span class="hl-kw">await</span> ollama.<span class="hl-fn">generate</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">prompt</span>: <span class="hl-str">'这张图片里有什么?请详细描述。'</span>,
|
||
<span class="hl-prop">images</span>: [imageBase64],
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
});
|
||
|
||
console.<span class="hl-fn">log</span>(result.response);</pre>
|
||
</div>
|
||
<div class="code-panel" id="gen-http-3">
|
||
<pre><span class="hl-cm">// HTTP 图像识别</span>
|
||
<span class="hl-cm">// 将本地图片转为 Base64</span>
|
||
<span class="hl-kw">const</span> fs = <span class="hl-fn">require</span>(<span class="hl-str">'fs'</span>);
|
||
<span class="hl-kw">const</span> imageBuffer = fs.<span class="hl-fn">readFileSync</span>(<span class="hl-str">'./photo.jpg'</span>);
|
||
<span class="hl-kw">const</span> imageBase64 = imageBuffer.<span class="hl-fn">toString</span>(<span class="hl-str">'base64'</span>);
|
||
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/generate'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">prompt</span>: <span class="hl-str">'这张图片里有什么?请详细描述。'</span>,
|
||
<span class="hl-prop">images</span>: [imageBase64],
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> data = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(data.response);</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-title">📤 响应示例</div>
|
||
<div class="response-block">
|
||
<pre>{
|
||
<span class="hl-prop">"model"</span>: <span class="hl-str">"gemma3"</span>,
|
||
<span class="hl-prop">"created_at"</span>: <span class="hl-str">"2026-05-18T08:14:07.414671Z"</span>,
|
||
<span class="hl-prop">"response"</span>: <span class="hl-str">"量子计算是一种利用量子力学原理进行计算的新型计算方式..."</span>,
|
||
<span class="hl-prop">"done"</span>: <span class="hl-kw">true</span>,
|
||
<span class="hl-prop">"done_reason"</span>: <span class="hl-str">"stop"</span>,
|
||
<span class="hl-prop">"total_duration"</span>: <span class="hl-num">174560334</span>,
|
||
<span class="hl-prop">"load_duration"</span>: <span class="hl-num">101397084</span>,
|
||
<span class="hl-prop">"prompt_eval_count"</span>: <span class="hl-num">11</span>,
|
||
<span class="hl-prop">"prompt_eval_duration"</span>: <span class="hl-num">13074791</span>,
|
||
<span class="hl-prop">"eval_count"</span>: <span class="hl-num">128</span>,
|
||
<span class="hl-prop">"eval_duration"</span>: <span class="hl-num">52479709</span>
|
||
}</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== CHAT ==================== -->
|
||
<section class="api-section" id="chat">
|
||
<h2><span class="method method-post">POST</span> /api/chat</h2>
|
||
<p class="desc">对话模式生成消息。支持多轮对话、工具调用 (Tool Calling)、Thinking 模式、结构化输出、图像输入、logprobs。适用于 gpt-oss、Gemma 3、Qwen3 等模型。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-post">POST</span>
|
||
<span class="url">http://localhost:11434/api/chat</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td class="param-required">必填</td><td>模型名称</td></tr>
|
||
<tr><td class="param-name">messages</td><td class="param-type">array</td><td class="param-required">必填</td><td>对话历史消息数组</td></tr>
|
||
<tr><td class="param-name">messages[].role</td><td class="param-type">string</td><td class="param-required">必填</td><td>角色: "system" | "user" | "assistant" | "tool"</td></tr>
|
||
<tr><td class="param-name">messages[].content</td><td class="param-type">string</td><td class="param-required">必填</td><td>消息文本</td></tr>
|
||
<tr><td class="param-name">messages[].images</td><td class="param-type">string[]</td><td class="param-optional">可选</td><td>Base64 编码的图像数组</td></tr>
|
||
<tr><td class="param-name">messages[].tool_calls</td><td class="param-type">array</td><td class="param-optional">可选</td><td>工具调用请求</td></tr>
|
||
<tr><td class="param-name">tools</td><td class="param-type">array</td><td class="param-optional">可选</td><td>可用的函数工具列表</td></tr>
|
||
<tr><td class="param-name">format</td><td class="param-type">string | object</td><td class="param-optional">可选</td><td>结构化输出格式</td></tr>
|
||
<tr><td class="param-name">stream</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否流式返回(默认 true)</td></tr>
|
||
<tr><td class="param-name">think</td><td class="param-type">boolean | string</td><td class="param-optional">可选</td><td>Thinking 模式</td></tr>
|
||
<tr><td class="param-name">keep_alive</td><td class="param-type">string | number</td><td class="param-optional">可选</td><td>模型保持加载时间</td></tr>
|
||
<tr><td class="param-name">options</td><td class="param-type">object</td><td class="param-optional">可选</td><td>模型参数</td></tr>
|
||
<tr><td class="param-name">logprobs</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否返回对数概率</td></tr>
|
||
<tr><td class="param-name">top_logprobs</td><td class="param-type">integer</td><td class="param-optional">可选</td><td>每位置候选 token 数</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">📤 响应字段</div>
|
||
<table class="params">
|
||
<thead><tr><th>字段名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td>模型名称</td></tr>
|
||
<tr><td class="param-name">created_at</td><td class="param-type">string</td><td>ISO 8601 时间戳</td></tr>
|
||
<tr><td class="param-name">message</td><td class="param-type">object</td><td>包含 role, content, thinking, tool_calls 等</td></tr>
|
||
<tr><td class="param-name">message.role</td><td class="param-type">string</td><td>始终为 "assistant"</td></tr>
|
||
<tr><td class="param-name">message.content</td><td class="param-type">string</td><td>助手回复文本</td></tr>
|
||
<tr><td class="param-name">message.thinking</td><td class="param-type">string</td><td>Thinking 模式的思考输出</td></tr>
|
||
<tr><td class="param-name">message.tool_calls</td><td class="param-type">array</td><td>模型请求的工具调用</td></tr>
|
||
<tr><td class="param-name">message.images</td><td class="param-type">string[]</td><td>Base64 编码的图像(部分模型支持)</td></tr>
|
||
<tr><td class="param-name">done</td><td class="param-type">boolean</td><td>是否完成</td></tr>
|
||
<tr><td class="param-name">done_reason</td><td class="param-type">string</td><td>停止原因</td></tr>
|
||
<tr><td class="param-name">total_duration</td><td class="param-type">integer</td><td>总耗时(纳秒)</td></tr>
|
||
<tr><td class="param-name">eval_count</td><td class="param-type">integer</td><td>输出 token 数</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'chat-sdk-1')">SDK · 多轮对话</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'chat-http-1')">HTTP · 多轮对话</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'chat-sdk-2')">SDK · 工具调用</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'chat-http-2')">HTTP · 工具调用</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'chat-sdk-3')">SDK · Thinking 模式</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'chat-http-3')">HTTP · Thinking 模式</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="chat-sdk-1">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 多轮对话</span>
|
||
<span class="hl-kw">const</span> messages = [
|
||
{ <span class="hl-prop">role</span>: <span class="hl-str">'system'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'你是一个专业的编程助手,请用中文回答。'</span> },
|
||
{ <span class="hl-prop">role</span>: <span class="hl-str">'user'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'JavaScript 中 Promise 和 async/await 的区别是什么?'</span> },
|
||
];
|
||
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> ollama.<span class="hl-fn">chat</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">messages</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">true</span>,
|
||
});
|
||
|
||
<span class="hl-kw">let</span> fullReply = <span class="hl-str">''</span>;
|
||
<span class="hl-kw">for await</span> (<span class="hl-kw">const</span> chunk <span class="hl-kw">of</span> response) {
|
||
<span class="hl-kw">const</span> text = chunk.message.content;
|
||
fullReply += text;
|
||
process.stdout.<span class="hl-fn">write</span>(text);
|
||
}
|
||
|
||
<span class="hl-cm">// 追加助手回复,继续对话</span>
|
||
messages.<span class="hl-fn">push</span>({ <span class="hl-prop">role</span>: <span class="hl-str">'assistant'</span>, <span class="hl-prop">content</span>: fullReply });
|
||
messages.<span class="hl-fn">push</span>({ <span class="hl-prop">role</span>: <span class="hl-str">'user'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'能给一个 async/await 的代码示例吗?'</span> });</pre>
|
||
</div>
|
||
<div class="code-panel" id="chat-http-1">
|
||
<pre><span class="hl-cm">// HTTP 多轮对话(非流式)</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/chat'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
<span class="hl-prop">messages</span>: [
|
||
{ <span class="hl-prop">role</span>: <span class="hl-str">'system'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'你是一个专业的编程助手。'</span> },
|
||
{ <span class="hl-prop">role</span>: <span class="hl-str">'user'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'解释 JavaScript 的事件循环机制'</span> },
|
||
],
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> data = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(data.message.content);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`输出 ${data.eval_count} tokens,耗时 ${(data.eval_duration / 1e6).toFixed(0)}ms`</span>);</pre>
|
||
</div>
|
||
<div class="code-panel" id="chat-sdk-2">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 定义工具</span>
|
||
<span class="hl-kw">const</span> tools = [{
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'function'</span>,
|
||
<span class="hl-prop">function</span>: {
|
||
<span class="hl-prop">name</span>: <span class="hl-str">'get_weather'</span>,
|
||
<span class="hl-prop">description</span>: <span class="hl-str">'获取指定城市的当前天气信息'</span>,
|
||
<span class="hl-prop">parameters</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'object'</span>,
|
||
<span class="hl-prop">properties</span>: {
|
||
<span class="hl-prop">city</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'string'</span>,
|
||
<span class="hl-prop">description</span>: <span class="hl-str">'城市名称,如 "北京"'</span>,
|
||
},
|
||
<span class="hl-prop">unit</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'string'</span>,
|
||
<span class="hl-prop">enum</span>: [<span class="hl-str">'celsius'</span>, <span class="hl-str">'fahrenheit'</span>],
|
||
<span class="hl-prop">description</span>: <span class="hl-str">'温度单位'</span>,
|
||
},
|
||
},
|
||
<span class="hl-prop">required</span>: [<span class="hl-str">'city'</span>],
|
||
},
|
||
},
|
||
}];
|
||
|
||
<span class="hl-cm">// 第一轮:模型可能请求调用工具</span>
|
||
<span class="hl-kw">const</span> response1 = <span class="hl-kw">await</span> ollama.<span class="hl-fn">chat</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'qwen3'</span>,
|
||
<span class="hl-prop">messages</span>: [{ <span class="hl-prop">role</span>: <span class="hl-str">'user'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'北京今天天气怎么样?'</span> }],
|
||
<span class="hl-prop">tools</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
});
|
||
|
||
<span class="hl-kw">if</span> (response1.message.tool_calls?.length) {
|
||
<span class="hl-kw">const</span> toolCall = response1.message.tool_calls[<span class="hl-num">0</span>];
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`模型调用: ${toolCall.function.name}`</span>, toolCall.function.arguments);
|
||
|
||
<span class="hl-cm">// 模拟工具执行结果</span>
|
||
<span class="hl-kw">const</span> weatherResult = <span class="hl-str">'晴天,温度 22°C,微风'</span>;
|
||
|
||
<span class="hl-cm">// 第二轮:将工具结果返回给模型</span>
|
||
<span class="hl-kw">const</span> response2 = <span class="hl-kw">await</span> ollama.<span class="hl-fn">chat</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'qwen3'</span>,
|
||
<span class="hl-prop">messages</span>: [
|
||
{ <span class="hl-prop">role</span>: <span class="hl-str">'user'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'北京今天天气怎么样?'</span> },
|
||
response1.message,
|
||
{
|
||
<span class="hl-prop">role</span>: <span class="hl-str">'tool'</span>,
|
||
<span class="hl-prop">content</span>: weatherResult,
|
||
},
|
||
],
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
});
|
||
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'最终回复:'</span>, response2.message.content);
|
||
}</pre>
|
||
</div>
|
||
<div class="code-panel" id="chat-http-2">
|
||
<pre><span class="hl-cm">// HTTP 工具调用</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/chat'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'qwen3'</span>,
|
||
<span class="hl-prop">messages</span>: [
|
||
{ <span class="hl-prop">role</span>: <span class="hl-str">'user'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'巴黎今天天气如何?'</span> },
|
||
],
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
<span class="hl-prop">tools</span>: [{
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'function'</span>,
|
||
<span class="hl-prop">function</span>: {
|
||
<span class="hl-prop">name</span>: <span class="hl-str">'get_current_weather'</span>,
|
||
<span class="hl-prop">description</span>: <span class="hl-str">'获取指定地点的当前天气'</span>,
|
||
<span class="hl-prop">parameters</span>: {
|
||
<span class="hl-prop">type</span>: <span class="hl-str">'object'</span>,
|
||
<span class="hl-prop">properties</span>: {
|
||
<span class="hl-prop">location</span>: { <span class="hl-prop">type</span>: <span class="hl-str">'string'</span>, <span class="hl-prop">description</span>: <span class="hl-str">'地点'</span> },
|
||
<span class="hl-prop">format</span>: { <span class="hl-prop">type</span>: <span class="hl-str">'string'</span>, <span class="hl-prop">enum</span>: [<span class="hl-str">'celsius'</span>, <span class="hl-str">'fahrenheit'</span>] },
|
||
},
|
||
<span class="hl-prop">required</span>: [<span class="hl-str">'location'</span>, <span class="hl-str">'format'</span>],
|
||
},
|
||
},
|
||
}],
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> data = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'工具调用:'</span>, data.message.tool_calls);</pre>
|
||
</div>
|
||
<div class="code-panel" id="chat-sdk-3">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// Thinking 模式 - 让模型先思考再回答</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> ollama.<span class="hl-fn">chat</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gpt-oss'</span>,
|
||
<span class="hl-prop">messages</span>: [
|
||
{ <span class="hl-prop">role</span>: <span class="hl-str">'user'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'如果一个房间里有3个人,每两个人握手一次,一共握了几次手?'</span> },
|
||
],
|
||
<span class="hl-prop">think</span>: <span class="hl-str">'low'</span>, <span class="hl-cm">// 可选: true/false/"high"/"medium"/"low"</span>
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">true</span>,
|
||
});
|
||
|
||
<span class="hl-kw">let</span> thinking = <span class="hl-str">''</span>;
|
||
<span class="hl-kw">let</span> content = <span class="hl-str">''</span>;
|
||
<span class="hl-kw">for await</span> (<span class="hl-kw">const</span> chunk <span class="hl-kw">of</span> response) {
|
||
<span class="hl-kw">if</span> (chunk.message.thinking) {
|
||
thinking += chunk.message.thinking;
|
||
process.stderr.<span class="hl-fn">write</span>(chunk.message.thinking); <span class="hl-cm">// 思考过程</span>
|
||
}
|
||
<span class="hl-kw">if</span> (chunk.message.content) {
|
||
content += chunk.message.content;
|
||
process.stdout.<span class="hl-fn">write</span>(chunk.message.content); <span class="hl-cm">// 最终答案</span>
|
||
}
|
||
}</pre>
|
||
</div>
|
||
<div class="code-panel" id="chat-http-3">
|
||
<pre><span class="hl-cm">// HTTP Thinking 模式(流式读取)</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/chat'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'gpt-oss'</span>,
|
||
<span class="hl-prop">messages</span>: [
|
||
{ <span class="hl-prop">role</span>: <span class="hl-str">'user'</span>, <span class="hl-prop">content</span>: <span class="hl-str">'如果一个房间里有3个人,每两个人握手一次,一共握了几次手?'</span> },
|
||
],
|
||
<span class="hl-prop">think</span>: <span class="hl-str">'low'</span>,
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> reader = response.body.getReader();
|
||
<span class="hl-kw">const</span> decoder = <span class="hl-kw">new</span> <span class="hl-fn">TextDecoder</span>();
|
||
<span class="hl-kw">let</span> buffer = <span class="hl-str">''</span>;
|
||
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'=== 思考过程 ==='</span>);
|
||
<span class="hl-kw">while</span> (<span class="hl-kw">true</span>) {
|
||
<span class="hl-kw">const</span> { done, value } = <span class="hl-kw">await</span> reader.<span class="hl-fn">read</span>();
|
||
<span class="hl-kw">if</span> (done) <span class="hl-kw">break</span>;
|
||
|
||
buffer += decoder.<span class="hl-fn">decode</span>(value, { <span class="hl-prop">stream</span>: <span class="hl-kw">true</span> });
|
||
<span class="hl-kw">const</span> lines = buffer.<span class="hl-fn">split</span>(<span class="hl-str">'\n'</span>);
|
||
buffer = lines.<span class="hl-fn">pop</span>();
|
||
|
||
<span class="hl-kw">for</span> (<span class="hl-kw">const</span> line <span class="hl-kw">of</span> lines) {
|
||
<span class="hl-kw">if</span> (!line.<span class="hl-fn">trim</span>()) <span class="hl-kw">continue</span>;
|
||
<span class="hl-kw">const</span> chunk = JSON.<span class="hl-fn">parse</span>(line);
|
||
<span class="hl-kw">if</span> (chunk.message?.thinking) {
|
||
process.stderr.<span class="hl-fn">write</span>(chunk.message.thinking);
|
||
}
|
||
<span class="hl-kw">if</span> (chunk.message?.content) {
|
||
process.stdout.<span class="hl-fn">write</span>(chunk.message.content);
|
||
}
|
||
}
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-title">📤 响应示例</div>
|
||
<div class="response-block">
|
||
<pre>{
|
||
<span class="hl-prop">"model"</span>: <span class="hl-str">"gemma3"</span>,
|
||
<span class="hl-prop">"created_at"</span>: <span class="hl-str">"2026-05-18T08:14:07.414671Z"</span>,
|
||
<span class="hl-prop">"message"</span>: {
|
||
<span class="hl-prop">"role"</span>: <span class="hl-str">"assistant"</span>,
|
||
<span class="hl-prop">"content"</span>: <span class="hl-str">"Promise 和 async/await 的主要区别在于语法和错误处理方式..."</span>
|
||
},
|
||
<span class="hl-prop">"done"</span>: <span class="hl-kw">true</span>,
|
||
<span class="hl-prop">"done_reason"</span>: <span class="hl-str">"stop"</span>,
|
||
<span class="hl-prop">"total_duration"</span>: <span class="hl-num">174560334</span>,
|
||
<span class="hl-prop">"load_duration"</span>: <span class="hl-num">101397084</span>,
|
||
<span class="hl-prop">"prompt_eval_count"</span>: <span class="hl-num">24</span>,
|
||
<span class="hl-prop">"prompt_eval_duration"</span>: <span class="hl-num">13074791</span>,
|
||
<span class="hl-prop">"eval_count"</span>: <span class="hl-num">156</span>,
|
||
<span class="hl-prop">"eval_duration"</span>: <span class="hl-num">52479709</span>
|
||
}</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== EMBED ==================== -->
|
||
<section class="api-section" id="embed">
|
||
<h2><span class="method method-post">POST</span> /api/embed</h2>
|
||
<p class="desc">生成文本的向量嵌入。用于语义搜索、RAG 检索增强生成、文本相似度比较等场景。支持批量输入和自定义维度。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-post">POST</span>
|
||
<span class="url">http://localhost:11434/api/embed</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td class="param-required">必填</td><td>嵌入模型名称,如 "embeddinggemma"</td></tr>
|
||
<tr><td class="param-name">input</td><td class="param-type">string | string[]</td><td class="param-required">必填</td><td>待编码的文本或文本数组</td></tr>
|
||
<tr><td class="param-name">truncate</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否截断超长输入(默认 true)</td></tr>
|
||
<tr><td class="param-name">dimensions</td><td class="param-type">integer</td><td class="param-optional">可选</td><td>生成的嵌入维度数</td></tr>
|
||
<tr><td class="param-name">keep_alive</td><td class="param-type">string</td><td class="param-optional">可选</td><td>模型保持加载时间</td></tr>
|
||
<tr><td class="param-name">options</td><td class="param-type">object</td><td class="param-optional">可选</td><td>模型参数</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">📤 响应字段</div>
|
||
<table class="params">
|
||
<thead><tr><th>字段名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td>使用的模型</td></tr>
|
||
<tr><td class="param-name">embeddings</td><td class="param-type">number[][]</td><td>向量嵌入数组</td></tr>
|
||
<tr><td class="param-name">total_duration</td><td class="param-type">integer</td><td>总耗时(纳秒)</td></tr>
|
||
<tr><td class="param-name">load_duration</td><td class="param-type">integer</td><td>模型加载耗时(纳秒)</td></tr>
|
||
<tr><td class="param-name">prompt_eval_count</td><td class="param-type">integer</td><td>输入 token 数</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'embed-sdk')">SDK · 批量嵌入</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'embed-http')">HTTP · 批量嵌入</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'embed-usage')">实际用法 · 语义搜索</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="embed-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 单条文本嵌入</span>
|
||
<span class="hl-kw">const</span> single = <span class="hl-kw">await</span> ollama.<span class="hl-fn">embed</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'embeddinggemma'</span>,
|
||
<span class="hl-prop">input</span>: <span class="hl-str">'Ollama 是一个本地运行大语言模型的工具'</span>,
|
||
});
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`维度: ${single.embeddings[0].length}`</span>);
|
||
|
||
<span class="hl-cm">// 批量文本嵌入</span>
|
||
<span class="hl-kw">const</span> batch = <span class="hl-kw">await</span> ollama.<span class="hl-fn">embed</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'embeddinggemma'</span>,
|
||
<span class="hl-prop">input</span>: [
|
||
<span class="hl-str">'JavaScript 是一种编程语言'</span>,
|
||
<span class="hl-str">'Python 常用于数据科学'</span>,
|
||
<span class="hl-str">'机器学习是 AI 的子领域'</span>,
|
||
],
|
||
<span class="hl-prop">dimensions</span>: <span class="hl-num">256</span>, <span class="hl-cm">// 自定义维度</span>
|
||
});
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`生成了 ${batch.embeddings.length} 个向量`</span>);</pre>
|
||
</div>
|
||
<div class="code-panel" id="embed-http">
|
||
<pre><span class="hl-cm">// HTTP 批量嵌入</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/embed'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'embeddinggemma'</span>,
|
||
<span class="hl-prop">input</span>: [
|
||
<span class="hl-str">'什么是机器学习?'</span>,
|
||
<span class="hl-str">'深度学习与传统机器学习的区别'</span>,
|
||
<span class="hl-str">'如何训练一个神经网络'</span>,
|
||
],
|
||
<span class="hl-prop">dimensions</span>: <span class="hl-num">128</span>,
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> data = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`模型: ${data.model}`</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`向量数: ${data.embeddings.length}`</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`维度: ${data.embeddings[0].length}`</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`耗时: ${(data.total_duration / 1e6).toFixed(0)}ms`</span>);</pre>
|
||
</div>
|
||
<div class="code-panel" id="embed-usage">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 实际用法: 语义搜索</span>
|
||
<span class="hl-kw">function</span> <span class="hl-fn">cosineSimilarity</span>(a, b) {
|
||
<span class="hl-kw">const</span> dot = a.<span class="hl-fn">reduce</span>((s, v, i) => s + v * b[i], <span class="hl-num">0</span>);
|
||
<span class="hl-kw">const</span> magA = Math.<span class="hl-fn">sqrt</span>(a.<span class="hl-fn">reduce</span>((s, v) => s + v * v, <span class="hl-num">0</span>));
|
||
<span class="hl-kw">const</span> magB = Math.<span class="hl-fn">sqrt</span>(b.<span class="hl-fn">reduce</span>((s, v) => s + v * v, <span class="hl-num">0</span>));
|
||
<span class="hl-kw">return</span> dot / (magA * magB);
|
||
}
|
||
|
||
<span class="hl-kw">const</span> docs = [
|
||
<span class="hl-str">'Python 是一种通用编程语言'</span>,
|
||
<span class="hl-str">'机器学习使用统计方法让计算机学习'</span>,
|
||
<span class="hl-str">'React 是一个前端 JavaScript 框架'</span>,
|
||
];
|
||
|
||
<span class="hl-cm">// 生成文档嵌入</span>
|
||
<span class="hl-kw">const</span> docEmbeddings = <span class="hl-kw">await</span> ollama.<span class="hl-fn">embed</span>({ <span class="hl-prop">model</span>: <span class="hl-str">'embeddinggemma'</span>, <span class="hl-prop">input</span>: docs });
|
||
|
||
<span class="hl-cm">// 生成查询嵌入</span>
|
||
<span class="hl-kw">const</span> query = <span class="hl-str">'什么是 AI'</span>;
|
||
<span class="hl-kw">const</span> queryEmbed = <span class="hl-kw">await</span> ollama.<span class="hl-fn">embed</span>({ <span class="hl-prop">model</span>: <span class="hl-str">'embeddinggemma'</span>, <span class="hl-prop">input</span>: query });
|
||
|
||
<span class="hl-cm">// 计算相似度并排序</span>
|
||
<span class="hl-kw">const</span> results = docEmbeddings.embeddings
|
||
.<span class="hl-fn">map</span>((emb, i) => ({
|
||
<span class="hl-prop">text</span>: docs[i],
|
||
<span class="hl-prop">score</span>: <span class="hl-fn">cosineSimilarity</span>(queryEmbed.embeddings[<span class="hl-num">0</span>], emb),
|
||
}))
|
||
.<span class="hl-fn">sort</span>((a, b) => b.score - a.score);
|
||
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'搜索结果:'</span>, results);</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-title">📤 响应示例</div>
|
||
<div class="response-block">
|
||
<pre>{
|
||
<span class="hl-prop">"model"</span>: <span class="hl-str">"embeddinggemma"</span>,
|
||
<span class="hl-prop">"embeddings"</span>: [
|
||
[<span class="hl-num">0.010071029</span>, <span class="hl-num">-0.0017594862</span>, <span class="hl-num">0.05007221</span>, <span class="hl-num">0.04692972</span>, <span class="hl-num">0.054916814</span>, ...]
|
||
],
|
||
<span class="hl-prop">"total_duration"</span>: <span class="hl-num">14143917</span>,
|
||
<span class="hl-prop">"load_duration"</span>: <span class="hl-num">1019500</span>,
|
||
<span class="hl-prop">"prompt_eval_count"</span>: <span class="hl-num">8</span>
|
||
}</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== TAGS ==================== -->
|
||
<section class="api-section" id="tags">
|
||
<h2><span class="method method-get">GET</span> /api/tags</h2>
|
||
<p class="desc">列出所有已下载到本地的模型及其详细信息(名称、大小、格式、量化级别等)。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-get">GET</span>
|
||
<span class="url">http://localhost:11434/api/tags</span>
|
||
</div>
|
||
|
||
<div class="params-title">📤 响应字段</div>
|
||
<table class="params">
|
||
<thead><tr><th>字段名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">models[]</td><td class="param-type">array</td><td>模型列表</td></tr>
|
||
<tr><td class="param-name">models[].name</td><td class="param-type">string</td><td>模型名称</td></tr>
|
||
<tr><td class="param-name">models[].model</td><td class="param-type">string</td><td>模型标识</td></tr>
|
||
<tr><td class="param-name">models[].remote_model</td><td class="param-type">string</td><td>上游模型名称(远程模型时)</td></tr>
|
||
<tr><td class="param-name">models[].remote_host</td><td class="param-type">string</td><td>上游 Ollama 主机 URL(远程模型时)</td></tr>
|
||
<tr><td class="param-name">models[].modified_at</td><td class="param-type">string</td><td>最后修改时间</td></tr>
|
||
<tr><td class="param-name">models[].size</td><td class="param-type">integer</td><td>磁盘大小(字节)</td></tr>
|
||
<tr><td class="param-name">models[].digest</td><td class="param-type">string</td><td>SHA256 摘要</td></tr>
|
||
<tr><td class="param-name">models[].details</td><td class="param-type">object</td><td>格式、家族、参数量、量化级别</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'tags-sdk')">SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'tags-http')">HTTP</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="tags-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 列出所有本地模型</span>
|
||
<span class="hl-kw">const</span> { models } = <span class="hl-kw">await</span> ollama.<span class="hl-fn">list</span>();
|
||
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`共 ${models.length} 个模型:\n`</span>);
|
||
<span class="hl-kw">for</span> (<span class="hl-kw">const</span> m <span class="hl-kw">of</span> models) {
|
||
<span class="hl-kw">const</span> sizeGB = (m.size / 1e9).<span class="hl-fn">toFixed</span>(<span class="hl-num">2</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">` ${m.name} [${sizeGB} GB] ${m.details.parameter_size} ${m.details.quantization_level}`</span>);
|
||
}</pre>
|
||
</div>
|
||
<div class="code-panel" id="tags-http">
|
||
<pre><span class="hl-cm">// HTTP 列出模型</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/tags'</span>);
|
||
<span class="hl-kw">const</span> { models } = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
|
||
<span class="hl-kw">for</span> (<span class="hl-kw">const</span> m <span class="hl-kw">of</span> models) {
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`${m.name} - ${(m.size / 1e9).toFixed(2)} GB`</span>);
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-title">📤 响应示例</div>
|
||
<div class="response-block">
|
||
<pre>{
|
||
<span class="hl-prop">"models"</span>: [
|
||
{
|
||
<span class="hl-prop">"name"</span>: <span class="hl-str">"gemma3:latest"</span>,
|
||
<span class="hl-prop">"model"</span>: <span class="hl-str">"gemma3:latest"</span>,
|
||
<span class="hl-prop">"modified_at"</span>: <span class="hl-str">"2026-05-17T23:34:03.409490317+08:00"</span>,
|
||
<span class="hl-prop">"size"</span>: <span class="hl-num">3338801804</span>,
|
||
<span class="hl-prop">"digest"</span>: <span class="hl-str">"a2af6cc3eb7fa8be8504abaf9b04e88f17a119ec..."</span>,
|
||
<span class="hl-prop">"details"</span>: {
|
||
<span class="hl-prop">"format"</span>: <span class="hl-str">"gguf"</span>,
|
||
<span class="hl-prop">"family"</span>: <span class="hl-str">"gemma"</span>,
|
||
<span class="hl-prop">"families"</span>: [<span class="hl-str">"gemma"</span>],
|
||
<span class="hl-prop">"parameter_size"</span>: <span class="hl-str">"4.3B"</span>,
|
||
<span class="hl-prop">"quantization_level"</span>: <span class="hl-str">"Q4_K_M"</span>
|
||
}
|
||
}
|
||
]
|
||
}</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== SHOW ==================== -->
|
||
<section class="api-section" id="show">
|
||
<h2><span class="method method-post">POST</span> /api/show</h2>
|
||
<p class="desc">查看指定模型的详细信息,包括参数设置、许可证、模板、模型能力、模型架构元数据等。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-post">POST</span>
|
||
<span class="url">http://localhost:11434/api/show</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td class="param-required">必填</td><td>模型名称</td></tr>
|
||
<tr><td class="param-name">verbose</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否返回详细的 verbose 信息</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">📤 响应字段</div>
|
||
<table class="params">
|
||
<thead><tr><th>字段名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">parameters</td><td class="param-type">string</td><td>模型参数设置文本</td></tr>
|
||
<tr><td class="param-name">license</td><td class="param-type">string</td><td>模型许可证</td></tr>
|
||
<tr><td class="param-name">modified_at</td><td class="param-type">string</td><td>最后修改时间</td></tr>
|
||
<tr><td class="param-name">details</td><td class="param-type">object</td><td>模型格式、家族、参数量等</td></tr>
|
||
<tr><td class="param-name">template</td><td class="param-type">string</td><td>提示模板</td></tr>
|
||
<tr><td class="param-name">capabilities</td><td class="param-type">string[]</td><td>支持的功能列表(如 "completion", "vision")</td></tr>
|
||
<tr><td class="param-name">model_info</td><td class="param-type">object</td><td>详细的模型架构元数据</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'show-sdk')">SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'show-http')">HTTP</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="show-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 查看模型信息</span>
|
||
<span class="hl-kw">const</span> info = <span class="hl-kw">await</span> ollama.<span class="hl-fn">show</span>({ <span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>, <span class="hl-prop">verbose</span>: <span class="hl-kw">true</span> });
|
||
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'能力:'</span>, info.capabilities); <span class="hl-cm">// ["completion", "vision"]</span>
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'参数量:'</span>, info.details.parameter_size);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'格式:'</span>, info.details.format);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'上下文长度:'</span>, info.model_info?.[<span class="hl-str">'gemma3.context_length'</span>]);</pre>
|
||
</div>
|
||
<div class="code-panel" id="show-http">
|
||
<pre><span class="hl-cm">// HTTP 查看模型详情</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/show'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({ <span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>, <span class="hl-prop">verbose</span>: <span class="hl-kw">true</span> }),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> info = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'能力:'</span>, info.capabilities);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'模型信息:'</span>, info.model_info);</pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== CREATE ==================== -->
|
||
<section class="api-section" id="create">
|
||
<h2><span class="method method-post">POST</span> /api/create</h2>
|
||
<p class="desc">基于已有模型创建自定义模型。可以自定义系统提示词、模板、参数,也可以进行量化。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-post">POST</span>
|
||
<span class="url">http://localhost:11434/api/create</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td class="param-required">必填</td><td>新模型的名称</td></tr>
|
||
<tr><td class="param-name">from</td><td class="param-type">string</td><td class="param-optional">可选</td><td>基础模型名称</td></tr>
|
||
<tr><td class="param-name">template</td><td class="param-type">string</td><td class="param-optional">可选</td><td>自定义提示模板</td></tr>
|
||
<tr><td class="param-name">system</td><td class="param-type">string</td><td class="param-optional">可选</td><td>嵌入模型的系统提示词</td></tr>
|
||
<tr><td class="param-name">license</td><td class="param-type">string | string[]</td><td class="param-optional">可选</td><td>许可证</td></tr>
|
||
<tr><td class="param-name">parameters</td><td class="param-type">object</td><td class="param-optional">可选</td><td>模型参数</td></tr>
|
||
<tr><td class="param-name">messages</td><td class="param-type">array</td><td class="param-optional">可选</td><td>用于模型的消息历史</td></tr>
|
||
<tr><td class="param-name">quantize</td><td class="param-type">string</td><td class="param-optional">可选</td><td>量化级别,如 "q4_K_M", "q8_0"</td></tr>
|
||
<tr><td class="param-name">stream</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否流式返回创建进度(默认 true)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'create-sdk')">SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'create-http')">HTTP</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'create-quant')">量化模型</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="create-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 创建自定义模型</span>
|
||
<span class="hl-kw">const</span> stream = <span class="hl-kw">await</span> ollama.<span class="hl-fn">create</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'my-assistant'</span>,
|
||
<span class="hl-prop">from</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">system</span>: <span class="hl-str">'你是一个专业的中文编程助手。回答简洁明了,优先使用代码示例。'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">true</span>,
|
||
});
|
||
|
||
<span class="hl-kw">for await</span> (<span class="hl-kw">const</span> chunk <span class="hl-kw">of</span> stream) {
|
||
<span class="hl-kw">if</span> (chunk.status) process.stdout.<span class="hl-fn">write</span>(<span class="hl-str">`状态: ${chunk.status}\n`</span>);
|
||
}</pre>
|
||
</div>
|
||
<div class="code-panel" id="create-http">
|
||
<pre><span class="hl-cm">// HTTP 创建模型</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/create'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'emoji-bot'</span>,
|
||
<span class="hl-prop">from</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">system</span>: <span class="hl-str">'你只会用表情符号回答问题。'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> result = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(result.status); <span class="hl-cm">// "success"</span></pre>
|
||
</div>
|
||
<div class="code-panel" id="create-quant">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 创建量化版本模型(减少显存占用)</span>
|
||
<span class="hl-kw">const</span> stream = <span class="hl-kw">await</span> ollama.<span class="hl-fn">create</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'llama3:8b-q4'</span>,
|
||
<span class="hl-prop">from</span>: <span class="hl-str">'llama3:8b-instruct-fp16'</span>,
|
||
<span class="hl-prop">quantize</span>: <span class="hl-str">'q4_K_M'</span>, <span class="hl-cm">// 量化到 Q4_K_M 级别</span>
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">true</span>,
|
||
});
|
||
|
||
<span class="hl-kw">for await</span> (<span class="hl-kw">const</span> chunk <span class="hl-kw">of</span> stream) {
|
||
<span class="hl-kw">if</span> (chunk.total && chunk.completed) {
|
||
<span class="hl-kw">const</span> pct = ((chunk.completed / chunk.total) * <span class="hl-num">100</span>).<span class="hl-fn">toFixed</span>(<span class="hl-num">1</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`量化进度: ${pct}%`</span>);
|
||
}
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== COPY ==================== -->
|
||
<section class="api-section" id="copy">
|
||
<h2><span class="method method-post">POST</span> /api/copy</h2>
|
||
<p class="desc">复制一个已有模型到新名称。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-post">POST</span>
|
||
<span class="url">http://localhost:11434/api/copy</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">source</td><td class="param-type">string</td><td class="param-required">必填</td><td>源模型名称</td></tr>
|
||
<tr><td class="param-name">destination</td><td class="param-type">string</td><td class="param-required">必填</td><td>目标模型名称</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'copy-sdk')">SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'copy-http')">HTTP</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="copy-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-kw">await</span> ollama.<span class="hl-fn">copy</span>({
|
||
<span class="hl-prop">source</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">destination</span>: <span class="hl-str">'gemma3-backup'</span>,
|
||
});
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'复制完成'</span>);</pre>
|
||
</div>
|
||
<div class="code-panel" id="copy-http">
|
||
<pre><span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/copy'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">source</span>: <span class="hl-str">'gemma3'</span>,
|
||
<span class="hl-prop">destination</span>: <span class="hl-str">'gemma3-backup'</span>,
|
||
}),
|
||
});
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'复制完成'</span>); <span class="hl-cm">// 成功返回 200</span></pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== DELETE ==================== -->
|
||
<section class="api-section" id="delete">
|
||
<h2><span class="method method-delete">DELETE</span> /api/delete</h2>
|
||
<p class="desc">删除本地模型文件,释放磁盘空间。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-delete">DELETE</span>
|
||
<span class="url">http://localhost:11434/api/delete</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td class="param-required">必填</td><td>要删除的模型名称</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="note-box"><strong>⚠️ 警告:</strong>此操作不可恢复。模型文件将被永久删除。</div>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'del-sdk')">SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'del-http')">HTTP</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="del-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-kw">await</span> ollama.<span class="hl-fn">delete</span>({ <span class="hl-prop">model</span>: <span class="hl-str">'gemma3-backup'</span> });
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'模型已删除'</span>);</pre>
|
||
</div>
|
||
<div class="code-panel" id="del-http">
|
||
<pre><span class="hl-cm">// HTTP 删除模型 (注意是 DELETE 方法)</span>
|
||
<span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/delete'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'DELETE'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({ <span class="hl-prop">model</span>: <span class="hl-str">'gemma3-backup'</span> }),
|
||
});
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'模型已删除'</span>);</pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== PULL ==================== -->
|
||
<section class="api-section" id="pull">
|
||
<h2><span class="method method-post">POST</span> /api/pull</h2>
|
||
<p class="desc">从 Ollama 模型仓库下载模型到本地。支持流式进度显示。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-post">POST</span>
|
||
<span class="url">http://localhost:11434/api/pull</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td class="param-required">必填</td><td>要下载的模型名称,如 "gemma3", "llama3:70b"</td></tr>
|
||
<tr><td class="param-name">insecure</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>允许不安全连接下载</td></tr>
|
||
<tr><td class="param-name">stream</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否流式返回进度(默认 true)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">📤 响应字段</div>
|
||
<table class="params">
|
||
<thead><tr><th>字段名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">status</td><td class="param-type">string</td><td>状态消息(如 "pulling manifest", "success")</td></tr>
|
||
<tr><td class="param-name">digest</td><td class="param-type">string</td><td>当前层的内容摘要</td></tr>
|
||
<tr><td class="param-name">total</td><td class="param-type">integer</td><td>总字节数</td></tr>
|
||
<tr><td class="param-name">completed</td><td class="param-type">integer</td><td>已传输字节数</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'pull-sdk')">SDK · 进度条</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'pull-http')">HTTP · 进度条</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="pull-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 下载模型并显示进度</span>
|
||
<span class="hl-kw">const</span> stream = <span class="hl-kw">await</span> ollama.<span class="hl-fn">pull</span>({ <span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span>, <span class="hl-prop">stream</span>: <span class="hl-kw">true</span> });
|
||
|
||
<span class="hl-kw">for await</span> (<span class="hl-kw">const</span> chunk <span class="hl-kw">of</span> stream) {
|
||
<span class="hl-kw">if</span> (chunk.total && chunk.completed) {
|
||
<span class="hl-kw">const</span> pct = ((chunk.completed / chunk.total) * <span class="hl-num">100</span>).<span class="hl-fn">toFixed</span>(<span class="hl-num">1</span>);
|
||
<span class="hl-kw">const</span> doneMB = (chunk.completed / 1e6).<span class="hl-fn">toFixed</span>(<span class="hl-num">0</span>);
|
||
<span class="hl-kw">const</span> totalMB = (chunk.total / 1e6).<span class="hl-fn">toFixed</span>(<span class="hl-num">0</span>);
|
||
process.stdout.<span class="hl-fn">write</span>(<span class="hl-str">`\r${chunk.status}: ${pct}% (${doneMB}/${totalMB} MB)`</span>);
|
||
} <span class="hl-kw">else</span> {
|
||
console.<span class="hl-fn">log</span>(chunk.status);
|
||
}
|
||
}
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'\n下载完成!'</span>);</pre>
|
||
</div>
|
||
<div class="code-panel" id="pull-http">
|
||
<pre><span class="hl-cm">// HTTP 下载模型并跟踪进度</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/pull'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({ <span class="hl-prop">model</span>: <span class="hl-str">'gemma3'</span> }),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> reader = response.body.getReader();
|
||
<span class="hl-kw">const</span> decoder = <span class="hl-kw">new</span> <span class="hl-fn">TextDecoder</span>();
|
||
<span class="hl-kw">let</span> buffer = <span class="hl-str">''</span>;
|
||
|
||
<span class="hl-kw">while</span> (<span class="hl-kw">true</span>) {
|
||
<span class="hl-kw">const</span> { done, value } = <span class="hl-kw">await</span> reader.<span class="hl-fn">read</span>();
|
||
<span class="hl-kw">if</span> (done) <span class="hl-kw">break</span>;
|
||
|
||
buffer += decoder.<span class="hl-fn">decode</span>(value, { <span class="hl-prop">stream</span>: <span class="hl-kw">true</span> });
|
||
<span class="hl-kw">const</span> lines = buffer.<span class="hl-fn">split</span>(<span class="hl-str">'\n'</span>);
|
||
buffer = lines.<span class="hl-fn">pop</span>();
|
||
|
||
<span class="hl-kw">for</span> (<span class="hl-kw">const</span> line <span class="hl-kw">of</span> lines) {
|
||
<span class="hl-kw">if</span> (!line.<span class="hl-fn">trim</span>()) <span class="hl-kw">continue</span>;
|
||
<span class="hl-kw">const</span> event = JSON.<span class="hl-fn">parse</span>(line);
|
||
<span class="hl-kw">if</span> (event.total) {
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`${event.status}: ${((event.completed / event.total) * 100).toFixed(1)}%`</span>);
|
||
}
|
||
}
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== PUSH ==================== -->
|
||
<section class="api-section" id="push">
|
||
<h2><span class="method method-post">POST</span> /api/push</h2>
|
||
<p class="desc">将本地自定义模型推送到 Ollama 模型仓库(需要先登录 <code>ollama.com</code>)。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-post">POST</span>
|
||
<span class="url">http://localhost:11434/api/push</span>
|
||
</div>
|
||
|
||
<div class="params-title">📥 请求参数</div>
|
||
<table class="params">
|
||
<thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">model</td><td class="param-type">string</td><td class="param-required">必填</td><td>要推送的模型名称(格式:username/model)</td></tr>
|
||
<tr><td class="param-name">insecure</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>允许不安全连接</td></tr>
|
||
<tr><td class="param-name">stream</td><td class="param-type">boolean</td><td class="param-optional">可选</td><td>是否流式返回进度(默认 true)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'push-sdk')">SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'push-http')">HTTP</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="push-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 推送模型到仓库</span>
|
||
<span class="hl-kw">const</span> stream = <span class="hl-kw">await</span> ollama.<span class="hl-fn">push</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'my-username/my-custom-model'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">true</span>,
|
||
});
|
||
|
||
<span class="hl-kw">for await</span> (<span class="hl-kw">const</span> chunk <span class="hl-kw">of</span> stream) {
|
||
<span class="hl-kw">if</span> (chunk.total && chunk.completed) {
|
||
<span class="hl-kw">const</span> pct = ((chunk.completed / chunk.total) * <span class="hl-num">100</span>).<span class="hl-fn">toFixed</span>(<span class="hl-num">1</span>);
|
||
process.stdout.<span class="hl-fn">write</span>(<span class="hl-str">`\r推送进度: ${pct}%`</span>);
|
||
}
|
||
}
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'\n推送完成!'</span>);</pre>
|
||
</div>
|
||
<div class="code-panel" id="push-http">
|
||
<pre><span class="hl-cm">// HTTP 推送模型</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/push'</span>, {
|
||
<span class="hl-prop">method</span>: <span class="hl-str">'POST'</span>,
|
||
<span class="hl-prop">headers</span>: { <span class="hl-str">'Content-Type'</span>: <span class="hl-str">'application/json'</span> },
|
||
<span class="hl-prop">body</span>: <span class="hl-fn">JSON.stringify</span>({
|
||
<span class="hl-prop">model</span>: <span class="hl-str">'my-username/my-model'</span>,
|
||
<span class="hl-prop">stream</span>: <span class="hl-kw">false</span>,
|
||
}),
|
||
});
|
||
|
||
<span class="hl-kw">const</span> result = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(result.status); <span class="hl-cm">// "success"</span></pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== PS ==================== -->
|
||
<section class="api-section" id="ps">
|
||
<h2><span class="method method-get">GET</span> /api/ps</h2>
|
||
<p class="desc">列出当前正在内存中运行的模型。显示 VRAM 占用、上下文长度、过期时间等信息。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-get">GET</span>
|
||
<span class="url">http://localhost:11434/api/ps</span>
|
||
</div>
|
||
|
||
<div class="params-title">📤 响应字段</div>
|
||
<table class="params">
|
||
<thead><tr><th>字段名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">models[]</td><td class="param-type">array</td><td>正在运行的模型列表</td></tr>
|
||
<tr><td class="param-name">models[].name</td><td class="param-type">string</td><td>模型名称</td></tr>
|
||
<tr><td class="param-name">models[].size</td><td class="param-type">integer</td><td>模型大小(字节)</td></tr>
|
||
<tr><td class="param-name">models[].digest</td><td class="param-type">string</td><td>SHA256 摘要</td></tr>
|
||
<tr><td class="param-name">models[].details</td><td class="param-type">object</td><td>格式、家族等详细信息</td></tr>
|
||
<tr><td class="param-name">models[].expires_at</td><td class="param-type">string</td><td>模型自动卸载时间</td></tr>
|
||
<tr><td class="param-name">models[].size_vram</td><td class="param-type">integer</td><td>VRAM 占用(字节)</td></tr>
|
||
<tr><td class="param-name">models[].context_length</td><td class="param-type">integer</td><td>当前上下文长度</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'ps-sdk')">SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'ps-http')">HTTP</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="ps-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 列出正在运行的模型</span>
|
||
<span class="hl-kw">const</span> { models } = <span class="hl-kw">await</span> ollama.<span class="hl-fn">ps</span>();
|
||
|
||
<span class="hl-kw">if</span> (models.length === <span class="hl-num">0</span>) {
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">'当前没有运行中的模型'</span>);
|
||
} <span class="hl-kw">else</span> {
|
||
<span class="hl-kw">for</span> (<span class="hl-kw">const</span> m <span class="hl-kw">of</span> models) {
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`模型: ${m.name}`</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">` VRAM: ${(m.size_vram / 1e9).toFixed(2)} GB`</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">` 上下文: ${m.context_length} tokens`</span>);
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">` 过期: ${m.expires_at}`</span>);
|
||
}
|
||
}</pre>
|
||
</div>
|
||
<div class="code-panel" id="ps-http">
|
||
<pre><span class="hl-cm">// HTTP 列出运行中的模型</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/ps'</span>);
|
||
<span class="hl-kw">const</span> { models } = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`运行中: ${models.length} 个模型`</span>);
|
||
<span class="hl-kw">for</span> (<span class="hl-kw">const</span> m <span class="hl-kw">of</span> models) {
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">` ${m.name} → VRAM: ${(m.size_vram / 1e9).toFixed(2)} GB`</span>);
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-title">📤 响应示例</div>
|
||
<div class="response-block">
|
||
<pre>{
|
||
<span class="hl-prop">"models"</span>: [
|
||
{
|
||
<span class="hl-prop">"name"</span>: <span class="hl-str">"gemma3:latest"</span>,
|
||
<span class="hl-prop">"model"</span>: <span class="hl-str">"gemma3:latest"</span>,
|
||
<span class="hl-prop">"size"</span>: <span class="hl-num">6591830464</span>,
|
||
<span class="hl-prop">"digest"</span>: <span class="hl-str">"a2af6cc3eb7fa..."</span>,
|
||
<span class="hl-prop">"details"</span>: {
|
||
<span class="hl-prop">"parent_model"</span>: <span class="hl-str">""</span>,
|
||
<span class="hl-prop">"format"</span>: <span class="hl-str">"gguf"</span>,
|
||
<span class="hl-prop">"family"</span>: <span class="hl-str">"gemma3"</span>,
|
||
<span class="hl-prop">"families"</span>: [<span class="hl-str">"gemma3"</span>],
|
||
<span class="hl-prop">"parameter_size"</span>: <span class="hl-str">"4.3B"</span>,
|
||
<span class="hl-prop">"quantization_level"</span>: <span class="hl-str">"Q4_K_M"</span>
|
||
},
|
||
<span class="hl-prop">"expires_at"</span>: <span class="hl-str">"2026-05-18T16:47:07.93355+08:00"</span>,
|
||
<span class="hl-prop">"size_vram"</span>: <span class="hl-num">5333539264</span>,
|
||
<span class="hl-prop">"context_length"</span>: <span class="hl-num">4096</span>
|
||
}
|
||
]
|
||
}</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ==================== VERSION ==================== -->
|
||
<section class="api-section" id="version">
|
||
<h2><span class="method method-get">GET</span> /api/version</h2>
|
||
<p class="desc">获取当前 Ollama 服务的版本号。</p>
|
||
|
||
<div class="endpoint-bar">
|
||
<span class="http-method method-get">GET</span>
|
||
<span class="url">http://localhost:11434/api/version</span>
|
||
</div>
|
||
|
||
<div class="params-title">📤 响应字段</div>
|
||
<table class="params">
|
||
<thead><tr><th>字段名</th><th>类型</th><th>描述</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="param-name">version</td><td class="param-type">string</td><td>Ollama 版本号</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="params-title">💻 代码示例</div>
|
||
<div class="code-tabs">
|
||
<button class="code-tab active" onclick="switchTab(this, 'ver-sdk')">SDK</button>
|
||
<button class="code-tab" onclick="switchTab(this, 'ver-http')">HTTP</button>
|
||
</div>
|
||
<div class="code-block">
|
||
<div class="code-panel active" id="ver-sdk">
|
||
<pre><span class="hl-kw">import</span> Ollama <span class="hl-kw">from</span> <span class="hl-str">'ollama'</span>;
|
||
<span class="hl-kw">const</span> ollama = <span class="hl-kw">new</span> <span class="hl-fn">Ollama</span>();
|
||
|
||
<span class="hl-cm">// 获取版本</span>
|
||
<span class="hl-kw">const</span> { version } = <span class="hl-kw">await</span> ollama.<span class="hl-fn">version</span>();
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`Ollama 版本: ${version}`</span>); <span class="hl-cm">// 如 "0.12.6"</span></pre>
|
||
</div>
|
||
<div class="code-panel" id="ver-http">
|
||
<pre><span class="hl-cm">// HTTP 获取版本</span>
|
||
<span class="hl-kw">const</span> response = <span class="hl-kw">await</span> <span class="hl-fn">fetch</span>(<span class="hl-str">'http://localhost:11434/api/version'</span>);
|
||
<span class="hl-kw">const</span> { version } = <span class="hl-kw">await</span> response.<span class="hl-fn">json</span>();
|
||
console.<span class="hl-fn">log</span>(<span class="hl-str">`Ollama 版本: ${version}`</span>);</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-title">📤 响应示例</div>
|
||
<div class="response-block">
|
||
<pre>{
|
||
<span class="hl-prop">"version"</span>: <span class="hl-str">"0.12.6"</span>
|
||
}</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- FOOTER -->
|
||
<div style="text-align:center; padding: 40px 0 20px; color: var(--text-dim); font-size: 13px; border-top: 1px solid var(--border);">
|
||
<p>📄 本文档基于 <a href="https://docs.ollama.com" style="color:var(--accent)">docs.ollama.com</a> 官方文档生成</p>
|
||
<p>支持模型: <strong style="color:var(--green)">gpt-oss · Gemma 3 · DeepSeek-R1 · Qwen3</strong> · 文档日期: <strong style="color:var(--accent)">2026-05-18</strong></p>
|
||
<p style="margin-top:8px;">JavaScript SDK: <a href="https://github.com/ollama/ollama-js" style="color:var(--accent)">github.com/ollama/ollama-js</a> · Python SDK: <a href="https://github.com/ollama/ollama-python" style="color:var(--accent)">github.com/ollama/ollama-python</a></p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function switchTab(clickedTab, panelId) {
|
||
const tabContainer = clickedTab.parentElement;
|
||
const blockContainer = tabContainer.nextElementSibling;
|
||
|
||
tabContainer.querySelectorAll('.code-tab').forEach(t => t.classList.remove('active'));
|
||
blockContainer.querySelectorAll('.code-panel').forEach(p => p.classList.remove('active'));
|
||
|
||
clickedTab.classList.add('active');
|
||
document.getElementById(panelId).classList.add('active');
|
||
}
|
||
|
||
// Smooth scroll for sidebar links
|
||
document.querySelectorAll('.sidebar a[href^="#"]').forEach(a => {
|
||
a.addEventListener('click', e => {
|
||
e.preventDefault();
|
||
const target = document.querySelector(a.getAttribute('href'));
|
||
if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
});
|
||
});
|
||
|
||
// Highlight active sidebar item on scroll
|
||
const sections = document.querySelectorAll('.api-section');
|
||
const sidebarLinks = document.querySelectorAll('.sidebar a[href^="#"]');
|
||
|
||
window.addEventListener('scroll', () => {
|
||
let current = '';
|
||
sections.forEach(s => {
|
||
if (window.scrollY >= s.offsetTop - 100) current = s.id;
|
||
});
|
||
sidebarLinks.forEach(a => {
|
||
a.classList.toggle('active', a.getAttribute('href') === '#' + current);
|
||
});
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|