拾忆🍂拾忆🍂
  • cpp
  • MySQL
  • Oracle
  • PostgreSQL
  • MyBatis
  • API升级
  • HMOS
  • 百变小组件
  • hdc
  • 元服务
  • Java
  • MinIO
  • Stream
  • JSP & Struts2
  • Spring
  • FFmpeg
  • Linux
  • Git
  • Nginx
  • Ollama
  • Adobe Audition
  • Aseprite
  • Excel
  • Markdown基本用法
  • MuseScore 4.x
  • UVR
  • Windows
  • emoji-cheat-sheet
  • IDE快捷键
  • obs-studio
  • YOLO
  • Python
  • VuePress 2.x
  • 内置组件
  • markdown-container
  • markdown-ext
  • markdown-hint
  • markdown-preview
  • markdown-tab
  • Markdown扩展语法
  • 插件配置
  • prismjs
  • 样式
  • CSS
  • JS
  • TS
  • Vue3
主页
梦的开始🌅
  • cpp
  • MySQL
  • Oracle
  • PostgreSQL
  • MyBatis
  • API升级
  • HMOS
  • 百变小组件
  • hdc
  • 元服务
  • Java
  • MinIO
  • Stream
  • JSP & Struts2
  • Spring
  • FFmpeg
  • Linux
  • Git
  • Nginx
  • Ollama
  • Adobe Audition
  • Aseprite
  • Excel
  • Markdown基本用法
  • MuseScore 4.x
  • UVR
  • Windows
  • emoji-cheat-sheet
  • IDE快捷键
  • obs-studio
  • YOLO
  • Python
  • VuePress 2.x
  • 内置组件
  • markdown-container
  • markdown-ext
  • markdown-hint
  • markdown-preview
  • markdown-tab
  • Markdown扩展语法
  • 插件配置
  • prismjs
  • 样式
  • CSS
  • JS
  • TS
  • Vue3
主页
梦的开始🌅
  • 「从开始,到永久」
  • C艹

    • cpp
  • Database

    • MySQL
    • Oracle
    • PostgreSQL
    • MyBatis
  • HarmonyOS

    • API升级
    • HMOS
    • 百变小组件
    • hdc
    • 元服务
  • Java

    • Java
    • MinIO
    • Stream
    • JSP & Struts2
    • Spring
  • Linux

    • FFmpeg
    • Linux
    • Git
    • Nginx
  • LLM

    • Ollama
  • Others

    • Adobe Audition
    • Aseprite
    • Excel
    • Markdown基本用法
    • MuseScore 4.x
    • UVR
    • Windows
    • emoji-cheat-sheet
    • IDE快捷键
    • obs-studio
    • YOLO
  • Python

    • Python
  • VuePress

    • VuePress 2.x
    • 内置组件
    • markdown-container
    • markdown-ext
    • markdown-hint
    • markdown-preview
    • markdown-tab
    • Markdown扩展语法
    • 插件配置
    • prismjs
    • 样式
  • Web

    • CSS
    • JS
    • TS
    • Vue3
  • 主页

文档📃

常见问题 - Ollama 中文文档


安装位置

  1. 默认安装位置改变:
    语法(建议先创建好位置):

    软件名称 /DIR="指定安装位置"
    

    示例:

    OllamaSetup.exe /DIR="D:\Program Files\ollama"
    
  2. 更改模型下载 & 本地create的默认路径:
    新增环境变量:OLLAMA_MODELS,值为路径D:\Program Files\ollama\models

    如果已经在本地创建或下载过模型了,需要重启ollama,将C盘->用户->你自己的电脑名称->.ollama文件夹下的models文件夹直接覆盖剪切在环境变量所指向的文件夹上,使之最终对应环境变量所设置的值。
    使用ollama list验证

文件夹

执行ollama run或者ollama create之后,下载或生成的文件被分别放在models下的两个文件内,我称为 实体文件 和 描述文件:

