如何使用 Ollama 的 API 来创建模型

如何使用 Ollama 的 API 来创建模型

简介

创建模型

创建模型的示例

查询 Blob(Binary Large Object)是否存在

推送 Blob 到服务器当中

简介

        Ollama 提供了一个 RESTful API,允许开发者通过 HTTP 请求与 Ollama 服务进行交互。这个 API 覆盖了所有 Ollama 的核心功能,包括模型管理、运行和监控。本篇将介绍如何调用 Ollama 的 RESTful API 来创建模型。

创建模型

端点

POST /api/create

        我们可以从另一个模型、safetensors 目录、GGUF 文件创建模型。如果要从 safetensors 目录或 GGUF 文件创建模型,在此之前必须把各个文件的Blob(Binary Large Object)推送到服务器,然后在请求中的 files 字段中填入其的 blob 关联的文件名和 SHA256 摘要。

参数

  • model:要创建的模型的名称,即 ollama list 当中看到的名字
  • from(可选):指的是现有模型的名称,可以是已经在 ollama 当中创建的,也可以是存在于官方当中的模型,如果本地没有会自动去官方库当中搜索下载
  • files(可选):这是一个字典,key 为模型的文件名,value 为文件对应的 SHA256 摘要,用于指定用于创建模型的 blob
  • adapters(可选):这是一个字典,key 为 LORA 适配器的文件名,value 为文件对应的 SHA256 摘要,把 LORA 适配器应用到基础模型上,实现模型的高效微调
  • template(可选):用于定义模型的提示模板
  • license(可选):遵循的许可协议相关信息
  • system(可选):系统提示
  • parameters(可选):这是一个字典,key 为模型参数名,value 为具体的模型参数值,根据这些参数可以对模型进行微调,这些模型参数有 temperature(温度,控制生成文本的随机性和创造性)、top_k(固定挑选最高概率候选词的数量)、top_p(也称核采样,可动态调整候选词的数量)、max_tokens(限制模型生成文本的最大长度)等
  • messages(可选):这是一个列表,用于创建对话场景,可以保留以往的聊天记录
  • stream(可选):如果设置为 false,响应将作为单个响应对象返回,而对象流
  • quantize(可选):量化类型,用于控制非量化模型的量化规模,例如可从高精度数据类型(例如,float32、float16)转换为低精度数据类型(例如,int8)

不同量化类型及推荐

        目前量化的类型有 q2_K、q3_K_L、q3_K_M、q3_K_S、q4_0、q4_1、q4_K_M、q4_K_S、q5_0、q5_1、q5_K_M、q5_K_S、q6_K、q8_0;推荐把非量化版本的模型量化为 q4_K_M 或 q8_0,这两个类型的量化可以在减少内存占用的同时保留较好的性能。

创建模型的示例

一、创建新模型

        从现有的模型(在 ollama list 或者在官方库当中的模型)当中创建新模型。

请求

curl http://localhost:11434/api/create -d '{
  "model": "mario",
  "from": "llama3.2",
  "system": "You are Mario from Super Mario Bros."
}'

响应

{"status":"using existing layer sha256:dde5aa3fc5ffc17176b5e8bdc82f587b24b2678c6c66101bf7da77af9f7ccdff"}
{"status":"using existing layer sha256:966de95ca8a62200913e3f8bfbf84c8494536f1b94b49166851e76644e966396"}
{"status":"using existing layer sha256:fcc5a6bec9daf9b561a68827b67ab6088e1dba9d1fa2a50d7bbcc8384e0a265d"}
{"status":"using existing layer sha256:a70ff7e570d97baaf4e62ac6e6ad9975e04caa6d900d3742d37698494479e0cd"}
{"status":"creating new layer sha256:941b69ca7dc2a85c053c38d9e8029c9df6224e545060954fa97587f87c044a64"}
{"status":"using existing layer sha256:56bb8bd477a519ffa694fc449c2413c6f0e1d3b1c88fa7e3c9d88d3ae49d4dcb"}
{"status":"writing manifest"}
{"status":"success"}

二、量化一个未量化的完整模型

        量化模型是一个从高到低的过程,需要先拥有一个高精度的模型,例如,float32、float16 这类高精度模型,本例将会把 llama3.1:8b-instruct-fp16 版本量化为 q4_K_M。

请求

