首先给大家准备一些gemini的api-key 方便大家实战gemini。
AIzaSyDFKzqbwbM78iflpIlgj81cSAaEOWjbzJs
AIzaSyBq_qvVZqp8InnNrkuAPCpJBC7EWiAnAVc
AIzaSyAxc7owaBrs9QbK9fzGplV6enyUt6T2aOg
AIzaSyCy4kznxmWi1OkLkaffZ6mL-RpVaUoeXEs
AIzaSyCj_dvlvKdf87b2zdyycFhcdHRuOigzSZQ
AIzaSyDhguhSVoZ_5EIbN2p63hDWKxNFFZBL_2s
AIzaSyBPHGM30gG4YHrTYI4yUEXYCJkTRjgYT80
AIzaSyDAJ8zQAl8nwA_JjDEf7WmAkqP8k9f5r-c
接下来,这是一个关于如何使用 Google Gemini API 和 Python 从航行情报通告 (NOTAM) 中提取结构化空域信息的教程。本教程将基于我们之前的讨论,包括定义数据结构、构建提示、进行 API 调用以及处理可能出现的 schema 问题。
教程:使用 Gemini API 和 Python 从 NOTAM 提取结构化空域信息
目标:
- 学习如何设置和使用 Google Generative AI Python SDK。
- 使用 Pydantic 定义期望的输出数据结构。
- 构建有效的提示 (prompt) 以指导 Gemini API 进行信息提取。
- 调用 Gemini API 并获取结构化的 JSON 响应。
- 处理 API 响应,包括使用
response_schema(如果支持复杂类型) 和手动 JSON 解析作为备选方案。
前提条件:
- Python 环境: 确保您已安装 Python (建议 3.9 或更高版本)。
- Google AI API 密钥:
- 您需要一个 Google Cloud 项目并启用 Vertex AI API,或者通过 Google AI Studio 获取 API 密钥。
- 获取 API 密钥后,请妥善保管。
- 安装必要的库:
pip install google-generativeai pydantic
步骤 1:设置项目和导入库
首先,创建一个 Python 文件 (例如 notam_parser.py) 并导入所需的库。
import google.generativeai as genai
from pydantic import BaseModel, TypeAdapter
import json
import os # 用于安全处理 API 密钥 (推荐)
# 用于清晰的类型提示 (Python 3.9+ 可以直接使用 list, dict)
# from typing import List, Dict
步骤 2:配置 API 密钥
安全地配置您的 API 密钥。建议使用环境变量。
# 推荐方式:从环境变量读取 API 密钥
# 在您的终端设置:export GOOGLE_API_KEY="YOUR_API_KEY"
# 或者,如果您在类似 Jupyter Notebook 的环境中,可以直接设置,但不推荐用于生产代码
# API_KEY = "YOUR_API_KEY" # 直接替换 YOUR_API_KEY,注意安全风险
try:
# 尝试从环境变量获取 API 密钥
API_KEY = os.environ["GOOGLE_API_KEY"]
except KeyError:
print("错误:GOOGLE_API_KEY 环境变量未设置。")
print("请设置该变量或在代码中直接提供 API_KEY (注意安全)。")
# 为防止代码完全中断,您可以临时在这里设置,但强烈建议使用环境变量
API_KEY = "YOUR_API_KEY_PLACEHOLDER" # <--- 临时的,请务必替换或通过环境变量设置
if API_KEY == "YOUR_API_KEY_PLACEHOLDER":
raise ValueError("请将 YOUR_API_KEY_PLACEHOLDER 替换为您的有效 API 密钥或设置 GOOGLE_API_KEY 环境变量。")
genai.configure(api_key=API_KEY)
请务必将 "YOUR_API_KEY_PLACEHOLDER" 替换为您的真实 API 密钥,或通过设置 GOOGLE_API_KEY 环境变量来提供。
步骤 3:定义输出数据结构 (Pydantic 模型)
我们将定义一个 Pydantic 模型来描述从 NOTAM 中提取的每个字段的结构。我们期望的最终输出是一个包含多个“区域”信息的列表,每个“区域”信息又包含多个提取字段。
class ExtractedField(BaseModel):
start: int
end: int
label: str # 例如: "通告号", "机场名称" 等中文标签
text: str
# 期望的整体输出结构是: list[list[ExtractedField]]
# 即一个列表,其中每个元素是代表一个空域区域信息的字段列表
步骤 4:准备输入数据 (NOTAM 文本和指令)
这是我们要处理的 NOTAM 文本和给模型的指令。
instruction_text = "检测到空域相关关键词。请参照参考案例的结构和字段标签,从航行情报通告中提取所有相关的空域信息。"
notam_to_process = """ZCZC BUI2865 251937
GG ZBAAUIXX
251937 ZBAAOIXX
UUUU
(K1372/25 NOTAMN
Q)UUWV/QRTCA/IV/BO/W/000/030/5549N03844E003
A)UUWV B)2501290900 C)2502031600
D)JAN 29-31 FEB 01 03 0900-1600
E) AIRSPACE CLSD WI AREA:
554930N0384015E-554916N0383931E-
554903N0384027E-554902N0384104E-
554905N0384411E-554909N0384845E-
554940N0384840E-554930N0384512E-
554925N0384106E-554930N0384015E
F)SFC G)640M AMSL)
NNNN"""
步骤 5:构建提示 (Prompt)
一个好的提示对于引导模型输出正确的结构化数据至关重要。
# 详细的提示,指导模型进行提取并遵循特定的JSON结构
# 注意:这里的 {notam_to_process} 将会被实际的NOTAM文本替换
prompt_template = f"""指令: {
instruction_text}
待处理的航行情报通告 (NOTAM) 文本:
---
{
notam_to_process}
---
请从上述 NOTAM 文本中提取所有相关的空域信息。
您的输出必须是一个严格的 JSON 格式字符串。
此 JSON 字符串应代表一个JSON数组,该数组的每个元素本身也是一个JSON对象列表 (即 `list[list[object]]` 结构)。
每个JSON对象代表一个提取出的字段,并且必须包含以下键值对:
- "start": (整数) 提取文本在原始 NOTAM 字符串中的起始字符索引 (0-based)。
- "end": (整数) 提取文本在原始 NOTAM 字符串中的结束字符索引 (不包含结束字符本身)。
- "label": (字符串) 字段的中文标签 (例如:"通告号", "机场名称", "多边形坐标序列" 等,请参考通用NOTAM字段定义和标签)。
- "text": (字符串) 为该字段提取的实际文本。
例如,期望的 JSON 结构是:`[[{
{"start": 0, "end": 5, "label": "示例标签", "text": "示例文本"}}]]`
如果NOTAM中包含多个空域区域的描述,请为每个区域生成一个内部列表。对于给定的NOTAM,它描述了一个主要区域。
"""
步骤 6:进行 API 调用和处理响应
我们将尝试两种方法:
- 方法 A (推荐,如果SDK支持您的schema): 使用
response_schema来让 SDK 自动解析和验证。 - 方法 B (备选方案): 如果方法 A 对于
list[list[ExtractedField]]这样的复杂嵌套 schema 失败 (出现Unsupported schema type错误),我们将移除response_schema并手动解析 JSON。
# 初始化 Gemini 模型客户端
# 您最初使用的是 client.models.generate_content,这里我们使用更通用的方式获取模型实例
# 但会保持与您原始代码相似的参数传递方式 (使用 'config' 而非 'generation_config')
# 使用您在原始代码中指定的模型
model_name = "models/gemini-2.5-flash-preview-04-17"
# 您也可以尝试其他模型,例如 "gemini-1.5-flash-latest"
# model_name = "gemini-1.5-flash-latest"
model = genai.GenerativeModel(model_name)
print(f"--- 方法 A: 尝试使用 response_schema ---")
try:
# 注意:client.models.generate_content() 是您之前用的方式。
# 如果直接使用 model.generate_content(),参数名可能是 generation_config。
# 为了与您之前的代码和错误保持一致,我们先模拟 client.models.generate_content() 的参数风格
# 但实际上 genai.GenerativeModel(model_name).generate_content() 是更推荐的用法。
# 为简单起见,这里直接用 model.generate_content 并使用正确的 generation_config。
# 如果您坚持使用 client.models.generate_content 且它存在并使用 'config',请相应调整。
# 经过之前的讨论,我们知道 client.models.generate_content(config=...) 这种方式
# 对于 list[list[ExtractedField]] 可能会报 "Unsupported schema type"
# 因此,方法A的演示将直接跳到结论,并引导至方法B。
# 或者,我们可以先尝试,如果您的SDK版本支持,它就能工作。
print("尝试使用 config 和 response_schema...")
# 这里我们用 model.generate_content,它使用 generation_config
# 如果您想严格模拟 client.models.generate_content,您需要确保该方法存在且可用。
# genai.Client 本身没有 .models.generate_content()。
# 正确的方式是 client.get_generative_model(model_name).generate_content()
# 或者 genai.GenerativeModel(model_name).generate_content()
# 我们将使用 genai.GenerativeModel().generate_content(),它使用 'generation_config'
# 并且,如果 'response_schema': list[list[ExtractedField]] 仍然不受支持,
# 我们将看到同样的错误,然后转到方法B。
response_attempt_A = model.generate_content(
prompt_template, # 使用上面定义的完整 prompt
generation_config=genai.types.GenerationConfig(


3126

被折叠的 条评论
为什么被折叠?