models
├─blobs																	// 实体文件
│      sha256-xxxxxxxxx 								// gguf文件、参数文件、template等文件均在这个文件夹内以此类型名称存放
│
└─manifests															// 描述文件
    └─registry.ollama.ai								// ollama 域名
        ├─huihui_ai											// ollama run 从ollama官网下载的大模型对应的组织名
        │  └─deepseek-r1-abliterated
        │          8b										// ollama run 之后生成的,和官网的url呈对应关系,文件内容描述这个模型对应的gguf文件和参数、template等文件的名称
        │          8b-0528-qwen3-q8_0		// 同上
        │
        └─library												// ollama create 从本地gguf文件创建的大模型默认组织名
            └─qwen3
                    latest							// ollama create 之后生成的,文件内容描述这个模型对应的gguf文件和参数、template等文件的名称

从另一台电脑复制

基于上面文件夹内结构,可以得出,只要复制了文件夹内的 实体文件 和 描述文件 并粘贴到另一台电脑的对应结构目录下即可。

环境变量

注释中标有*的代表就算没有手动设置也是ollama启动之后的默认值;

变量名值注释
OLLAMA_MODELSD:\Program Files\ollama\models模型安装位置(默认为 ~/.ollama/models ),包括create和run
OLLAMA_HOST0.0.0.0*允许远程访问的时候需要改成这个
OLLAMA_PORT11434*端口
OLLAMA_ORIGINS**允许跨域
OLLAMA_KEEP_ALIVE600数字单位就是秒,也可以是10m代表十分钟
OLLAMA_NOHISTORY1不在 ~/.ollama/history 中记录用户提问历史

启动命令

ollama run qwen3 --verbose
  • --verbose: 每次回答之后输出tokens/s等信息
  • --model-path: 指定模型存储的目标路径
  • --host: 监听主机地址
  • --post: 监听端口号(默认:11434)
  • --gpu: Ollama 会自动检测 GPU 并使用,但需确保系统已安装 CUDA 和相关驱动(Windows暂不支持,须通过WSL或Docker)
  • ``:
  • ``:

注:,如果需要共享上下文,需通过 Ollama 的服务模式(如 ollama serve)统一管理模型实例。


从本地GGUF中create

将Qwen3-30B-A3B-Q4_0.gguf和Modelfile文件放在同一文件夹

ollama create qwen3 -f ./Modelfile

Modelfile文件示例(根据Qwen3:30B-A3B),其中的内容还是要根据各个模型所修改:

FROM ./Qwen3-30B-A3B-Q4_0.gguf

PARAMETER stop "<|im_start|>,<|im_end|>"
# set the temperature to 1 [higher is more creative, lower is more coherent]
PARAMETER temperature 0.6
PARAMETER top_k 20
PARAMETER top_p 0.95
PARAMETER min_p 0
PARAMETER repeat_penalty 1

TEMPLATE """{{ if .Messages }}
{{- if or .System .Tools }}<|im_start|>system
{{ .System }}
{{- if .Tools }}

# Tools

You are provided with function signatures within <tools></tools> XML tags:
<tools>{{- range .Tools }}
{"type": "function", "function": {{ .Function }}}{{- end }}
</tools>

For each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:
<tool_call>
{"name": <function-name>, "arguments": <args-json-object>}
</tool_call>
{{- end }}<|im_end|>
{{ end }}
{{- range $i, $_ := .Messages }}
{{- $last := eq (len (slice $.Messages $i)) 1 -}}
{{- if eq .Role "user" }}<|im_start|>user
{{ .Content }}<|im_end|>
{{ else if eq .Role "assistant" }}<|im_start|>assistant
{{ if .Content }}{{ .Content }}
{{- else if .ToolCalls }}<tool_call>
{{ range .ToolCalls }}{"name": "{{ .Function.Name }}", "arguments": {{ .Function.Arguments }}}
{{ end }}</tool_call>
{{- end }}{{ if not $last }}<|im_end|>
{{ end }}
{{- else if eq .Role "tool" }}<|im_start|>user
<tool_response>
{{ .Content }}
</tool_response><|im_end|>
{{ end }}
{{- if and (ne .Role "assistant") $last }}<|im_start|>assistant
{{ end }}
{{- end }}
{{- else }}
{{- if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}<|im_end|>
{{ end }}<|im_start|>assistant
{{ end }}{{ .Response }}{{ if .Response }}<|im_end|>{{ end }}"""