curl http://localhost:11434/api/create -d '{
  "model": "llama3.1:8b-q4_K_M",
  "from": "llama3.1:8b-instruct-fp16",
  "quantize": "q4_K_M"
}'

响应

{"status":"quantizing F16 model to Q4_K_M"}
{"status":"creating new layer sha256:52006a88ba4cacaab4e6cd53e470402bdd83dc71c99f88623bfecbd42128f011"}
{"status":"using existing layer sha256:948af2743fc78a328dcb3b0f5a31b3d75f415840fdb699e8b1235978392ecf85"}
{"status":"using existing layer sha256:0ba8f0e314b4264dfd19df045cde9d4c394a52474bf92ed6a3de22a4ca31a177"}
{"status":"using existing layer sha256:56bb8bd477a519ffa694fc449c2413c6f0e1d3b1c88fa7e3c9d88d3ae49d4dcb"}
{"status":"writing manifest"}
{"status":"success"}

三、从 GGUF 文件创建模型

        从 GGUF 文件创建模型需要使用 files 字段,需要把 GGUF 文件的文件名作为 key,GGUF 文件的 SHA256 摘要作为 value 填入 files 字段中。在此之前需要先把 Blob 推送到服务器中,用于完整性验证。

请求

curl http://localhost:11434/api/create -d '{
  "model": "DeepSeek-R1-32B-abliterated-Q4_K_M",
  "files": {
    "test.gguf": "sha256:4de296cf59ba595f8695084cd4e0215784baa1c6b02ee9fc26a250be08b7b6a3"
  }
}'

响应

{"status":"parsing GGUF"}
{"status":"using existing layer sha256:4de296cf59ba595f8695084cd4e0215784baa1c6b02ee9fc26a250be08b7b6a3"}
{"status":"writing manifest"}
{"status":"success"}

四、从 Safetensors 目录创建模型

        与 GGUF 文件创建模型类似,Safetensors 目录创建模型都需要使用 files 字段,key 和 value 分别为 Safetensors 目录中文件的文件名和相应文件的 SHA256 摘要。同样的在调用该 API 之前需要先将每一个文件生成 Blob 推送到服务器中,这些文件会保存在 cache 当中,在服务器重启之后才会清除。

请求

        在发送请求前需要先为每个文件进行哈希得到它们的 SHA256 摘要,我们用 Python 来实现这一操作,代码如下

import hashlib
import os,re

dir_path = r'E:\ChatAI\DeepSeek-R1-Distill-Qwen-1.5B'

list_files = os.listdir(dir_path)
matched_files = []
for file_name in list_files:
    if re.search(".*\\.json",file_name) or re.search(".*\\.safetensors",file_name):
        matched_files.append(file_name)

try:
    for file_name in matched_files:
        file_path = os.path.join(dir_path,file_name)
        sha256_hash = hashlib.sha256()  # 新的文件要清空一下上一个文件传入的哈希
        # 以二进制模式打开文件
        with open(file_path, "rb") as file:
            # 分块读取文件内容,避免一次性加载大文件到内存中
            for byte_block in iter(lambda: file.read(4096), b""):
                # 更新哈希对象
                sha256_hash.update(byte_block)
            print("%s: %s" %(file_name,sha256_hash.hexdigest()))
except FileNotFoundError:
        print(f"文件 {file_path} 未找到。")
except Exception as e:
        print(f"发生错误: {e}")

curl http://localhost:11434/api/create -d '{
  "model": "deepseek-r1-distill-qwen:1.5b",
  "files": {
    "config.json": "sha256:91e31a6e6cadfab3b37454eed713f0ba04a560feea71117af7c8b36fba685960",
    "generation_config.json": "sha256:7ea7c03a13f41e3343c1427c9286bf69774b766c00be5e991fb759c721b3ba47",
    "tokenizer.json": "sha256:b5abcf735404aaa97acc3307bf24116da134a3a33776a60a099af825d329bf7e",
    "tokenizer_config.json": "sha256:3f955d042956ab3430de2c344b0804ae5300beec17cb70be1cf35c3d3e499c33",
    "model.safetensors": "sha256:58858233513d76b8703e72eed6ce16807b523328188e13329257fb9594462945"
  }
}'

响应

