返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

Ollama 0.5.1重磅更新:支持结构化输出,让 AI 回复更精准

[复制链接]
链载Ai 显示全部楼层 发表于 昨天 12:04 |阅读模式 打印 上一主题 下一主题

最新消息!开源 AI 工具 Ollama 新增了结构化输出支持。这意味着我们可以使用预定义的格式来约束 AI 的输出,让回复更加精确和可控。让我们通过一些实际的代码示例来看看这个强大的新功能。

直接从数据中提取结构化的内容并分析

使用 Ollama 进行数据提取非常简单。下面是一个提取宠物信息的示例:


这里使用国产最强开源模型qwen2.5

Qwen2.5是阿里巴巴通义千问团队于2024年9月发布的最新开源大语言模型系列,涵盖从0.5B到72B参数规模的模型,包括基础版本和指令微调版本。


/**
*数据提取测试
*演示如何从自然语言文本中提取结构化数据
*/import{Ollama}from"ollama";import{z}from"zod";import{zodToJsonSchema}from"zod-to-json-schema";constconfig={baseUrl:"http://192.168.1.180:8000",model:"qwen2.5:14b",
};//定义宠物信息的数据结构constPet=z.object({name:z.string().describe("宠物名字"),animal:z.string().describe("动物类型"),age:z.number().describe("年龄"),color:z.string().nullable().describe("毛色"),favorite_toy:z.string().nullable().describe("最喜欢的玩具"),
});//定义宠物列表的数据结构constPetList=z.object({pets:z.array(Pet).describe("宠物列表"),
});asyncfunctionextractPetsInfo(){constollama=newOllama({host:config.baseUrl,
});try{console.log("\n===宠物信息提取测试===");constresponse=awaitollama.chat({model:config.model,messages:[
{role:"user",content:`
我家有三只宠物。
一只叫小白的猫咪,今年3岁,是白色的,最喜欢玩逗猫棒。
还有一只2岁的橘猫叫胖虎,特别喜欢玩毛线球。
最后是一只叫旺财的狗,5岁了,是棕色的,最喜欢玩飞盘。
`,
},
],format:zodToJsonSchema(PetList),
});//解析返回的数据constpetInfo=PetList.parse(JSON.parse(response.message.content));//打印原始JSON数据console.log("\n提取的原始数据:");console.log(JSON.stringify(petInfo,null,2));//格式化输出每只宠物的信息console.log("\n===宠物信息汇总===");
petInfo.pets.forEach((pet,index)=>{console.log(`\n${index+1}.${pet.name}:`);console.log(`-类型{pet.animal}`);console.log(`-年龄{pet.age}岁`);console.log(`-毛色{pet.color||"未知"}`);console.log(`-最爱玩具{pet.favorite_toy||"未知"}`);
});//统计信息console.log("\n===统计信息===");constanimalCount=petInfo.pets.reduce((acc,pet)=>{
acc[pet.animal]=(acc[pet.animal]||0)+1;returnacc;
},{});console.log("宠物类型统计:");Object.entries(animalCount).forEach(([animal,count])=>{console.log(`-${animal}{count}只`);
});constavgAge=
petInfo.pets.reduce((sum,pet)=>sum+pet.age,0)/petInfo.pets.length;console.log(`平均年龄{avgAge.toFixed(1)}岁`);
}catch(error){console.error("数据提取失败:",error.message);if(error.response){console.error("API响应:",error.response);
}
}
}

提取结果如下图所示:

图片分析能力

Ollama 还支持图片内容分析,可以返回结构化的图片描述

这里使用 Llama 3.2-Vision作为图片识别模型

Llama 3.2-Vision是Meta公司于2024年9月发布的多模态大语言模型,具备处理文本和图像的能力。该模型提供11B和90B两个版本,支持128,000个tokens的上下文长度。在文本处理方面,Llama 3.2-Vision支持多种语言,包括英语、德语、法语、意大利语、葡萄牙语、印地语、西班牙语和泰语。然而,在图像与文本结合的应用中,目前仅支持英语。