# set the system message
SYSTEM """你是通义千问,你能够回答问题、创作文字、逻辑推理、编程等。你是个乐于助人且善于思考的助手,你可以帮助用户解决一切问题!"""

参数

这些参数也可以在启动ollama run的时候添加在命令里面。

参数技术问答创意写作通用对话通俗解释
temperature0.2-0.50.7-1.00.5-0.7随机性控制:低温输出稳定如教科书,高温放飞想象力
top_k20-4080-10040-60候选词范围:仅从前k个概率最高的词中选择(小=精准,大=多样)
top_p0.9-0.950.85-0.980.9动态候选池:累积概率达p的词才进入选择(避免冷门词干扰)
repeat_penalty1.2-1.51.1-1.31.0-1.2重复惩罚:>1 时抑制重复内容(技术文档需高惩罚防冗余)
num_predict500-8001000-2000800-1200最大生成长度(tokens):控制回答篇幅
num_ctx409681924096-8192上下文窗口大小:决定模型能“记住”多长输入(创意写作需长上下文支持)

temperature 温度:控制回答的创意性和保守性

set the temperature to 1 [higher is more creative, lower is more coherent]

top_k

  • 低 top_k 值(如 20):
    模型仅从概率最高的少量 token 中选择,输出更集中、保守,适合需要严谨答案的场景(例如事实问答)。

  • 高 top_k 值(如 100):
    候选范围扩大,生成内容更多样化,但可能降低连贯性,适合创意任务(如写故事)。

  • 与 top_p(核采样)配合:

    top_k 先筛选出概率最高的k 个 token,top_p 再从中选择累计概率达到阈值 p 的子集,两者结合可平衡生成质量与效率。

    例如:top_k=50, top_p=0.9 表示:

  1. 取前 50 个高概率 token →
  2. 从中筛选累计概率 ≥90% 的 token 集合 →
  3. 最终从该集合中随机采样。
  • 任务类型推荐 top_k推荐 top_p推荐 temperature效果
    技术问答/代码生成20~400.60.2减少错误,保证答案精准性
    创意写作/故事生成60~1000.920.8激发多样性,避免内容重复
    通用对话40~600.850.5平衡连贯性与趣味性

repeat_penalty 惩罚系数

值大于 1.0 (如 1.1, 1.2) 会降低重复的可能性;值小于 1.0 则可能增加重复。

repeat_last_n 检测重复token数量

设置模型回溯检查重复的 token 数量范围。例如,设为 64 意味着模型会检查最近生成的 64 个 token 是否与当前预测的 token 重复,并应用 repeat_penalty。

num_ctx 上下文长度

例如 DeepSeek-R1 使用 ollama show 输出 context length 131072 说明模型支持 128k 长度,但ollama的默认上下文窗口可能仍是 2048 (2k),即使用户的模型支持128K,也需要通过 Modelfile 显式设置 PARAMETER num_ctx 32768 (32k),如果直接 ollama run 下载的模型,则需要手动修修改blobs文件夹下面的参数描述文件,新增 "num_ctx": 32768 (32k)参数。

为什么设置32k,是因为在DeepSeek-R1:8b的模型6G大小启动之后,使用32k上下文长度,ollama 占用内存在14G左右,可以。

另外如果 num_ctx 设置为 131072,则8b模型启动时需要月 64G 显存,在此模型下,上下文长度以k为单位和显存占用存在除以二的关系,例如 128k 占用 64G。


如何保持模型在内存中加载或立即卸载?

默认情况下,模型会在内存中保留 5 分钟后才被卸载。这允许在你向 LLM 发送多个请求时获得更快的响应时间。如果你希望立即从内存中卸载模型,可以使用 ollama stop 命令:

ollama stop qwen3

