zeerd's blog         Search     Categories     Tags     Feed

闲来添雅趣,无事自逍遥。对窗静望雪,一盏茶香绕。

Ollama 的结构化输出

#Ollama @AI


Contents:

官方提供了通过 BaseModel 规范输出格式的例子。

但是,实际使用的情况下,很多时候提示词都是从模板中读取出来的,输出格式也不是限定的,需要根据实际情况动态生成。而无法预先通过BaseModel为每种情况创建子类。

下面,给出了一个借助Genson动态生成JSON Schema的例子,用于辅助Ollama进行输出内容的规范化。

# pip install ollama genson

import json
import os
from ollama import Client
from genson import SchemaBuilder

# 提供一个回答问题的格式模板
# 这里的值(即例子中的0、""和False)并本身不重要,重要的是他们表达了自己的类型
json_data = {
    "Summary": "",
    "Points": [
        {
            "Percent": 0,
            "Abstract": "",
            "Key": False
        }
    ]
}

# 使用 Genson 库生成 JSON Schema
# 这将生成一个标准的 JSON Schema ,描述了 json_data 的结构
builder = SchemaBuilder()
builder.add_object(json_data)
fmt = builder.to_schema()

client = Client(host='http://localhost:11434')
# 简单起见,直接读取本脚本自身作为提示词的一部分
with open(os.path.abspath(__file__), 'rb') as f:
    content = f.read().decode('utf-8')

# 调用 ollama 接口提问
response = client.chat(
    model='qwen3:32b',
    messages=[
        {
            'role': 'user',
            'content': (
                "请对下面代码进行审查。\n"
                "首先,使用一句话,总结一下全文(Summary)。\n"
                "然后,概括出最多不超过3条的摘要(Abstract),并逐一列出它们。"
                "说明每个摘要占用篇幅的百分比(Percent)及是否为关键点(Key)。\n"
                f"---\n{content}\n---\n"
            )
        },
    ],
    format=fmt,
)

# 输出反馈的答案,验证答案的格式是否与前文的“json_data”期望的一致
response_json = json.loads(response.message.content)
print(json.dumps(response_json, ensure_ascii=False, indent=4))

输出如下:

{
    "Summary": "该代码使用 Ollama 和 Genson 库来审查代码,生成一个包含总结和摘要的 JSON 格式反馈,其中摘要部分包括百分比和关键点标志。",
    "Points": [
        {
            "Percent": 10,
            "Abstract": "导入了必要的库,如 json、os、ollama 和 genson,并定义了一个 JSON 数据模板。",
            "Key": true
        },
        {
            "Percent": 30,
            "Abstract": "使用 Genson 库生成 JSON Schema,以描述 json_data 的结构。",
            "Key": true
        },
        {
            "Percent": 60,
            "Abstract": "通过 Ollama 接口调用模型进行代码审查,传递提示词和格式要求,并输出验证结果。",
            "Key": true
        }
    ]
}

如果使用的是OpenAI的接口,则需要将format=fmt替换成:

response_format={
    'type': 'json_schema',
    'json_schema':
    {
        "schema": fmt
    }
}