{"status":"converting model"}
{"status":"creating new layer sha256:0dc48895db155013d789b285ec2d9888b73be5dfe8ea5621507ab789d36e0b58"}
{"status":"writing manifest"}
{"status":"success"}

查询 Blob(Binary Large Object)是否存在

端口

HEAD /api/blobs/:digest

            这个 API 接口可以查询服务器上是否存在相应模型的 blob,使用 GGUF 文件和 Safetensors 目录创建模型前可以用该接口查询一下先。

    参数

    • digest:需要查询的 blob 的 SHA256 摘要

    示例

    请求:

    curl -I http://localhost:11434/api/blobs/sha256:4de296cf59ba595f8695084cd4e0215784baa1c6b02ee9fc26a250be08b7b6a3

    响应:

            如果返回 201 则代表查询成功,blob 存在,如果返回 400(可能是 GGUF 文件的 SHA256 摘要和 digest 不一样导致或者是 blob 根本不存在)则代表查询失败。

    推送 Blob 到服务器当中

     端口

    POST /api/blobs/:digest

             这个 API 接口会将一个文件推送到服务器以创建一个 blob。

    参数

    • digest:推送文件预生成的 SHA256 摘要,创建模型和查询 blob 是否存在的时候会以该 SHA256 摘要为准

    示例

    请求:

            在发送请求前我们需要先把 GGUF 文件进行哈希生成 SHA256 的摘要,我们使用下面的 Python 代码来生成

    import hashlib
    
    file_path = r'E:\ChatAI\lmstudio\models\DeepSeek-R1-Distill-Qwen-32B-abliterated\DeepSeek-R1-Distill-Qwen-32B-abliterated-Q4_K_M.gguf'    # 需要修改为你自己 GGUF 文件的位置
    sha256_hash = hashlib.sha256()
    try:
        # 以二进制模式打开文件
        with open(file_path, "rb") as file:
            # 分块读取文件内容,避免一次性加载大文件到内存中
            for byte_block in iter(lambda: file.read(4096), b""):
                # 更新哈希对象
                sha256_hash.update(byte_block)
            print(sha256_hash.hexdigest())
    except FileNotFoundError:
            print(f"文件 {file_path} 未找到。")
    except Exception as e:
            print(f"发生错误: {e}")

             由于文件比较大需要摘要的生成需要一定的时间,生成完成后把 SHA256 摘要复制到 /api/blobs/sha256: 后面

    curl -T model.gguf -X POST http://localhost:11434/api/blobs/sha256:4de296cf59ba595f8695084cd4e0215784baa1c6b02ee9fc26a250be08b7b6a3

    响应:

            如果返回 201 则代表创建成功,如果返回 400(很大可能是 GGUF 文件的 SHA256 摘要和 digest 不一样导致的)则代表创建失败。

            可以看到在 blobs 目录下已经有该模型的 blob 了

    <think>好的,我现在需要解决用户在使用Ollama API调用本地模型时,模型不返回中间思考步骤的问题。用户希望得到解决方案,让API在回答问题时能展示模型的思考过程。首先,我需要理解Ollama API的工作原理以及可能的配置选项。 根据用户提供的引用资料,尤其是引用[1]提到Ollama提供了REST API,允许开发者通过HTTP请求与模型交互。引用[3]提到Ollama支持自定义模型参数和行为,这可能涉及到API请求时的参数设置。而用户的问题可能出在默认情况下,Ollama API只返回最终结果,没有中间步骤,这可能与模型的输出设置或API参数有关。 接下来,我需要考虑生成式模型通常有两种输出模式:一种是直接输出最终结果,另一种是流式传输(streaming),逐块返回内容。可能用户当前使用的是非流式请求,导致一次性获取全部结果,而中间步骤没有被分离出来。例如,在流式传输中,每个生成的token或段落可以实时返回,这可能包含中间思考过程。 然后,查看OllamaAPI文档,确认是否有相关参数控制输出格式。例如,是否有“stream”选项,或者是否可以通过设置“options”中的参数来调整生成过程的可视化程度。例如,在API请求中设置“stream: true”可能允许逐步接收响应,从而捕捉中间步骤。 此外,引用[3]提到Ollama允许通过Modelfile自定义模型参数,可能需要在模型配置中启用详细输出或中间步骤的记录。例如,设置温度参数(temperature)或最大token数(num_ctx)可能影响生成内容的详细程度,但需要具体分析。 可能的解决方案步骤包括: 1. 检查API请求是否启用了流式传输,使用stream参数为true。 2. 在模型调用时设置参数,如verbose模式,让模型输出更多中间信息。 3. 修改Modelfile,自定义模型生成行为,确保中间步骤被包含在输出中。 4. 处理API的流式响应,将接收到的每个块拼接成完整的思考过程。 需要验证这些方法的可行性。例如,在Python使用requests库发起流式请求,逐行读取响应内容,可能得到逐步生成的文本,其中包含中间推理步骤。另外,查看Ollama的日志或调试信息,确认模型是否实际上生成了中间步骤但未被API返回,或者模型本身在生成时没有这些步骤。 可能的代码示例:使用流式请求处理中间输出,并设置适当的参数如temperature或top_p来增加输出的多样性,从而可能促使模型展示更多思考过程。 需要确保用户了解如何修改API调用方式,并正确处理流式数据。同时,提醒用户某些模型可能默认不生成中间步骤,需要调整提示词(prompt)来明确要求逐步思考,例如在提问时加入“请逐步解释你的思考过程”这样的指令。 总结可能的解决方案:调整API请求参数启用流式传输,结合模型配置或提示词优化,确保中间步骤被生成并捕获。</think>以下是针对Ollama API调用本地模型时不返回中间思考步骤的解决方案: --- ### 解决方案分步说明 #### 1. 启用流式传输模式 Ollama API支持流式传输(Streaming),通过设置`stream: true`参数逐块获取生成内容,可捕捉中间思考步骤。 **Python示例代码**: ```python import requests response = requests.post( 'http://localhost:11434/api/generate', json={ 'model': 'llama2', 'prompt': '请逐步解释量子力学的基本原理', 'stream': True # 启用流式传输 }, stream=True ) for line in response.iter_lines(): if line: data = json.loads(line.decode('utf-8')) print(data["response"], end='', flush=True) # 实时输出中间步骤 ``` #### 2. 优化提示词设计 在提问时明确要求模型展示思考过程,例如添加指令性语句。 **示例提示词**: ``` 请分步骤解释以下问题:{{问题内容}}。要求:先分析关键概念,再推导逻辑关系,最后总结结论。 ``` #### 3. 调整模型参数 通过API的`options`字段控制生成行为,增加输出详细度: - `temperature`(值越高输出越随机) - `num_ctx`(上下文窗口大小) **带参数的请求示例**: ```json { "model": "llama2", "prompt": "问题内容", "stream": true, "options": { "temperature": 0.7, "num_ctx": 4096 } } ``` #### 4. 使用Modelfile自定义模型行为 创建自定义模型配置文件(`Modelfile`),强制模型返回中间步骤。 **Modelfile示例**: ``` FROM llama2 PARAMETER temperature 0.8 SYSTEM 你需要在回答时详细展示推理过程,包括中间假设和逻辑推导步骤。 ``` 构建并运行自定义模型: ```bash ollama create mymodel -f ./Modelfile ollama run mymodel ``` #### 5. 解析流式响应数据 处理流式响应时,需实时拼接中间结果。以下为完整处理逻辑: ```python import json import requests def get_streaming_response(prompt): try: response = requests.post( 'http://localhost:11434/api/generate', json={ 'model': 'llama2', 'prompt': prompt, 'stream': True }, stream=True, timeout=60 ) full_response = [] for chunk in response.iter_content(chunk_size=None): if chunk: data = json.loads(chunk.decode('utf-8')) if 'response' in data: print(data['response'], end='', flush=True) full_response.append(data['response']) return ''.join(full_response) except Exception as e: print(f"API请求失败: {str(e)}") ``` --- ### 技术原理说明 1. **流式传输机制**:Ollama的流式API基于HTTP chunked encoding实现,每个数据块包含部分生成内容,通过实时输出可观察模型推理路径[^1][^3]。 2. **温度参数影响**:`temperature=0.7`时,模型在保持合理性的前提下会增加输出多样性,更易展现思考步骤[^3][^4]。 3. **提示词工程**:明确的指令可激活模型的元认知能力,促使其结构化输出内容,这与LLM的指令遵循特性直接相关[^5]。 ---
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    JoveZou

    你的鼓励将是我创作的最大动力

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值