如果你正在使用 API,可以使用 keep_alive 参数与 /api/generate 和 /api/chat 端点来设置模型在内存中保持的时间。keep_alive 参数可以设置为:

  • 一个持续时间字符串(例如 "10m" 或 "24h")
  • 以秒为单位的数字(例如 3600)
  • 任何负数,这将使模型保持在内存中(例如 -1 或 "-1m")
  • '0',这将在生成响应后立即卸载模型

例如,要预加载模型并将其保留在内存中,可以使用:

linux

curl http://localhost:11434/api/generate -d '{"model": "llama3.2", "keep_alive": -1}'

windows

curl http://localhost:11434/api/generate -d "{\"model\": \"qwen3\", \"keep_alive\": \"10m\"}"

要卸载模型并释放内存,请使用:

curl http://localhost:11434/api/generate -d '{"model": "llama3.2", "keep_alive": 0}'

或者,你可以在启动 Ollama 服务器之前通过设置 OLLAMA_KEEP_ALIVE 环境变量来更改所有模型加载到内存中的时间。OLLAMA_KEEP_ALIVE 变量使用与上述 keep_alive 参数类型相同的参数类型。

keep_alive API 参数在 /api/generate 和 /api/chat API 端点中将覆盖 OLLAMA_KEEP_ALIVE 设置。


/think

Qwen3默认输出思考过程,如果不想输出思考过程在问题后追加/no_think字符,则此Session之后的回答都是不带思考过程的,除非执行/clear清空了此Session。

想要恢复思考过程,需要在下次提问之后追加上/think字符。


使用终端日志记录

如果你通过命令行调用Ollama(例如通过ollama run启动模型),可以使用以下命令记录终端输出:

script -c "ollama run your_model_name" session_log.txt
  • 这会将终端的所有输入输出保存到session_log.txt中,包含你的问答对话。
  • 注意:结束后按 Ctrl+D 退出记录。

————————————————

Open-WebUI🌐

官方中文文档:🏡 主页 | Open WebUI 文档

部署

  • Python:3.11或更高(后端服务需要,可以参考 Python.md 的 conda 来配置多环境)

  • Node.js:版本22.10或更高。(前端开发所需)

  • IDE(可选):我们建议使用类似VSCode的IDE进行代码编辑、调试和集成终端访问。

下载

git clone https://github.com/open-webui/open-webui.git

进入目录

cd open-webui

前端

  1. 环境变量

    cp -RPp .env.example .env
    
  2. 安装依赖

    # 如果很慢就用 pnpm
    npm install
    
  3. 打包

    # 不单独启动前端的话,需要打包一下前端项目
    npm run build
    
    # 首次打包前端之后,如果修改了前端代码,第二次打包可以在`package.json`中加入以下配置
    ## Pyodide是一个将Python运行时环境移植到Web浏览器的工具,允许在浏览器中直接执行Python代码(如文档解析、数据处理等)。由于第一次已经使用过Pyodide了,后续打包就不需要了,节省每次下载py包时间。
    "build:vite": "vite build",
    # 然后执行
    npm run build:vite
    

(现在不用单独启动前端了,后端 uvicorn 服务自动代理前端打包后的 dist 文件夹了)

npm run dev
# 或
npm run preview

后端

  1. 进入后端目录

    cd backend
    
  2. 使用 conda 创建环境

    conda create --name open-webui python=3.11
    
    conda activate open-webui
    
  3. 安装依赖

    pip install -r ./requirements.txt -U
    

    -U 标志可确保您获得最新兼容版本的库,不是必须得。

  4. 启动

    • Linux

      sh dev.sh
      
    • Windows(可以创建一个 dev_windows.bat ,双击运行)

      :: 不显示运行语句
      @echo off 
      
      :: 改编码为:UTF8
      chcp 65001
      
      :: 如果放到桌面上运行,需要取消注释下面两行和检查目录代码
      :: call d:
      :: cd /d "D:\WorkSpace\LLM\open-webui\backend"
      
      :: 检查目录是否存在
      :: if not exist "." (
      ::     echo Error: Directory does not exist!
      ::     pause
      ::     exit /b 1
      :: )
      
      :: 1. 激活 Conda 环境(需要先安装 Conda 并配置环境变量)
      call conda activate open-webui
      
      :: 检查 conda 环境是否激活成功
      if errorlevel 1 (
          echo Error: Failed to activate conda environment!
          pause
          exit /b 1
      )
      
      :: 2. 打开一个cmd窗口,启动 uvicorn并保持cmd窗口(关闭/c)
      start "open-webui-server" cmd /k "uvicorn open_webui.main:app --port 8848 --host 0.0.0.0 --forwarded-allow-ips '*' --reload"
      
      echo Open-WebUI server is starting...
      echo You can access it at: http://localhost:8848
      
  5. 浏览器访问:http://localhost:8848