先上图

再上代码

/**
*图片内容分析测试
*演示如何使用AI模型分析图片并返回结构化数据
*/import{Ollama}from"ollama";import{z}from"zod";import{zodToJsonSchema}from"zod-to-json-schema";importfsfrom"fs/promises";constconfig={baseUrl:"http://192.168.1.180:8000",model:"llama3.2-vision",
};//定义物体信息的数据结构constObject=z.object({name:z.string().describe("物体名称"),confidence:z.number().min(0).max(1).describe("置信度"),attributes:z.string().describe("物体属性描述"),
});//定义图片描述的数据结构constImageDescription=z.object({summary:z.string().describe("图片整体描述"),objects:z.array(Object).describe("检测到的物体列表"),scene:z.string().describe("场景描述"),colors:z.array(z.string()).describe("主要颜色列表"),time_of_day:z
.enum(["Morning","Afternoon","Evening","Night"])
.describe("拍摄时间"),setting:z.enum(["Indoor","Outdoor","Unknown"]).describe("环境设置"),text_content:z.string().nullable().describe("图片中的��字内容"),
});asyncfunctionanalyzeImage(imagePath){constollama=newOllama({host:config.baseUrl,
});try{//读取图片文件constimageBuffer=awaitfs.readFile(imagePath);constbase64Image=imageBuffer.toString("base64");console.log("\n===图片内容分析测试===");constresponse=awaitollama.chat({model:config.model,messages:[
{role:"user",content:"请分析这张图片,描述你看到的内容,包括物体、场景、颜色和任何可以检测到的文字。",images:[base64Image],
},
],format:zodToJsonSchema(ImageDescription),options:{temperature:0,//设置为0以获得更确定性的输出},
});//解析返回的数据constimageInfo=ImageDescription.parse(JSON.parse(response.message.content)
);//打印原始JSON数据console.log("\n===原始JSON数据===");console.log(JSON.stringify(imageInfo,null,2));//打印格式化的分析结果console.log("\n===格式化分析结果===");console.log("\n【整体描述】");console.log(imageInfo.summary);console.log("\n【场景信息】");console.log(`场景类型{imageInfo.scene}`);console.log(`环境设置{getChineseSettingName(imageInfo.setting)}`);console.log(`拍摄时间{getChineseTimeName(imageInfo.time_of_day)}`);console.log("\n【检测到的物体】");
imageInfo.objects.forEach((obj,index)=>{console.log(`\n${index+1}.${obj.name}`);console.log(`置信度{(obj.confidence*100).toFixed(1)}%`);console.log(`属性:${obj.attributes}`);
});console.log("\n【主要颜色】");
imageInfo.colors.forEach((color)=>console.log(`-${color}`));if(imageInfo.text_content){console.log("\n【检测到的文字】");console.log(imageInfo.text_content);
}
}catch(error){console.error("图片分析失败:",error.message);if(error.response){console.error("API响应:",error.response);
}
}
}//环境设置的中文映射functiongetChineseSettingName(setting){constsettingMap={Indoor:"室内",Outdoor:"室外",Unknown:"未知",
};returnsettingMap[setting]||setting;
}//时间段的中文映射functiongetChineseTimeName(time){consttimeMap={Morning:"早晨",Afternoon:"下午",Evening:"傍晚",Night:"夜晚",
};returntimeMap[time]||time;
}//使用示例constimagePath="/Users/SCR-20241019-marq.png";analyzeImage(imagePath).catch(console.error);

返回结果如下图:

简历信息提取

结构化输出在处理文档信息时也很有用:

constResume=z.object({basicInfo:z.object({name:z.string().describe("姓名"),age:z.number().describe("年龄"),email:z.string().email().describe("电子邮箱"),phone:z.string().describe("电话号码")
}),education:z.array(z.object({school:z.string(),degree:z.string(),major:z.string(),period:z.object({start:z.string(),end:z.string()
})
})),workExperience:z.array(z.object({company:z.string(),position:z.string(),period:z.object({start:z.string(),end:z.string()
}),responsibilities:z.array(z.string()),achievements:z.array(z.string())
}))
});

实用技巧

  • 使用 Zod 来定义清晰的数据结构
  • 为每个字段添加描述,帮助模型理解
  • 设置 temperature 为 0,使输出更稳定
  • 合理使用可空字段(nullable)增加灵活性

应用场景

  • 自动化数据提取和整理
  • 智能文档解析
  • 图片内容分析
  • 结构化知识提取
  • API 响应格式化


扩展阅读:Zod 使用详解

1. 基础类型定义

import{z}from"zod";//基础类型conststringSchema=z.string();constnumberSchema=z.number();constbooleanSchema=z.boolean();constnullSchema=z.null();//可选和可空constoptionalString=z.string().optional();//string|undefinedconstnullableString=z.string().nullable();//string|null

2. 复杂对象定义

//对象定义constUserSchema=z.object({id:z.number(),name:z.string().min(2),email:z.string().email(),age:z.number().min(0).max(120),role:z.enum(["admin","user","guest"]),tags:z.array(z.string())
});//嵌套对象constPostSchema=z.object({title:z.string(),content:z.string(),author:UserSchema,comments:z.array(z.object({text:z.string(),user:UserSchema
}))
});

3. 类型转换和验证

//添加自定义验证constPhoneSchema=z.string().refine((val)=>/^1[3-9]\d{9}$/.test(val),"请输入有效的手机号");//类型转换constNumberFromString=z.string().transform((val)=>parseInt(val));//默认值constConfigSchema=z.object({port:z.number().default(3000),host:z.string().default("localhost")
});

4. 继承和合并

//基础配置constBaseConfig=z.object({version:z.string(),name:z.string()
});//扩展配置constFullConfig=BaseConfig.extend({description:z.string(),isEnabled:z.boolean()
});//合并多个SchemaconstMergedSchema=z.intersection(SchemaA,SchemaB);

5. 实战应用技巧

  • 添加字段描述
constProductSchema=z.object({name:z.string().describe("产品名称"),price:z.number().describe("产品价格(元)"),stock:z.number().describe("库存数量"),category:z.enum(["电子","服装","食品"]).describe("产品类别")
});
  • 错误处理
try{constresult=ProductSchema.parse(data);
}catch(error){if(errorinstanceofz.ZodError){
error.errors.forEach(err=>{console.log(`${err.path.join('.')}:${err.message}`);
});
}
}
  • 异步验证
constAsyncSchema=z.object({username:z.string().refine(async(val)=>{//检查用户名是否可用constexists=awaitcheckUserExists(val);return!exists;
},"用户名已存在"
)
});

6. 最佳实践

  • 类型复用
//定义可复用的类型constDateRangeSchema=z.object({start:z.string(),end:z.string()
});//在其他Schema中复用constEventSchema=z.object({title:z.string(),periodateRangeSchema,location:z.string()
});
  • 性能优化
//预编译SchemaconstcompiledSchema=z.object({/*...*/}).compile();//重复使用已编译的SchemafunctionvalidateData(data){returncompiledSchema.safeParse(data);

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

链载AI是专业的生成式人工智能教程平台。提供Stable Diffusion、Midjourney AI绘画教程,Suno AI音乐生成指南,以及Runway、Pika等AI视频制作与动画生成实战案例。从提示词编写到参数调整,手把手助您从入门到精通。
  • 官方手机版

  • 微信公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2025-2025. | 链载Ai
  • 桂ICP备2024021734号 | 营业执照 | |广西笔趣文化传媒有限公司|| QQ