1. 简介
概览
您是一家旅游营销公司的开发者。您的销售部门决定需要一款新的聊天应用,以便与规模更大的预订和搜索公司竞争。他们也听说过生成式 AI,但不太了解它。其他部门也听说了这项计划,他们很想知道这项计划是否也能帮助他们改善客户体验。
您将执行的操作
在本实验中,您将使用 Vertex AI 上的 Gemini 2.5 Flash 模型构建一个旅行助理聊天机器人。
应用应:
- 帮助用户询问有关旅行的问题、预订旅行以及了解他们计划前往的地点
- 为用户提供有关其具体旅行计划的帮助
- 能够使用工具获取实时数据,例如天气
您将在预配置的 Google Cloud 环境(具体来说是 Cloud Shell 编辑器)中操作。系统已为您设置基本的 Web 应用前端,并授予您访问 Vertex AI 的必要权限。此应用是使用 Streamlit 构建的。
学习内容
在本实验中,您将学习如何执行以下任务:
- 探索 Vertex AI 平台,以确定可用的生成式 AI 模型。
- 在 Cloud Shell 编辑器和终端中进行开发
- 利用 Gemini Code Assist 了解代码。
- 使用 Python 中的 Vertex AI SDK 向 Gemini LLM 发送提示并接收响应。
- 应用基本的提示工程(系统指令、模型参数)来自定义 Gemini LLM 的输出。
- 通过修改提示和参数来改进回答,测试并迭代优化 LLM 赋能的聊天应用。
- 定义工具并将其与 Gemini 模型搭配使用,以启用函数调用。
- 重构代码以使用有状态的聊天会话,这是对话应用的最佳实践。
2. 项目设置
Google 账号
如果您还没有个人 Google 账号,则必须先创建一个 Google 账号。
请使用个人账号,而不是工作账号或学校账号。
登录 Google Cloud 控制台
使用个人 Google 账号登录 Google Cloud 控制台。
启用结算功能
兑换 5 美元的 Google Cloud 赠金(可选)
如需参加此研讨会,您需要拥有一个有一定信用额度的结算账号。如果您打算使用自己的结算方式,则可以跳过此步骤。
- 点击此链接,然后使用个人 Google 账号登录。您会看到类似以下内容:

- 点击点击此处以访问您的积分按钮。系统会将您转到用于设置结算资料的页面

- 点击确认
您现在已关联到 Google Cloud Platform 试用结算账号。

设置个人结算账号
如果您使用 Google Cloud 抵用金设置了结算,则可以跳过此步骤。
如需设置个人结算账号,请点击此处在 Cloud 控制台中启用结算功能。
注意事项:
- 完成本实验的 Cloud 资源费用应不到 1 美元。
- 您可以按照本实验结束时的步骤删除资源,以避免产生更多费用。
- 新用户符合参与 $300 USD 免费试用计划的条件。
创建项目(可选)
如果您没有想要用于此实验的当前项目,请在此处创建一个新项目。
3. 打开 Cloud Shell Editor
- 点击此链接可直接前往 Cloud Shell 编辑器
- 如果系统在今天任何时间提示您进行授权,请点击授权继续。

- 如果终端未显示在屏幕底部,请打开它:
- 点击查看
- 点击终端