进入主页慢?

  1. .env文件修改:OPENAI_API_BASE_URL='http://localhost:11434/v1';
    原因:自动请求openai中所有的可用模型api: /v1/models,导致的连接超时10秒;

  2. backend\open_webui\retrieval\utils.py文件,注释掉以下:

    try:
      model_repo_path = snapshot_download(**snapshot_kwargs)
      log.debug(f"model_repo_path: {model_repo_path}")
      return model_repo_path
    except Exception as e:
      log.exception(f"Cannot determine model snapshot path: {e}")
      return model
    

    原因:检测模型在huggingface.co上是否有更新导致的连接超时;

字体更改

  1. 去官网下载字体:JetBrains Mono NL

  2. static\assets\fonts 复制NL相关字体文件到这里

  3. src\app.css 文件,新增:

    @font-face {
      font-family: 'JetBrains Mono NL';
      src: url('/assets/fonts/JetBrainsMonoNL-Regular.ttf');
      font-display: swap;
      font-style: normal;
    }
    
    @font-face {
      font-family: 'JetBrains Mono NL';
      src: url('/assets/fonts/JetBrainsMonoNL-Italic.ttf');
      font-display: swap;
      font-style: italic;
    }
    
    /* 项目运行时主页`html`文件上方被动态加入了`<style>`标签,导致的这个`class`所指向的代码块元素字体改为了`monospace`,但是不知道怎么改,只好先这样改了 */
    .cm-scroller {
      font-family: 'JetBrains Mono NL', -apple-system, BlinkMacSystemFont, 'Inter', ui-sans-serif, system-ui, 'Segoe UI',
        Roboto, Ubuntu, Cantarell, 'Vazirmatn', 'Noto Sans', sans-serif, 'Helvetica Neue', Arial,
        'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji' !important;
    }
    
  4. src\tailwind.css 文件,修改:(最前面加上JetBrains Mono NL)

    @layer base {
      html,
      pre {
        font-family: 'JetBrains Mono NL', -apple-system, BlinkMacSystemFont, 'Inter', ui-sans-serif, system-ui, 'Segoe UI',
          Roboto, Ubuntu, Cantarell, 'Vazirmatn', 'Noto Sans', sans-serif, 'Helvetica Neue', Arial,
          'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
      }
    
  5. 重启 uvicorn 服务。

删除按钮字体颜色更改

删除按钮和其他按钮一样颜色的,不能起到醒目作用,取的项目里的颜色var --color-red-500 = oklch(.637 .237 25.331),对应HEX为#FB2C36

  • src\lib\components\icons\GarbageBin.svelte 删除icon的svg文件,更改:

    stroke="oklch(.637 .237 25.331)"
    
  • src\lib\components\icons\SignOut.svelte 登出icon的svg文件,更改:

    fill="oklch(.637 .237 25.331)"
    
  • src\lib\components\chat\Settings\Chats.svelte 设置 - 对话 - 删除所有对话记录icon的svg代码,更改:

    <!-- 搜索:$i18n.t('Delete All Chats'),这个是文字,上面的`svg`标签是`svg` -->
    文字:style="color:oklch(.637 .237 25.331)"
    svg:fill="oklch(.637 .237 25.331)"
    
    <!-- 搜索 $i18n.t('Are you sure?'),这个是删除确认文字,上面有`svg` -->
    文字:style="color:oklch(.637 .237 25.331)"
    svg:fill="oklch(.637 .237 25.331)"
    
  • “删除”文字颜色修改,以下文件关键字搜索 $i18n.t( ,看参数为 Delete、Sign Out 相关的,给元素加上style="color:oklch(.637 .237 25.331)"

    • src\lib\components\layout\Sidebar\ChatMenu.svelte
    • src\lib\components\notes\Notes\NoteMenu.svelte
    • src\lib\components\admin\Evaluations\FeedbackMenu.svelte
    • src\lib\components\layout\Sidebar\UserMenu.svelte Sign Out
    • src\lib\components\layout\Sidebar\Folders\FolderMenu.svelte
    • src\lib\components\workspace\Prompts\PromptMenu.svelte
    • src\lib\components\workspace\Tools\ToolMenu.svelte
  • “移除”头像,文字颜色修改,同上方检索,参数为 Remove,css样式相同。

    • src\lib\components\chat\Settings\Account.svelte

————————————————

api🛠️

Ollama 提供了多种 REST API 接口,支持生成文本、对话交互、模型管理等功能。以下是详细的 API 调用方式及使用场景:

http://localhost:11434
# 或
http://127.0.0.1:11434

# 兼容 OpenAI 格式
http://127.0.0.1:11434/v1

兼容 OpenAI 风格

若需要以兼容 OpenAI 的风格调用,只需在在 ollama 给出的api地址后面拼接上 /v1 就行了。

一、基础文本生成

POST /api/generate

用途:生成单轮文本响应(非对话场景)。
参数:

  • model (必填): 模型名称(如 qwen3)。
  • prompt (必填): 输入的提示文本。
  • stream (可选): 是否启用流式传输(默认 false)。
  • format (可选): 指定响应格式(如 json)。
  • 其他高级参数:temperature, top_p, max_tokens 等。

使用场景:

  • 单次问答(如翻译、摘要)。
  • 代码生成、文案创作。

示例:

curl http://localhost:11434/api/generate -d '{
  "model": "qwen3",
  "prompt": "用一句话解释量子力学",
  "stream": false
}'

二、对话交互

POST /api/chat

用途:多轮对话交互,维护上下文。
参数:

  • model (必填): 模型名称。
  • messages (必填): 消息历史数组(包含 role 和 content)。
  • stream (可选): 流式传输(默认 false)。

使用场景:

  • 聊天机器人。
  • 多轮任务(如订餐助手、客服)。

示例:

curl http://localhost:11434/api/chat -d '{
  "model": "qwen3",
  "messages": [
    { "role": "user", "content": "你好" },
    { "role": "assistant", "content": "您好!有什么可以帮助您?" },
    { "role": "user", "content": "推荐一本小说" }
  ],
  "stream": false
}'

