结构化输出一直是AI应用开发中一个很麻烦的问题,业内也有很多实践方法来解决问题,OpenAI在之前的更新中也专门针对这一问题进行优化。
延伸阅读:
Instructor:58种Prompt技术让 LLM输出更加结构化和可控
OpenAI发布小更新!100%解决LLM应用开发Json结构化输出不稳定问题
Outlines:让LLM结构化输出可控,提升LLM应用的稳定性
Ollama 近日就此问题推出重要更新(0.5.0+),引入与OpenAI一样的结构化输出(Structured Outputs)功能,让开发者能够通过 JSON schema 精确定义和约束模型输出格式。该功能已在 Ollama 的 Python 和 JavaScript 库中得到全面支持。
本次更新的核心亮点包括:
-
基于 JSON schema 的输出格式控制 -
支持多种数据解析场景,包括文档解析和图像分析 -
相比传统 JSON 模式,提供更可靠和一致的输出 -
提供 OpenAI 兼容性支持
在技术实现层面,开发者可以通过多种方式使用该功能:
-
REST API:使用 cURL 请求中的 format
参数 -
Python:通过 Pydantic 进行模式定义 -
JavaScript:利用 Zod 进行架构序列化
下面是python的示例:
from ollama import chat
from pydantic import BaseModel
class Country(BaseModel):
name: str
capital: str
languages: list[str]
response = chat(
messages=[
{
'role': 'user',
'content': 'Tell me about Canada.',
}
],
model='llama3.1',
format=Country.model_json_schema(),
)
country = Country.model_validate_json(response.message.content)
print(country)
输出:
name='Canada' capital='Ottawa' languages=['English', 'French']
除了常规的输出格式限制外,数据提取也是一个常见的结构化输出应用场景,开发者可以精确定义需要提取的字段和格式,从文档或图像中提取结构化数据。
比如:在一段自然语言文本中提取有效的结构化内容:
from ollama import chat
from pydantic import BaseModel
class Pet(BaseModel):
name: str
animal: str
age: int
color: str | None
favorite_toy: str | None
class PetList(BaseModel):
pets: list[Pet]
response = chat(
messages=[
{
'role': 'user',
'content': '''
I have two pets.
A cat named Luna who is 5 years old and loves playing with yarn. She has grey fur.
I also have a 2 year old black cat named Loki who loves tennis balls.
''',
}
],
model='llama3.1',
format=PetList.model_json_schema(),
)
pets = PetList.model_validate_json(response.message.content)
print(pets)
输出:
pets=[
Pet(name='Luna', animal='cat', age=5, color='grey', favorite_toy='yarn'),
Pet(name='Loki', animal='cat', age=2, color='black', favorite_toy='tennis balls')
]
对于图片内容提取一样可以:
from ollama import chat
from pydantic import BaseModel
class Object(BaseModel):
name: str
confidence: float
attributes: str
class ImageDescription(BaseModel):
summary: str
objects: List[Object]
scene: str
colors: List[str]
time_of_day: Literal['Morning', 'Afternoon', 'Evening', 'Night']
setting: Literal['Indoor', 'Outdoor', 'Unknown']
text_content: Optional[str] = None
path = 'path/to/image.jpg'
response = chat(
model='llama3.2-vision',
format=ImageDescription.model_json_schema(), # Pass in the schema for the response
messages=[
{
'role': 'user',
'content': 'Analyze this image and describe what you see, including any objects, the scene, colors and any text you can detect.',
'images': [path],
},
],
options={'temperature': 0}, # Set temperature to 0 for more deterministic output
)
image_description = ImageDescription.model_validate_json(response.message.content)
print(image_description)
输出:
summary='A palm tree on a sandy beach with blue water and sky.'
objects=[
Object(name='tree', confidence=0.9, attributes='palm tree'),
Object(name='beach', confidence=1.0, attributes='sand')
],
scene='beach',
colors=['blue', 'green', 'white'],
time_of_day='Afternoon'
setting='Outdoor'
text_content=None
官方同时指出,该接口完全和OpenAI风格兼容,使用了OpenAI结构化输出功能的开发者来讲,可以无缝迁移到利用Ollama托管的推理接口上来。同时,官方给出了以下tips可以实践:
-
使用 Pydantic 或 Zod 定义响应模式 -
在提示中明确要求 JSON 格式输出 -
将温度参数设为 0 以获得更稳定的输出
还透露了下一步优化计划,包括:
-
引入 logits 控制生成过程 -
提升结构化输出的性能和准确性 -
支持 GPU 加速采样 -
扩展更多格式支持
小结
Ollama官方原生解决这一问题,通过严格的输出控制,会使得应用获得更强鲁棒性,进而进一步提升用户体验。Ollama的快速发展得益于他们对开发者在实际开发过程中的实际痛点的精准把握,让更多的开发者感受到易用和便捷。docker作为Cloud Native的基石存在,原班人马出走打造的Ollama也或将引领AI Native时代到来。
(文:AI工程化)