Flutter AI:将Google Gemini API集成到Flutter中
前提条件
检查可用区域
先检查Gemini API可用区域,并准备对应的VPN。注意区域后方[1]代表Gemini API 的免费层级未在此区域推出
。
申请API KEY
访问Google AI Studio点击左上角Get API Key
这里我使用是免费计划,速率限制如下
15 RPM(每分钟请求数)
100 万个 TPM(每分钟令牌数)
1500 RPD(每日请求数)
不适用上下文缓存
基础使用
引用插件
导入插件google_generative_ai,并引入头文件
google_generative_ai: ^0.4.3
import 'package:google_generative_ai/google_generative_ai.dart';
根据纯文本输入生成文本
var model = GenerativeModel(model: 'gemini-1.5-flash', apiKey: 'APIKEY');
final content = [Content.text('写一个睡前故事')];
final response = await model.generateContent(content);
print(response.text);
/*
在一片宁静的森林深处,住着一个小小的萤火虫,名叫露西。露西非常喜欢夜晚,因为那时她可以闪着自己小小的灯,照亮周围的黑暗。
有一天晚上,露西在草丛中飞舞,看到一只迷路的小兔子,它惊慌失措地哭着,因为它找不到回家的路。露西飞到小兔子身边,用自己微弱的光亮照亮了周围的树木,让小兔子能看清楚路。
“别害怕,”露西说,“我会帮助你找到回家的路。”
露西带着小兔子飞过草丛,穿过树林,最后来到了一片开满鲜花的草地上。小兔子看到了自己的家,高兴地跳了起来。
“谢谢你,露西!”小兔子说,“你真是个善良的小萤火虫!”
露西微笑着说:“不用谢,帮助别人是我最开心的事情。”
小兔子回家后,露西继续在森林里飞舞,她闪着自己小小的灯,照亮了黑夜,也照亮了所有需要帮助的人。
这个晚上,森林里充满了温暖和光明。露西知道,只要她继续闪亮,就能给所有迷路的人带来希望和勇气。
露西回到了自己的草丛,闭上眼睛,进入了甜蜜的梦乡。她梦见了美丽的森林,梦见了快乐的小动物,也梦见了所有她帮助过的人。
露西,这个小小的萤火虫,用自己的微弱光亮照亮了整个夜晚,也照亮了所有需要帮助的人的心。
晚安,小宝贝们,也愿你们做个好梦。
*/
据文本和图片输入生成文本
var model = GenerativeModel(model: 'gemini-1.5-flash', apiKey: 'APIKEY');
final (firstImage, secondImage) = await (
rootBundle.load('assets/image0.png'),
rootBundle.load('assets/image1.png')
).wait;
final prompt = TextPart("这两种图片有什么不同?");
final imageParts = [
DataPart('image/png', firstImage.buffer.asUint8List()),
DataPart('image/png', secondImage.buffer.asUint8List()),
];
final response = await model.generateContent([
Content.multi([prompt, ...imageParts])
]);
print(response.text);
//输出:第一张图片中没有鱼,第二张图片中有一条黄色的鱼在湖里。
这里表现的差点意思,没有找出所有差别
建立多轮对话
借助 Gemini,可以跨多个回合构建自由形式的对话。该 SDK 通过管理对话状态来简化该过程,无需自行存储对话历史记录。
通过调用 startChat()
初始化对话。然后,使用 sendMessage()
发送一条新的用户消息,此消息也会将此消息和响应附加到聊天记录。
与对话内容相关联的 role
有两种可能的选项:
user
:提供提示的角色。此值是sendMessage
调用的默认值,如果传递了其他角色,函数将抛出异常。model
:提供响应的角色。使用现有的history
调用startChat()
时,可以使用此角色。
final model = GenerativeModel(
model: 'gemini-1.5-flash',
apiKey: 'APIKEY',
generationConfig: GenerationConfig(maxOutputTokens: 100));
final chat = model.startChat(history: [
Content.text('你好,我的房子里有两只狗'),
Content.model([TextPart('很高兴见到你。你想知道什么?')])
]);
var content = Content.text('我的房子里有几只爪子?');
var response = await chat.sendMessage(content);
print(response.text);
//输出:每只狗有四只爪子,所以两只狗就有八只爪子。
使用流式传输加快互动速度
默认情况下,模型会在完成整个生成过程后返回响应。通过不等待整个结果,可以实现更快的互动,使用流式传输来处理部分结果。
final model = GenerativeModel(model: 'gemini-1.5-flash', apiKey: 'APIKEY');
final (firstImage, secondImage) = await (
rootBundle.load('assets/image0.png'),
rootBundle.load('assets/image1.png')
).wait;
final prompt = TextPart("这两种图片有什么不同?");
final imageParts = [
DataPart('image/png', firstImage.buffer.asUint8List()),
DataPart('image/png', secondImage.buffer.asUint8List()),
];
final response = model.generateContentStream([
Content.multi([prompt, ...imageParts])
]);
await for (final chunk in response) {
print(chunk.text);
}
//flutter: 第一
//flutter: 张图片里,湖里没有鱼。
//flutter: 第二张图片里,湖里
//flutter: 有一条黄色的鱼。
进阶用法
进阶用法没有实际尝试,以下代码来自官方文档
调用函数
函数调用可让您更轻松地从生成模型获取结构化数据输出。然后,您可以使用这些输出来调用其他 API,并将相关响应数据返回给模型。换句话说,函数调用可帮助您将生成模型连接到外部系统,以便生成的内容包含最新且准确的信息。如需了解详情,请参阅函数调用教程。
使用嵌入
嵌入是一种用于将信息表示为数组中的浮点数列表的技术。借助 Gemini,您能够以矢量化形式表示文本(字词、句子和文本块),从而更轻松地比较和对比嵌入。例如,主题或情感相似的两个文本应该具有相似的嵌入,这些嵌入可以通过余弦相似度等数学比较技术来识别。
结合使用 embedding-001
模型和 embedContent
方法(或 batchEmbedContent
方法)生成嵌入。以下示例为单个字符串生成嵌入:
final model = GenerativeModel(model: 'embedding-001', apiKey: apiKey);
final content = Content.text('The quick brown fox jumps over the lazy dog.');
final result = await model.embedContent(content);
print(result.embedding.values);
计算词元数量
使用长提示时,在向模型发送任何内容之前统计词元数量可能会很有用。以下示例展示了如何针对各种用例使用 countTokens()
:
// For text-only input
final tokenCount = await model.countTokens(Content.text(prompt));
print('Token count: ${tokenCount.totalTokens}');
// For text-and-image input (multimodal)
final tokenCount = await model.countTokens([
Content.multi([prompt, ...imageParts])
]);
print('Token count: ${tokenCount.totalTokens}');
// For multi-turn conversations (like chat)
final prompt = Content.text(message);
final allContent = [...chat.history, prompt];
final tokenCount = await model.countTokens(allContent);
print('Token count: ${tokenCount.totalTokens}');
用于控制内容生成的选项
您可以通过配置模型参数和使用安全设置来控制内容生成。
请注意,将 generationConfig
或 safetySettings
传递给模型请求方法(如 generateContent
)将完全替换与 getGenerativeModel
中传递的相同名称的配置对象。
配置模型参数
您发送到模型的每个提示都包含参数值,用于控制模型如何生成回答。对于不同的参数值,模型会生成不同的结果。详细了解模型参数。此配置在模型实例的生命周期内保持不变。
final generationConfig = GenerationConfig(
stopSequences: ["red"],
maxOutputTokens: 200,
temperature: 0.9,
topP: 0.1,
topK: 16,
);
final model = GenerativeModel(
// The Gemini 1.5 models are versatile and work with most use cases
model: 'gemini-1.5-flash',
apiKey: apiKey,
generationConfig: generationConfig,
);
使用安全设置
您可以使用安全设置来调整获得可能被视为有害响应的可能性。默认情况下,安全设置会在所有维度上屏蔽不安全内容的中等和/或高概率。详细了解安全设置。
设置一项安全设置的方法如下:
final safetySettings = [
SafetySetting(HarmCategory.harassment, HarmBlockThreshold.high)
];
final model = GenerativeModel(
// The Gemini 1.5 models are versatile and work with most use cases
model: 'gemini-1.5-flash',
apiKey: apiKey,
safetySettings: safetySettings,
);
还可以设定多项安全设置:
final safetySettings = [
SafetySetting(HarmCategory.harassment, HarmBlockThreshold.high),
SafetySetting(HarmCategory.hateSpeech, HarmBlockThreshold.high),
];
常见报错
Unhandled Exception: Instance of 'UnsupportedUserLocation'
Geimni API不支持该区域。检查可用区域,使用可用区域的VPN。
User location is not supported for the API use without a billing account linked.
Geimni API在该区域不支持免费计划,有两种解决方案。
如果要使用免费计划,参照文章开头提到的,选择可用区域中后面没有[1]的。
不需要免费计划的话,去Google控制台点击结算,添加付款信息。这里可能也有很多问题,不支持大陆信用卡、找到了可用信用卡保存的时候报错OR_BACR2_34,本文不讨论这个问题。
- 0
- 0
-
赞助
微信支付宝 -
分享