三、生成嵌入向量

POST /api/embeddings

用途:获取文本的嵌入向量(Embeddings)。
参数:

  • model (必填): 模型名称。
  • prompt (必填): 输入文本。

使用场景:

  • 语义搜索、文本聚类。
  • 机器学习模型的特征输入。

示例:

curl http://localhost:11434/api/embeddings -d '{
  "model": "qwen3",
  "prompt": "人工智能的未来"
}'

四、模型管理

1. 列出本地模型:GET /api/tags

用途:查看已下载的模型列表。
示例:

curl http://localhost:11434/api/tags

2. 拉取模型:POST /api/pull

用途:从仓库下载模型。
参数:

  • name (必填): 模型名称(如 qwen3)。
  • stream (可选): 显示下载进度(默认 false)。

示例:

curl http://localhost:11434/api/pull -d '{
  "name": "qwen3"
}'

3. 删除模型:DELETE /api/delete

用途:删除本地模型。
参数:

  • name (必填): 模型名称。

示例:

curl -X DELETE http://localhost:11434/api/delete -d '{
  "name": "qwen3"
}'

五、高级功能

1. 查看模型信息:POST /api/show

用途:获取模型的详细信息(如参数、模板)。
参数:

  • name (必填): 模型名称。

示例:

curl http://localhost:11434/api/show -d '{
  "name": "qwen3"
}'

