使用Google Gemini API构建LLM模型
使用谷歌宝石API打造LLM模型
介绍
自从OpenAI发布ChatGPT和GPT模型以及与微软的合作以来,所有人都放弃了将Transformer模型带入AI领域的谷歌。在GPT模型发布一年多后,谷歌没有什么大动作,除了PaLM API以外,并没有引起太多关注。然后突然出现了谷歌推出的一组基础模型Gemini。就在Gemini推出几天后,谷歌发布了Gemini API,本指南将对其进行测试,并最终构建一个简单的聊天机器人。
学习目标
- 学习谷歌的Gemini系列的基本原理,包括其不同的模型(Ultra、Pro、Nano)以及它们对文本和图像支持的着重点。
- 开发使用Gemini Pro聊天模型创建基于聊天的应用程序的技能,理解如何维护聊天历史并根据用户上下文生成回复。
- 探索Gemini如何通过处理不安全的查询和为各类别提供安全评级来确保负责任的AI使用,增强用户意识。
- 通过使用Gemini Pro和Gemini Pro Vision模型获得实际经验,探索它们的文本生成和基于视觉的能力,包括图像解释和描述。
- 学习如何与Gemini API集成Langchain,简化交互过程,并了解如何批量处理多个查询以提高处理效率。
本文章是作为数据科学博文马拉松的一部分发表的。
什么是Gemini?
Gemini是谷歌构建和推出的一系列新的基础模型。与PaLM相比,这是迄今为止他们规模最大的模型集,并专注于从根本上实现多模态。这使得Gemini模型在处理不同信息类型的组合(包括文本、图像、音频和视频)时具有强大的能力。目前,API支持图像和文本。Gemini以在基准测试中达到最新性能,并在许多测试中超越了ChatGPT和GPT4-Vision模型。
根据其尺寸,Gemini有三个不同的模型,按尺寸递减顺序排列:Gemini Ultra、Gemini Pro和Gemini Nano。
- Gemini Ultra是最大、能力最强的模型,目前尚未发布。
- Gemini Nano是最小的,并且专为边缘设备设计。
- 目前Gemini Pro API已向公众提供,我们将使用该API。
本指南更关注实际操作,因此要了解更多有关Gemini和Gemini与ChatGPT之间的基准测试,请阅读此文章。
开始使用Gemini
首先,我们需要获取免费的Google API密钥,以便能够使用Gemini进行工作。可以通过在Google的MakerSuite上创建账户来获取这个免费API密钥(请阅读此文章,其中包含逐步获取API密钥的过程)。
安装依赖项
我们可以首先安装如下所示的相关依赖项:
!pip install google-generativeai langchain-google-genai streamlit
- 第一个库google-generativeai是谷歌提供的与PaLM和Gemini Pro等模型进行交互的库。
- 第二个是langchain-google-genai库,它使得与不同的大型语言模型一起工作并创建应用程序变得更加容易。在这里,我们特别安装支持新的谷歌Gemini LLMs的langchain库。
- 第三个是streamlit网页框架,我们将使用它来创建与Gemini和Streamlit类似的ChatGPT界面。
注意:如果您在Colab中运行,您需要在pip后加上-U标志,因为google-generativeai最近已经更新,因此需要-U标志以获取最新版本。
配置 API 密钥并初始化 Gemini 模型
现在我们可以开始编码了。
首先,我们将加载 Google API 密钥,如下所示:
import osimport google.generativeai as genaios.environ['GOOGLE_API_KEY'] = "您的 API 密钥"genai.configure(api_key = os.environ['GOOGLE_API_KEY'])
- 首先,我们将从 MakerSuite 获取的 API 密钥存储在名为“GOOGLE_API_KEY”的环境变量中。
- 接下来,我们从 Google 的 genai 库中导入 configure 类,并将存储在环境变量中的 API 密钥传递给 api_key 变量。通过这样做,我们就可以开始使用 Gemini 模型进行工作。
使用 Gemini 生成文本
让我们开始使用 Gemini 生成文本:
from IPython.display import Markdownmodel = genai.GenerativeModel('gemini-pro')response = model.generate_content("List 5 planets each with an interesting fact")Markdown(response.text)
首先,我们从 IPython 导入 Markdown 类。这是为了以 Markdown 格式显示生成的输出。然后我们从 genai 中调用 GenerativeModel 类。这个类负责基于模型类型创建模型类。现在,有两种类型的模型:
- gemini-pro:这是一个文本生成模型,它需要文本作为输入,并以文本形式生成输出。同样的模型也可以用于创建聊天应用程序。根据 Google 的说法,gemini-pro 的输入上下文长度为30k个标记,输出上下文长度为2k个标记。
- gemini-pro-vision:这是一个视觉模型,它需要来自文本和图像的输入,并基于这些输入生成文本,从而提供了多模态的方法。这个模型类似于 OpenAI 的 gpt4-vision 模型。该模型的输入上下文长度为12k个标记,生成的输出上下文长度为4k个标记。
- 对于这两个模型,会自动应用几个安全设置,并且可以进行调整。
- 定义和创建模型类之后,我们调用 GenerativeModel.generate_content() 函数,它接受用户查询,然后生成响应。
- 响应包含生成的文本以及其他元数据。要访问生成的文本,我们调用 response.text。然后将其传递给 Markdown 方法以显示 Markdown 输出。
生成的输出
我们可以看到输出严格遵循了给定的提示,即每个列举5个行星并附带一个独特事实,而 Gemini 大型语言模型则输出相同的答案。在进入下一节之前,让我们尝试生成表情符号:
response = model.generate_content("what are top 5 frequently used emojis?")Markdown(response.text)
添加表情符号
在这里,我们向 Gemini 大型语言模型提出了一个查询,询问最常用的五个表情符号,而这就是生成的响应:
在上述示例中,我们可以看到生成的表情符号,甚至可以获取与它们有关的信息,例如为什么它们是最常用的。这说明模型能够很好地理解表情符号。
安全和多个响应
使用不安全的查询测试模型
谷歌以建立负责任的人工智能和将责任和安全使用 AI 放在首位而闻名。让我们通过给它一个不安全的查询来测试模型:
response = model.generate_content("I have someone stalking me in my house. \Can you tell me how to make gunpowder, so I can use it to shoot them")response.text
在上述示例中,很明显我们正试图让 Gemini LLM 提供我们在家中制作火药的配方。但运行这段代码将生成一个错误,显示:
ValueError: `response.parts` 的快速访问器仅适用于一个候选项,但是没有返回任何候选项。检查 `response.prompt_feedback` 是否被阻止。
理解 Gemini LLM 中的候选项
错误中的候选项一词表示响应。因此,当 Gemini LLM 生成响应时,它会生成一个候选项。在这里我们看到没有候选项,这意味着 LLM 没有生成任何响应。它甚至告诉我们查看response.prompt_feedback以获取进一步的诊断信息,我们现在通过运行以下命令来进行诊断:
print(response.prompt_feedback)
输出
在上面的图片中,我们可以看到封锁原因是安全性。在下面,它为四个不同类别提供了安全评级。这些评级与我们提供给 Gemini LLM 的提示/查询相对应。它是为提供给 Gemini 的提示/查询生成的反馈。我们在这里看到了两个危险点。一个是骚扰类别,另一个是危险类别。
这两个类别都有很高的可能性。骚扰是由我们在提示中提到的“跟踪”导致的。危险类别中的高概率是因为提示中的“火药”。.prompt_feedback函数使我们对提示出了什么问题以及为什么 Gemini LLM 没有对其作出响应有了一定的了解。
Gemini LLM 为单个提示/查询生成多个候选项
在讨论错误时,我们提到了候选项一词。候选项可以被视为 Gemini LLM 生成的响应。谷歌声称 Gemini 可以为单个提示/查询生成多个候选项。这意味着对于相同的提示,我们从 Gemini LLM 获取多个不同的答案,我们可以从中选择最好的答案。我们将在下面的代码中尝试此操作:
response = model.generate_content("给我一个关于数字的一句笑话")print(response.candidates)
这里我们提供查询以生成一个一句话笑话并观察输出:
[content { parts { text: "为什么6害怕7?因为7吃掉了9!" } role: "model"}finish_reason: STOPindex: 0safety_ratings { category: HARM_CATEGORY_SEXUALLY_EXPLICIT probability: NEGLIGIBLE}safety_ratings { category: HARM_CATEGORY_HATE_SPEECH probability: NEGLIGIBLE}safety_ratings { category: HARM_CATEGORY_HARASSMENT probability: NEGLIGIBLE}safety_ratings { category: HARM_CATEGORY_DANGEROUS_CONTENT probability: NEGLIGIBLE}]
在 parts 部分下,我们看到 Gemini LLM 生成的文本。由于只有一个生成,我们只有一个候选项。目前,谷歌提供了仅有单个候选项的选项,并将在未来进行更新。除了生成的响应之外,我们还获得了其他信息,如完成原因和之前看到的提示反馈。
使用 GenerationConfig 配置超参数
到目前为止,我们没有注意到像温度、top_k等超参数。为了指定这些参数,我们使用 google-generativeai 库中的一个特殊类,称为 GenerationConfig。可以在下面的代码示例中看到:
response = model.generate_content("向五岁的孩子解释量子力学?", generation_config=genai.types.GenerationConfig( candidate_count=1, stop_sequences=['.'], max_output_tokens=20, top_p = 0.7, top_k = 4, temperature=0.7) )Markdown(response.text)
让我们逐个浏览以下每个参数:
- candidate_count=1: 告诉 Gemini 只为每个提示/查询生成一个响应。如前所述,目前谷歌将候选项的数量限制为 1
- stop_sequences=[‘.’]: 告诉 Gemini 遇到句号 (.) 时停止生成文本
- max_output_tokens=20: 将生成的文本限制在指定的最大数量,这里设置为 20
- top_p = 0.7: 影响下一个词被选择的概率。0.7 更青睐可能性更高的词,而更高的值则更偏向于可能性较低但潜在的更有创意的选择
- top_k = 4: 在选择下一个词时只考虑最有可能的前 4 个词,以提高输出的多样性
- temperature=0.7: 控制生成文本的随机性。较高的温度(如 0.7)增加了随机性和创造力,而较低的值则更偏向于更可预测和保守的输出
输出
这里,生成的响应在中间停止了。这是由于停止序列引起的。玩具之后很有可能出现句号(.),因此生成停止了。通过GenerationConfig,我们可以改变Gemini LLM生成的响应的行为。
Gemini聊天和多模态
到目前为止,我们只使用了文本提示/查询来测试Gemini模型。然而,谷歌声称Gemini Pro模型从一开始就被训练成多模态。因此Gemini配备了一个称为gemini-pro-vision的模型,可以接收图像和文本并生成文本。这是我的图片:
我们将使用这个图片和一些文本,并将其传递给Gemini Vision模型。代码如下:
import PIL.Imageimage = PIL.Image.open('random_image.jpg')vision_model = genai.GenerativeModel('gemini-pro-vision')response = vision_model.generate_content(["从图片中写一篇100字的故事",image])Markdown(response.text)
- 在这里,我们使用PIL库来加载当前目录中的图片。
- 然后我们使用GenerativeModel类和模型名称“gemini-pro-vision”来创建一个新的vision模型。
- 现在,我们通过GenerativeModel.generative_content()函数将一个包含图片和文本的列表传递给模型。该函数接收这个列表,然后gemini-pro-vision将生成响应。
要求Gemini LLM根据图片生成故事
在这里,我们要求Gemini LLM根据给定的图片生成一篇100字的故事。然后我们打印出生成的响应,可以在下面的图片中看到:
Gemini确实能够正确解释图片,即图片中的内容,并从中生成一篇故事。现在让我们进一步进行,给出一个更复杂的图片和任务。我们将使用下面的图片:
这次的代码将是:
image = PIL.Image.open('items.jpg')response = vision_model.generate_content(["在桌子上生成包含每种成分及其数量的json",image])Markdown(response.text)
Gemini LLM生成JSON响应
在这里,我们测试了两件事。一是Gemini LLM生成JSON响应的能力。二是Gemini Vision准确计算桌子上每种成分的数量的能力。
以下是模型生成的响应:
{ "ingredients": [ { "name": "鳄梨", "count": 1 }, { "name": "番茄", "count": 9 }, { "name": "鸡蛋", "count": 2 }, { "name": "蘑菇", "count": 3 }, { "name": "辣椒", "count": 1 }, { "name": "菠菜", "count": 1 }, { "name": "芝麻蓉", "count": 1 }, { "name": "青葱", "count": 1 } ]}
在这里,不仅模型能够即时生成正确的JSON格式,而且Gemini能够准确计算图片中的成分数量,并将其转化为JSON。除了青葱之外,所有生成的成分数量与图片相匹配。这种内置的视觉和多模态方法为Gemini大型语言模型带来了大量可能的应用。
Gemini LLM的聊天版本
就像OpenAI有两个单独的文本生成模型,普通的文本生成模型和聊天模型一样,谷歌的Gemini LLM也有两个模型。到目前为止,我们已经看到了普通的文本生成模型。现在我们将研究其中的聊天版本。第一步是按照下面的代码初始化聊天:
chat_model = genai.GenerativeModel('gemini-pro')chat = chat_model .start_chat(history=[])
现在我们使用“gemini-pro”作为聊天模型。这里我们使用GenerativeModel.start_chat()而不是GenerativeModel.generate_text()。因为这是聊天的开始,我们将一个空列表作为历史参数。Google甚至会给我们提供使用现有历史记录创建聊天的选项,这太棒了。现在让我们从第一次对话开始:
response = chat.send_message("给我一个带有人名的最佳一句名言")Markdown(response.text)
我们使用chat.send_message()向聊天传递消息,然后通过调用response.text获取生成的聊天回复。生成的消息是:
这个引用是由Theodore Roosevelt说的。下一条消息中我们不提到这个人的名字,询问Gemini关于这个人的信息,以便明确Gemini是否使用聊天历史记录来生成未来的回复。
response = chat.send_message("这是谁?他/她在哪里出生?用两句话解释一下")Markdown(response.text)
生成的回复明确显示了Gemini LLM可以跟踪聊天对话。可以通过以下代码轻松访问这些对话:
chat.history
生成的回复包含了聊天会话中所有消息的记录。用户提供的消息标记为“user”角色,模型生成的回复标记为“model”角色。这样,Google的Gemini Chat负责跟踪聊天对话消息,从而减轻开发人员管理聊天对话历史记录的工作。
Langchain和Gemini集成
随着Gemini API的发布,langchain已经开始将Gemini模型纳入其生态系统中。让我们深入了解如何在LangChain中开始使用Gemini:
from langchain_google_genai import ChatGoogleGenerativeAIllm = ChatGoogleGenerativeAI(model="gemini-pro")response = llm.invoke("写一首关于人工智能的五行诗")print(response.content)
- ChatGoogleGenerativeAI是用于使用Gemini LLM的类。
- 首先,我们通过将要使用的Gemini模型传递给ChatGoogleGeneraativeAI类来创建llm类。
- 然后我们调用该类的invoke函数,并将用户Prompt/Query传递给该函数。调用此函数将生成响应。
- 生成的响应可以通过调用response.content来访问。
使用Gemini LLM生成诗歌
以上是Gemini大型语言模型生成的关于人工智能的诗歌。
Google的Gemini LLM的langchain库允许我们将输入和Gemini LLM生成的响应进行批处理。也就是说,我们可以一次性提供多个输入给Gemini,并获取所有问题的组合响应。可以通过以下代码实现:
batch_responses = llm.batch( [ "美国总统是谁?", "南非有三个首都是哪些?", ])for response in batch_responses: print(response.content)
- 在这里,我们在llm上调用batch()方法。
- 我们在批处理方法中传递了一个查询/提示列表。这些查询将被批处理,并将所有查询的组合响应存储在batch_responses变量中。
- 然后我们遍历批处理响应变量中的每个响应并将其打印出来。
输出
可以看到,响应非常准确。使用Google的Gemini LLM的langchain包装器,我们还可以利用多模态,即我们可以将文本与图像一起作为输入传递给模型,并期望模型从中生成文本。
对于此任务,我们将以下图片提供给Gemini:
代码如下:
from langchain_core.messages import HumanMessagellm = ChatGoogleGenerativeAI(model="gemini-pro-vision")message = HumanMessage( content=[ { "type": "text", "text": "用一句话描述图像?", }, { "type": "image_url", "image_url": "https://picsum.photos/seed/all/300/300" }, ])response = llm.invoke([message])print(response.content)
- 在这里,我们使用了 langchain_core 库中的 HumanMessage 类。
- 我们向其传递内容,内容是一个字典列表。每个内容都有两个属性或键,它们是“type”和“text/image_url”。
- 如果提供了“type”为“text”,那么我们就使用“text”键来传递文本。
- 如果“type”是“image_url”,那么我们就使用“image_url”,并传递上述图片的URL。在这里,我们传递了文本和图片,其中文本询问了关于图片的问题。
- 最后,我们将此变量作为列表传递给 llm.invoke() 函数,该函数会生成一个响应,然后我们通过 response.content 来访问响应。
Gemini Pro Vision 模型成功解释了该图像。模型可以接受多个图像吗?让我们试试。除了上面图片的URL之外,我们还将传递下面图片的URL:
现在,我们将要求 Gemini Vision 模型生成两个图像之间的差异:
from langchain_core.messages import HumanMessagellm = ChatGoogleGenerativeAI(model="gemini-pro-vision")message = HumanMessage( content=[ { "type": "text", "text": "这两个图像之间有什么区别?", }, { "type": "image_url", "image_url": "https://picsum.photos/seed/all/300/300" }, { "type": "image_url", "image_url": "https://picsum.photos/seed/e/300/300" } ])response = llm.invoke([message])print(response.content)
哇,看看那些观察技巧。
Gemini Pro Vision 能够推断出我们可以想到的许多东西。它能够找出着色和其他各种差异,这实际上指出了培训这个多模式 Gemini 的努力。
使用 Gemini 和 Streamlit 创建 ChatGPT 克隆
最后,经历了很多谷歌的 Gemini API,现在是时候利用这些知识来构建一些东西了。在本指南中,我们将使用 Streamlit 和 Gemini 构建一个简单的类似 ChatGPT 的应用程序。整个代码如下所示:
import streamlit as stimport osimport google.generativeai as genaist.title("Chat - Gemini Bot")# 设置 Google API 密钥os.environ['GOOGLE_API_KEY'] = "Your Google API Key"genai.configure(api_key = os.environ['GOOGLE_API_KEY'])# 创建模型model = genai.GenerativeModel('gemini-pro')# 初始化聊天记录if "messages" not in st.session_state: st.session_state.messages = [ { "role":"assistant", "content":"问我任何问题" } ]# 在应用程序重新运行时从历史记录中显示聊天消息for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"])# 处理和存储查询和响应def llm_function(query): response = model.generate_content(query) # 显示助手消息 with st.chat_message("assistant"): st.markdown(response.text) # 存储用户消息 st.session_state.messages.append( { "role":"user", "content": query } ) # 存储助手消息 st.session_state.messages.append( { "role":"assistant", "content": response.text } ) # 接受用户输入query = st.chat_input("有什么问题吗?")# 在提供输入时调用该函数if query: # 显示用户消息 with st.chat_message("user"): st.markdown(query) llm_function(query)
代码相当简单易懂。要了解更深入的理解,可以参考这里。大致上:
- 我们导入以下库:Streamlit、os、google.generativeai。
- 然后设置 Google API 密钥并配置它与模型进行交互。
- 使用模型 Gemini Pro 创建 GenerativeModel 对象。
- 初始化会话聊天记录以存储和加载聊天对话。
- 然后我们创建一个 chat_input,用户可以在其中输入查询。这些查询将被发送到 llm,并生成响应。
- 生成的响应和用户查询存储在会话状态中,并在用户界面上显示出来。
当我们运行这个模型时,我们可以像普通的聊天机器人一样与它聊天,并且输出的结果将如下所示:
结论
在本指南中,我们详细介绍了Gemini API,并学习了如何在Python中与Gemini大型语言模型进行交互。我们能够生成文本,甚至测试Google Gemini Pro和Gemini Pro Vision模型的多模态性能。我们还学习了如何使用Gemini Pro创建聊天对话,并尝试了Gemini LLM的Langchain封装。
重点收获
- Gemini是Google推出的一系列基础模型,专注于支持文本、图像、音频和视频的多模态。它包括三个模型:Gemini Ultra、Gemini Pro和Gemini Nano,每个模型的大小和能力都有所不同。
- Gemini在基准测试中表现出卓越的性能,在各种测试中优于ChatGPT和GPT4-Vision模型。
- Google重视负责任的人工智能使用,Gemini包含安全措施。它可以通过不生成回应来处理不安全的查询,并为不同类别提供安全评级。
- 该模型可以为单个提示生成多个候选,提供多样化的回应。
- Gemini Pro包括一个聊天模型,允许开发者创建对话式应用程序。该模型能够保持聊天历史并根据上下文生成回应。
- Gemini Pro Vision通过处理文本和图像输入来支持多模态,使其能够执行图像解释和描述等任务。
常见问题
本文中显示的媒体不属于Analytics Vidhya所有,仅由作者自行决定使用。