- 在终端中,使用以下命令设置项目:
gcloud config set project [PROJECT_ID]- 示例:
gcloud config set project lab-project-id-example - 如果您不记得自己的项目 ID,可以使用以下命令列出所有项目 ID:
gcloud projects list | awk '/PROJECT_ID/{print $2}'
- 示例:
- 您应会看到以下消息:
>aside negative 如果您看到“WARNING”并被询问“Do you want to continue (Y/n)?”,则很可能是您输入的项目 ID 不正确。按 `n`,按 `Enter`,然后尝试再次运行 `gcloud config set project` 命令。>Updated property [core/project].
4. 启用 API
如需使用 Vertex AI SDK 并与 Gemini 模型互动,您需要在 Google Cloud 项目中启用 Vertex AI API。
- 在终端中,启用以下 API:
gcloud services enable \ aiplatform.googleapis.com
Python 版 Vertex AI SDK 简介
如需通过 Python 应用与 Vertex AI 上托管的模型进行交互,您需要使用 Vertex AI SDK for Python。此 SDK 简化了发送提示、指定模型参数和接收响应的过程,无需直接处理底层 API 调用的复杂性。
您可以在以下位置找到有关 Vertex AI SDK for Python 的全面文档:Vertex AI SDK for Python 简介 | Google Cloud。
5. 创建虚拟环境并安装依赖项
在开始任何 Python 项目之前,最好先创建一个虚拟环境。这样可以隔离项目的依赖项,防止与其他项目或系统的全局 Python 软件包发生冲突。
- 创建一个名为
wanderbot的文件夹,用于存储旅游助理应用的代码。在终端中运行以下代码:mkdir wanderbot && cd wanderbot - 创建并激活虚拟环境:
您会看到终端提示符带有 (uv venv --python 3.12 source .venv/bin/activatewanderbot) 前缀,表明虚拟环境处于有效状态。它看起来会像这样:
6. 为 wanderbot 创建初始文件
- 为应用创建并打开新的
app.py文件。在终端中运行以下代码:cloudshell edit app.pycloudshell edit命令会在终端上方的编辑器中打开app.py文件。 - 将以下应用启动代码粘贴到
app.py中:import streamlit as st from google import genai from google.genai import types import requests import logging # --- Defining variables and parameters --- REGION = "global" PROJECT_ID = None # TO DO: Insert Project ID GEMINI_MODEL_NAME = "gemini-2.5-flash" temperature = .2 top_p = 0.95 system_instructions = None # --- Tooling --- # TODO: Define the weather tool function declaration # TODO: Define the get_current_temperature function # --- Initialize the Vertex AI Client --- try: # TODO: Initialize the Vertex AI client print(f"VertexAI Client initialized successfully with model {GEMINI_MODEL_NAME}") except Exception as e: st.error(f"Error initializing VertexAI client: {e}") st.stop() # TODO: Add the get_chat function here in Task 15. # --- Call the Model --- def call_model(prompt: str, model_name: str) -> str: """ This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions. It will be replaced in a later step with a more advanced version that handles tooling. """ try: # TODO: Prepare the content for the model # TODO: Define generate_content configuration (needed for system instructions and parameters) # TODO: Define response logging.info(f"[call_model_response] LLM Response: \"{response.text}\"") # TODO: Uncomment the below "return response.text" line # return response.text except Exception as e: return f"Error: {e}" # --- Presentation Tier (Streamlit) --- # Set the title of the Streamlit application st.title("Travel Chat Bot") # Initialize session state variables if they don't exist if "messages" not in st.session_state: # Initialize the chat history with a welcome message st.session_state["messages"] = [ {"role": "assistant", "content": "How can I help you today?"} ] # Display the chat history for msg in st.session_state.messages: st.chat_message(msg["role"]).write(msg["content"]) # Get user input if prompt := st.chat_input(): # Add the user's message to the chat history st.session_state.messages.append({"role": "user", "content": prompt}) # Display the user's message st.chat_message("user").write(prompt) # Show a spinner while waiting for the model's response with st.spinner("Thinking..."): # Get the model's response using the call_model function model_response = call_model(prompt, GEMINI_MODEL_NAME) # Add the model's response to the chat history st.session_state.messages.append( {"role": "assistant", "content": model_response} ) # Display the model's response st.chat_message("assistant").write(model_response) - 创建并打开一个新的
requirements.txt文件,用于存放应用代码。在终端中运行以下代码:cloudshell edit requirements.txtcloudshell edit命令会在终端上方的编辑器中打开requirements.txt文件。 - 将以下应用启动代码粘贴到
requirements.txt中。google-genai streamlit requests - 安装此项目所需的 Python 依赖项。在终端中运行以下代码:
uv pip install -r requirements.txt
7. 探索代码
您创建的文件包含一个基本的聊天应用前端。具体包括:
app.py:这是我们将要处理的文件。目前,该页面包含以下内容:- 必要的导入
- 环境变量和参数(其中一些是占位符)
- 一个空的
call_model函数,我们稍后会填写 - 前端聊天应用的 Streamlit 代码
requirements.txt:- 包含运行
app.py的安装要求
- 包含运行
现在,我们来探索一下代码!
打开 Gemini Code Assist 对话
Gemini Code Assist 对话窗口应已在 Cloud Shell 编辑器右侧的面板中打开。如果 Gemini Code Assist 对话尚未打开,您可以按照以下步骤打开它:
- 点击屏幕顶部附近的 Gemini Code Assist 按钮 (
)。 - 选择打开 Gemini Code Assist 对话。