2. 创建自定义模型:POST /api/create

用途:通过 Modelfile 创建自定义模型。
参数:

  • name (必填): 新模型名称。
  • modelfile (必填): 模型配置内容。

示例:

curl http://localhost:11434/api/create -d '{
  "name": "my-qwen3",
  "modelfile": "FROM qwen3\nSYSTEM 你是一个幽默的助手..."
}'

六、流式传输(Streaming)

适用场景:实时输出长文本(如逐句显示回答)。
示例(使用 curl 流式生成):

curl http://localhost:11434/api/generate -d '{
  "model": "qwen3",
  "prompt": "写一篇关于环保的文章",
  "stream": true
}'

七、客户端调用

除了直接调用 API,还可使用官方库或 HTTP 客户端:

1. Python 示例:

import requests

response = requests.post(
  "http://localhost:11434/api/generate",
  json={"model": "qwen3", "prompt": "你好"}
)
print(response.json()["response"])

2. JavaScript 示例:

fetch("http://localhost:11434/api/generate", {
  method: "POST",
  body: JSON.stringify({ model: "qwen3", prompt: "Hello" })
})
.then(res => res.json())
.then(data => console.log(data.response));

八、注意事项

  1. 端口:默认使用 11434,若修改需调整 URL。
  2. 认证:Ollama 默认无认证,暴露到公网需谨慎。
  3. 性能:流式传输可提升长文本响应体验。

通过上述 API,您可以在本地灵活调用 qwen3 模型,满足生成、对话、嵌入和管理等多样化需求。

————————————————

js-api🛠️

下面是如何在 JavaScript Web 应用中调用 Ollama API 并处理流式响应的详细指南:


一、基础 API 调用

1. 文本生成(非流式)

async function generateText() {
  try {
    const response = await fetch("http://localhost:11434/api/generate", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        model: "qwen3",
        prompt: "用 JavaScript 写一个快速排序函数",
        stream: false // 明确关闭流式
      })
    });

    const data = await response.json();
    console.log("完整响应:", data.response);
    document.getElementById("output").textContent = data.response;
  } catch (error) {
    console.error("请求失败:", error);
  }
}

2. 对话交互(非流式)

async function chat() {
  const messages = [
    { role: "user", content: "你好" },
    { role: "assistant", content: "您好!需要什么帮助?" },
    { role: "user", content: "推荐适合初学者的编程语言" }
  ];

  const response = await fetch("http://localhost:11434/api/chat", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ model: "qwen3", messages, stream: false })
  });

  const result = await response.json();
  console.log("助手回复:", result.message.content);
}

二、流式响应处理(重点)

1. 使用 Fetch API 处理流式

async function streamGenerate() {
  const outputDiv = document.getElementById("stream-output");
  outputDiv.textContent = ""; // 清空先前内容

  try {
    const response = await fetch("http://localhost:11434/api/generate", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        model: "qwen3",
        prompt: "详细解释神经网络的工作原理",
        stream: true // 启用流式
      })
    });

    // 获取可读流
    const reader = response.body.getReader();
    const decoder = new TextDecoder("utf-8");
    let buffer = "";

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });

      // 处理可能的分块边界(确保完整 JSON 解析)
      try {
        let boundary;
        while ((boundary = buffer.indexOf("\n")) !== -1) {
          const line = buffer.slice(0, boundary);
          buffer = buffer.slice(boundary + 1);

          if (line.trim()) {
            const parsed = JSON.parse(line);
            outputDiv.textContent += parsed.response; // 实时追加内容
          }
        }
      } catch (e) {
        console.warn("解析错误:", e);
      }
    }
  } catch (error) {
    console.error("流式请求失败:", error);
  }
}

2. 使用 EventSource(仅限 GET 请求,需 Ollama 支持 SSE)

如果 Ollama 支持 Server-Sent Events (SSE):

function streamWithSSE() {
  const outputDiv = document.getElementById("stream-output");
  outputDiv.textContent = "";

  const es = new EventSource(`http://localhost:11434/api/generate?prompt=hello&model=qwen3&stream=true`);

  es.onmessage = (event) => {
    const data = JSON.parse(event.data);
    outputDiv.textContent += data.response;
  };

  es.onerror = (error) => {
    console.error("SSE 错误:", error);
    es.close();
  };
}

三、流式处理关键技术点

1. 分块数据拼接

  • 使用 TextDecoder 处理二进制流
  • 通过缓冲区 (buffer) 处理不完整的数据包
  • 按 \n 分割 JSON 行(Ollama 流式响应默认以换行分隔)

2. 实时显示优化

// 使用文档片段减少重绘
const fragment = document.createDocumentFragment();

// 使用 requestAnimationFrame 优化渲染
function updateOutput(text) {
  requestAnimationFrame(() => {
    outputDiv.textContent += text;
    outputDiv.scrollTop = outputDiv.scrollHeight; // 自动滚动到底部
  });
}

3. 中断控制

let controller = null;

function startStream() {
  controller = new AbortController();
  
  fetch(url, {
    signal: controller.signal,
    // ...其他参数
  });
}

function stopStream() {
  if (controller) {
    controller.abort();
    controller = null;
  }
}

四、完整示例:带流式交互的聊天界面

<!DOCTYPE html>
<body>
  <div id="chat-box" style="height: 300px; overflow-y: auto"></div>
  <input id="user-input" type="text">
  <button onclick="sendMessage()">发送</button>

  <script>
    
    const input = document.getElementById("user-input");
    const chatBox = document.getElementById("chat-box");

    async function sendMessage() {
      const userMessage = input.value.trim();
      
      if (!userMessage) return;

      // 显示用户消息
      chatBox.innerHTML += `<div>用户: ${userMessage}</div>`;
      input.value = "";

      // 发起流式请求
      const response = await fetch("http://127.0.0.1:11434/api/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          model: "qwen3",
          messages: [{ role: "user", content: userMessage }],
          stream: true
        })
      });

      // 创建助手消息容器
      const assistantDiv = document.createElement("div");
      assistantDiv.textContent = "助手: ";
      chatBox.appendChild(assistantDiv);

      // 处理流式响应
      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        
        const chunk = decoder.decode(value);
        const lines = chunk.split('\n');
        
        lines.forEach(line => {
          if (line.trim()) {
            try {
              const data = JSON.parse(line);
              assistantDiv.textContent += data.message.content;
            } catch (e) {
              console.warn("解析错误:", e);
            }
          }
        });
      }
    }

	// 输入框回车支持
	input.addEventListener('keypress', (e) => {
		if (e.key === 'Enter') sendMessage();
	});
  </script>
</body>

五、注意事项

  1. 跨域问题:

    • 开发时配置代理(如 vite.config.js):

      export default {
        server: {
          proxy: {
            '/ollama': {
              target: 'http://localhost:11434',
              rewrite: path => path.replace(/^\/ollama/, '')
            }
          }
        }
      }
      
    • 生产环境需通过后端中转或配置 CORS

    • 添加环境变量: OLLAMA_ORIGINS = * 以允许所有域

      OLLAMA_ORIGINS=*
      
    • 如果需要允许浏览器插件,则需要添加环境变量

      OLLAMA_ORIGINS=chrome-extension://*,moz-extension://*,safari-web-extension://*
      
    • Ollama暴露在127.0.0.1和0.0.0.0上,想要指定域名,可以通过设置 OLLAMA_HOST 环境变量来更改绑定地址,多个用逗号连接。

  2. 性能优化:

    • 使用防抖(debounce)处理快速输入
    • 限制历史消息长度(通过 messages.slice(-5) 保留最近 5 条)
    • 添加加载状态指示器
  3. 错误处理:

    try {
      // ...流式处理代码
    } catch (error) {
      if (error.name === 'AbortError') {
        console.log('请求被用户中止');
      } else {
        console.error('请求失败:', error);
        chatBox.innerHTML += `<div style="color: red">错误: ${error.message}</div>`;
      }
    }
    
最近更新: 2025/12/14 00:09
Contributors: Enlin