使用 Gemini Code Assist 了解代码
您可以使用 Gemini Code Assist 对话功能更好地了解代码。
- 突出显示或选择所需的代码部分。
- 在 Gemini 对话中输入“解释这段代码”。
- 点击 Enter 键提交

8. 启动 Web 应用
在将此应用连接到 LLM 之前,请先启动该应用,看看它最初的行为方式。
- 在
wanderbot目录中,于终端中运行以下命令,以启动 Streamlit 应用并使其可在 Cloud Shell 环境中本地访问: 请保持此终端窗口处于打开状态,因为 Streamlit 应用将继续运行。您可以在 Cloud Shell 中打开新的终端窗口,以运行其他命令。streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - 运行该命令后,点击 Cloud Shell 编辑器顶部的网页预览按钮,然后选择在端口 8080 上预览。

您将看到一个简单的旅游应用聊天界面。 - 输入任意消息(例如
Hi!),然后按 Enter 键。
您会注意到,该消息会显示在对话记录中,但您会收到一条错误消息,而不是 Google 助理的回答。这是因为该应用尚未连接到大型语言模型。观察此行为,了解实验的起点。
9. 初始化 Vertex AI 客户端
探索 Vertex AI 中的可用模型
Google Cloud 的 Vertex AI 平台提供对各种生成式 AI 模型的访问权限。在集成之前,您可以在 Google Cloud 控制台中探索可用的选项。
- 在 Google Cloud 控制台中,前往 Model Garden。为此,您可以在屏幕顶部的搜索栏中搜索“Model Garden”,然后选择 Vertex AI。(
) - 浏览可用的模型。您可以按模态、任务类型和功能等条件进行过滤。
在本实验中,您将使用 Gemini 2.5 Flash 模型,该模型速度快,非常适合用于构建响应迅速的聊天应用。
初始化 Vertex AI 客户端
现在,您将修改 app.py 中的 --- Initialize the Vertex AI Client --- 部分,以初始化 Vertex AI 客户端。此客户端对象将用于向模型发送提示。
- 在 Cloud Shell Editor 中打开
app.py。 - 在
app.py中,找到PROJECT_ID = None这行代码。 - 将
None替换为您的 Google Cloud 项目 ID(用英文引号括起来)。(例如PROJECT_ID = "google-cloud-labs")
如果您不记得项目 ID,可以使用以下命令列出所有项目 ID:gcloud projects list | awk '/PROJECT_ID/{print $2}' - 定义客户端:在
try块内,初始化 Vertex AI 客户端。client = genai.Client( vertexai=True, project=PROJECT_ID, location=REGION, )
更新了 Vertex AI 客户端初始化
此时,“初始化 Vertex AI 客户端”部分应如下所示:
# --- Initialize the Vertex AI Client ---
try:
client = genai.Client(
vertexai=True,
project=PROJECT_ID,
location=REGION,
)
print(f"VertexAI Client initialized successfully with model {GEMINI_MODEL_NAME}")
except Exception as e:
st.error(f"Error initializing VertexAI client: {e}")
st.stop()
10. 准备数据并调用模型
现在,您将准备要发送给模型的内容,并调用 Gemini 模型。
- 找到定义了
call_model函数的--- Call the Model ---部分。 - 定义内容:在
# TODO: Prepare the content for the model下,定义将发送给模型的输入内容。对于基本提示,这会是用户的输入消息。contents = [prompt] - 定义响应:将此代码粘贴到
# TODO: Define response下方。response = client.models.generate_content( model=model_name, contents=contents, ) - 返回响应:取消对以下一行的注释:
return response.text - 检查
with代码块中文件底部附近调用call_model函数的行。如果您不了解此处发生了什么,请突出显示相应行,然后让 Gemini Code Assist 进行解释。
一种更明确的 contents 定义方式
上述定义 contents 的方式之所以可行,是因为 SDK 足够智能,能够理解包含字符串的列表表示用户文本输入。它会自动将其格式设置为适合模型 API 的格式。
不过,更明确且更基本的输入结构化方式是使用 types.Part 和 types.Content 对象,如下所示:
user_message_parts = [types.Part.from_text(text=prompt)]
contents = [
types.Content(
role="user", # Indicates the content is from the user
parts=user_message_parts, # A list, allowing multiple types of content
),
]
更新了 call_model 函数
此时,call_model 函数应如下所示:
def call_model(prompt: str, model_name: str) -> str:
"""
This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions.
It will be replaced in a later step with a more advanced version that handles tooling.
"""
try:
contents = [prompt]
# TODO: Define generate_content configuration (needed later for system instructions and parameters)
response = client.models.generate_content(
model=model_name,
contents=contents,
)
logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")
return response.text
except Exception as e:
return f"Error: {e}"
11. 测试已关联的应用
- 在终端中,终止当前正在运行的进程 (CTRL+C)
- 重新运行命令以再次启动 Streamlit 应用。
streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - 刷新 Streamlit 应用。如果 Streamlit 应用仍在运行,您只需刷新浏览器中的网页预览页面即可。
- 现在,在聊天输入框中输入问题,例如:
What is the best time of year to go to Iceland? - 按 Enter 键。
您应该会看到应用显示您的消息、一个“正在思考…”微调框,然后是 Gemini 模型生成的回答!如果您已完成上述操作,则表示您已成功将 Web 应用连接到 Vertex AI 上的 LLM。🙌 🥳
12. 定义系统指令
虽然基本连接有效,但 LLM 回答的质量和风格很大程度上会受到其接收的输入内容的影响。提示工程是指设计和优化这些输入(提示),以引导模型生成所需的输出。
为此,您将首先创建一些系统指令,并将它们传递给模型。
您将使用 Ask Gemini 来帮助您制定有用的系统指令。
- 在
app.py中,找到当前设置为None的system_instructions变量。 您将使用一个多行字符串替换system_instructions = NoneNone,该字符串为我们的旅游助理机器人提供指令。 - 向 Gemini Code Assist 提问:将以下提示传递给 Gemini Code Assist(或自行想出提示!):
I am a developer at a travel marketing company, and my sales department has decided that they need a new chat application to keep up with the bigger booking and search companies. I'm building a simple travel assistant chatbot using the Gemini 2.5 Flash model on Vertex AI. The application should: - Helps users ask questions about travel, book travel, and learn about places they are going to go - Provides users ways to get help about their specific travel plans - Provides all this in a production quality way (multiple environments, logging and monitoring, etc.) Please create system instructions appropriate for that chat app. Be thorough. Do not alter the code in any way beyond providing me with system instructions. - 定义
system_instructions:将system_instructions设置为使用 Gemini Code Assist 生成的系统指令。您也可以使用以下系统指令,这些指令是 Gemini 根据类似提示创建的。system_instructions = """ You are a sophisticated travel assistant chatbot designed to provide comprehensive support to users throughout their travel journey. Your capabilities include answering travel-related questions, assisting with booking travel arrangements, offering detailed information about destinations, and providing support for existing travel plans. **Core Functionalities:** 1. **Travel Information and Recommendations:** * Answer user inquiries about travel destinations, including popular attractions, local customs, visa requirements, weather conditions, and safety advice. * Provide personalized recommendations for destinations, activities, and accommodations based on user preferences, interests, and budget. * Offer insights into the best times to visit specific locations, considering factors like weather, crowds, and pricing. * Suggest alternative destinations or activities if the user's initial choices are unavailable or unsuitable. 2. **Booking Assistance:** * Facilitate the booking of flights, hotels, rental cars, tours, and activities. * Search for available options based on user-specified criteria such as dates, destinations, budget, and preferences. * Present clear and concise information about available options, including pricing, amenities, and booking terms. * Guide users through the booking process, ensuring accurate information and secure transactions. * Provide booking confirmations and relevant details, such as booking references and contact information. 3. **Travel Planning and Itinerary Management:** * Assist users in creating detailed travel itineraries, including flights, accommodations, activities, and transportation. * Offer suggestions for optimizing travel plans, such as minimizing travel time or maximizing sightseeing opportunities. * Provide tools for managing and modifying existing itineraries, including adding or removing activities, changing booking dates, or upgrading accommodations. * Offer reminders and notifications for upcoming travel events, such as flight check-in or tour departure times. 4. **Customer Support and Troubleshooting:** * Provide prompt and helpful support to users with questions or issues related to their travel plans. * Assist with resolving booking discrepancies, cancellations, or modifications. * Offer guidance on travel-related emergencies, such as lost luggage or travel delays. * Provide access to relevant contact information for airlines, hotels, and other travel providers. **Interaction Guidelines:** * **Professionalism:** Maintain a polite, respectful, and professional tone in all interactions. * **Clarity and Conciseness:** Provide clear, concise, and easy-to-understand information. Avoid jargon or technical terms unless necessary and always explain them. * **Accuracy:** Ensure all information provided is accurate and up-to-date. Double-check details before sharing them with users. If unsure about something, admit that you don't know and offer to find the information. * **Personalization:** Tailor your responses and recommendations to the specific needs and preferences of each user. * **Proactive Assistance:** Anticipate user needs and offer relevant information or suggestions proactively. * **Error Handling:** Gracefully handle user errors or misunderstandings. Provide helpful guidance and alternative options when necessary. * **Confidentiality:** Respect user privacy and handle personal information with the utmost confidentiality and in compliance with data protection regulations. **Example Interactions:** **User:** "I want to go on a beach vacation in the Caribbean. I have a budget of $2000 per person for a week." **Chatbot:** "Certainly! The Caribbean offers many beautiful beach destinations within your budget. Some popular options include Punta Cana in the Dominican Republic, Cancun in Mexico, and Montego Bay in Jamaica. These destinations offer stunning beaches, all-inclusive resorts, and various activities. Would you like me to search for flights and accommodations for these locations based on your travel dates?" **User:** "My flight is delayed. What should I do?" **Chatbot:** "I'm sorry to hear about the delay. Please check with the airline for the updated departure time and any assistance they can offer. You may be entitled to compensation or rebooking options depending on the length of the delay and the airline's policy. Do you have your flight number handy so I can look up the current status for you?" **User:** "Tell me about the best time to visit Japan." **Chatbot:** "Japan is a fantastic destination with distinct seasons offering unique experiences. Spring (March-May) is famous for the beautiful cherry blossoms, while autumn (September-November) boasts stunning fall foliage. Both seasons have pleasant temperatures, making them ideal for sightseeing. Summer (June-August) can be hot and humid, but it's a great time for festivals and outdoor activities in the mountains. Winter (December-February) offers opportunities for skiing and snowboarding in the Japanese Alps, though some areas may experience heavy snowfall. To recommend the best time for you, could you tell me what you'd like to experience in Japan?" By following these instructions, you will be able to provide exceptional travel assistance and create a positive experience for every user. """ - 定义 generate_content 配置:初始化一个配置对象,您将向该对象传递这些系统说明。由于
system_instructions在我们的脚本中是全局定义的,因此该函数可以直接访问它。generate_content_config = types.GenerateContentConfig( system_instruction=[ types.Part.from_text(text=system_instructions) ], ) logging.info(f"[generate_config_details] System Instruction: {generate_content_config.system_instruction[0].text}") - 如需将系统指令添加到回答中,请向
generate content方法添加config参数,并将其设置为上面创建的generate_content_config对象。response = client.models.generate_content( model=model_name, contents=contents, config=generate_content_config, # This is the new line )
更新了 call_model 函数
完整的 call_model 函数现在如下所示:
def call_model(prompt: str, model_name: str) -> str:
"""
This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions.
It will be replaced in a later step with a more advanced version that handles tooling.
"""
try:
contents = [prompt]
generate_content_config = types.GenerateContentConfig(
system_instruction=[
types.Part.from_text(text=system_instructions)
],
)
logging.info(f"[generate_config_details] System Instruction: {generate_content_config.system_instruction[0].text}")
response = client.models.generate_content(
model=model_name,
contents=contents,
config=generate_content_config,
)
logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")
return response.text
except Exception as e:
return f"Error: {e}"
13. 使用系统指令测试应用
- 在终端中,终止当前正在运行的进程 (CTRL+C)
- 重新运行命令以再次启动 Streamlit 应用。
streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - 刷新 Streamlit 应用。如果 Streamlit 应用仍在运行,您只需刷新浏览器中的网页预览页面即可。
- 尝试提出与之前相同的问题:
What is the best time of year to go to Iceland? - 按 Enter 键。
比较本次的回答与上次的回答。
14. 定义天气工具
到目前为止,我们的聊天机器人知识丰富,但其知识仅限于训练数据。它无法访问实时信息。对于旅游机器人来说,能够获取天气预报等实时数据是一项巨大的优势。
这时,工具(也称为函数调用)就派上用场了。我们可以定义一组 LLM 可以选择调用的工具(Python 函数)来获取外部信息。
工具的运作方式
- 我们向模型描述了我们的工具,包括它们的功能和所采用的参数。
- 用户发送提示(例如,“伦敦的天气如何?”。
- 模型收到提示,并发现用户询问的内容可以通过其某个工具找到答案。
- 模型不会以文本形式回答,而是以特殊的
function_call对象进行回答,指明要调用哪个工具以及使用哪些实参。 - 我们的 Python 代码接收此
function_call,使用提供的实参执行实际的get_current_temperature函数,并获取结果(例如,15°C)。 - 我们将此结果发送回模型。
- 模型会收到结果,并为用户生成自然语言回答(例如,“伦敦目前的气温为 15°C。”)。
通过这一过程,模型可以回答超出其训练数据范围的问题,从而成为更强大、更有用的助理。
定义天气工具
如果旅客正在寻找活动建议,并且正在选择受天气影响的活动,那么天气工具可能会派上用场!我们来为模型创建一个用于获取当前天气信息的工具。我们需要两个部分:一个向模型描述工具的函数声明,以及一个实现该工具的实际 Python 函数。
- 在
app.py中,找到注释# TODO: Define the weather tool function declaration。 - 在此注释下,添加
weather_function变量。这是一个字典,用于告知模型有关函数用途、形参和必需实参的所有必要信息。weather_function = { "name": "get_current_temperature", "description": "Gets the current temperature for a given location.", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city name, e.g. San Francisco", }, }, "required": ["location"], }, } - 接下来,找到注释
# TODO: Define the get_current_temperature function。在其下方添加以下 Python 代码。此函数将:- 调用 Geocoding API 以获取相应位置的坐标。
- 使用这些坐标调用天气 API。
- 返回包含温度和单位的简单字符串。
def get_current_temperature(location: str) -> str: """Gets the current temperature for a given location.""" try: # --- Get Latitude and Longitude for the location --- geocode_url = f"https://geocoding-api.open-meteo.com/v1/search?name={location}&count=1&language=en&format=json" geocode_response = requests.get(geocode_url) geocode_data = geocode_response.json() if not geocode_data.get("results"): return f"Could not find coordinates for {location}." lat = geocode_data["results"][0]["latitude"] lon = geocode_data["results"][0]["longitude"] # --- Get Weather for the coordinates --- weather_url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t_weather=true" weather_response = requests.get(weather_url) weather_data = weather_response.json() temperature = weather_data["current_weather"]["temperature"] unit = "°C" return f"{temperature}{unit}" except Exception as e: return f"Error fetching weather: {e}"
15. 重构了聊天和工具
我们当前的 call_model 函数使用简单的单次 generate_content 调用。这非常适合单个问题,但不太适合多轮对话,尤其是涉及工具来回交互的对话。
更好的做法是使用聊天会话,这样可以保留对话的上下文。现在,我们将重构代码以使用聊天会话,这是正确实现工具所必需的。
- 删除现有的
call_model函数。我们将替换为更高级的版本。 - 取而代之的是,添加以下代码块中的新
call_model函数。此新函数包含用于处理我们之前讨论的工具调用循环的逻辑。请注意,其中包含多个 TODO 注释,我们将在后续步骤中完成这些注释。# --- Call the Model --- def call_model(prompt: str, model_name: str) -> str: """ This function interacts with a large language model (LLM) to generate text based on a given prompt. It maintains a chat session and handles function calls from the model to external tools. """ try: # TODO: Get the existing chat session or create a new one. message_content = prompt # Start the tool-calling loop while True: # TODO: Send the message to the model. # Check if the model wants to call a tool has_tool_calls = False for part in response.candidates[0].content.parts: if part.function_call: has_tool_calls = True function_call = part.function_call logging.info(f"Function to call: {function_call.name}") logging.info(f"Arguments: {function_call.args}") # TODO: Call the appropriate function if the model requests it. # If no tool call was made, break the loop if not has_tool_calls: break # TODO: Return the model's final text response. except Exception as e: return f"Error: {e}" - 现在,我们来添加一个用于管理聊天会话的辅助函数。在新的
call_model函数上方,添加get_chat函数。此函数将创建包含系统指令和工具定义的新聊天会话,或检索现有聊天会话。这是整理代码的好方法。def get_chat(model_name: str): if f"chat-{model_name}" not in st.session_state: # TODO: Define the tools configuration for the model # TODO: Define the generate_content configuration, including tools # TODO: Create a new chat session st.session_state[f"chat-{model_name}"] = chat return st.session_state[f"chat-{model_name}"]
您现在已为我们的高级工具赋能聊天逻辑设置了框架!
16. 实现工具调用逻辑
现在,我们来填写 TODOs,以使工具调用逻辑完全正常运行。
实现 get_chat
- 在
# TODO: Define the tools configuration...注释下的get_chat函数中,通过从weather_function声明创建types.Tool实例来定义tools对象。tools = types.Tool(function_declarations=[weather_function]) - 在
# TODO: Define the generate_content configuration...下,定义generate_content_config,确保将tools对象传递给模型。这样,模型就能了解它可以使用的工具。generate_content_config = types.GenerateContentConfig( system_instruction=[types.Part.from_text(text=system_instructions)], tools=[tools] # Pass the tool definition here ) - 在
# TODO: Create a new chat session下,使用client.chats.create()创建聊天对象,并传入我们的模型名称和配置。chat = client.chats.create( model=model_name, config=generate_content_config, )
实现 call_model
- 在
call_model函数的# TODO: Get the existing chat session...下,调用新的get_chat辅助函数。chat = get_chat(model_name) - 接下来,找到
# TODO: Send the message to the model。使用chat.send_message()方法发送用户消息。response = chat.send_message(message_content) - 查找
# TODO: Call the appropriate function...。在此处,我们会检查模型需要哪个函数并执行该函数。
if function_call.name == "get_current_temperature":
result = get_current_temperature(**function_call.args)
function_response_part = types.Part.from_function_response(
name=function_call.name,
response={"result": result},
)
message_content = [function_response_part]
- 最后,找到
# TODO: Return the model's final text response并添加 return 语句。return response.text
更新了 get_chat 函数
更新后的 get_chat 函数现在应如下所示:
def get_chat(model_name: str):
if f"chat-{model_name}" not in st.session_state:
#Tools
tools = types.Tool(function_declarations=[weather_function])
# Initialize a confiburation object
generate_content_config = types.GenerateContentConfig(
system_instruction=[types.Part.from_text(text=system_instructions)],
tools=[tools]
)
chat = client.chats.create(
model=model_name,
config=generate_content_config,
)
st.session_state[f"chat-{model_name}"] = chat
return st.session_state[f"chat-{model_name}"]
更新了 call_model 函数
更新后的 call_model 函数现在应如下所示:
def call_model(prompt: str, model_name: str) -> str:
try:
chat = get_chat(model_name)
message_content = prompt
while True:
response = chat.send_message(message_content)
has_tool_calls = False
for part in response.candidates[0].content.parts:
if part.function_call:
has_tool_calls = True
function_call = part.function_call
logging.info(f"Function to call: {function_call.name}")
logging.info(f"Arguments: {function_call.args}")
if function_call.name == "get_current_temperature":
result = get_current_temperature(**function_call.args)
function_response_part = types.Part.from_function_response(
name=function_call.name,
response={"result": result},
)
message_content = [function_response_part]
elif part.text:
logging.info("No function call found in the response.")
logging.info(response.text)
if not has_tool_calls:
break
return response.text
except Exception as e:
return f"Error: {e}"
17. 测试已启用工具的应用
让我们看看您的新功能在实际应用中的效果!
- 在终端中,终止当前正在运行的进程 (CTRL+C)
- 重新运行命令以再次启动 Streamlit 应用。
streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - 刷新 Streamlit 应用。如果 Streamlit 应用仍在运行,您只需刷新浏览器中的网页预览页面即可。
- 现在,提出一个应触发新工具的问题,例如:
I'm looking for something to do in New York today. What do you recommend? Would it be a good day to go to Ellis Island? - 按 Enter 键
将此回答与之前的回答进行比较。有哪些不同之处?
您应该会看到包含函数返回的温度的响应!同时检查 Cloud Shell 终端;您应该会看到确认 Python 函数已执行的 print 语句。
18. 使用参数优化模型输出
太棒了!您的旅游助理现在可以使用工具来获取实时外部数据,从而变得更加强大。
现在,我们已经增强了模型的功能,接下来我们来微调模型的回答方式。模型参数可用于控制 LLM 生成文本的风格和随机性。通过调整这些设置,您可以使机器人的输出更具针对性和确定性,也可以使其更具创意和多样性。
在本实验中,我们将重点介绍 temperature 和 top_p。(如需查看可配置参数的完整列表及其说明,请参阅我们 API 参考文档中的 GenerateContentConfig。)
temperature:控制输出的随机程度。值越低(越接近 0),输出就越具确定性和针对性;值越高(越接近 2),随机性和创造性就越强。对于问答或助理机器人,通常最好使用较低的温度,以获得更一致、更符合事实的回答。top_p:抽样时要考虑的 token 的最大累积概率。系统会根据词元的分配概率对其进行排序,以便仅考虑最有可能的词元。模型会考虑概率总和达到top_p值的最有可能的 token。较低的值会限制 token 选择,从而减少输出的变化
通话参数
- 找到
app.py顶部定义的变量temperature和top_p。请注意,它们尚未在任何位置被调用。 - 向
call_model函数中GenerateContentConfig内定义的形参添加temperature和top_p。generate_content_config = types.GenerateContentConfig( temperature=temperature, top_p=top_p, system_instruction=[types.Part.from_text(text=system_instructions)], tools=[tools] # Pass the tool definition here )
更新了 get_chat 函数
get_chat 应用现在应如下所示:
def get_chat(model_name: str):
if f"chat-{model_name}" not in st.session_state:
#Tools
tools = types.Tool(function_declarations=[weather_function])
# Initialize a confiburation object
generate_content_config = types.GenerateContentConfig(
temperature=temperature,
top_p=top_p,
system_instruction=[types.Part.from_text(text=system_instructions)],
tools=[tools]
)
chat = client.chats.create(
model=model_name,
config=generate_content_config,
)
st.session_state[f"chat-{model_name}"] = chat
return st.session_state[f"chat-{model_name}"]
19. 使用模型参数进行测试
- 在终端中,终止当前正在运行的进程 (CTRL+C)
- 重新运行命令以再次启动 Streamlit 应用。
streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - 刷新 Streamlit 应用。如果 Streamlit 应用仍在运行,您只需刷新浏览器中的网页预览页面即可。
- 尝试提出与之前相同的问题,
I'm looking for something to do in New York today. What do you recommend? Would it be a good day to go to Ellis Island? - 按 Enter 键
将此回答与之前的回答进行比较。
20. 恭喜!
您已成功使用工具升级了问答应用。工具是一项强大的功能,可让基于 Gemini 的应用与外部系统互动并访问实时信息。
持续实验
您可以通过多种方式继续优化提示。以下是一些可供考虑的选项:
- 调整
temperature和top_p,看看 LLM 给出的回答有何变化。 - 如需查看可配置参数及其说明的完整列表,请参阅 API 参考文档中的
GenerateContentConfig。尝试定义更多参数并调整它们,看看会发生什么!
回顾
在本实验中,您完成了以下操作:
- 利用 Cloud Shell Editor 和终端进行开发。
- 使用 Vertex AI Python SDK 将应用连接到 Gemini 模型。
- 应用系统指令和模型参数来引导 LLM 的回答。
- 了解了工具(函数调用)的概念及其优势。
- 重构了代码,以使用有状态的聊天会话,这是对话式 AI 的最佳实践。
- 使用函数声明为模型定义了一个工具。
- 实现了 Python 函数以提供工具的逻辑。
- 编写了代码来处理模型的函数调用请求并返回结果。