使用 OpenAI API(多模态)
借助 LangChain(一个用于构建语言模型应用的灵活框架)高效使用 OpenAI 的多模态模型。你将学会配置并使用 ChatOpenAI 对象完成响应生成、模型输出分析,以及实时流式响应、token 对数概率分析等高级功能。并部署复杂 AI 方案所需的所有工具。
使用 langchain 构建一个 Agent,有以下 4 点重要的基础内容:
- 模型配置
- 提示词配置
- 工具配置
- 输出结构配置
获取一个好用的模型 API
在这里我推荐使用硅基流动的模型 API,因为它的模型性能好,价格也比较低,并且在测试和构建 Agent 时,使用免费的 API 是比较方便和将成本降下来。
注册后,进入 API 密钥页面,获取 API 密钥。
langchain_opentutorial 这个是一个比较好用的一个 Python 库,它提供了一些方便的函数和类,用于配置和使用 OpenAI 的多模态模型。
引入 langchain_openai 库,并使用 set_env 函数设置环境变量。
from langchain_opentutorial import set_env
import os
set_env(
{
"SILICONFLOW_API_KEY": "sk-iicnuzmyqazacwyxssiuvrabsntjornquscpjahkroumtrejlm",
}
)
也可以使用 os.environ 来设置环境变量。配合 dotenv 库,将环境变量存储在 .env 文件中,避免将敏感信息硬编码到代码中。
from dotenv import load_dotenv
import os
load_dotenv()
os.environ["SILICONFLOW_API_KEY"] = "sk-iicnuzmyqazacwyxiuvrssabsntjornquscpjahkroumtrejlm"
使用模型测试文本
模型配置,使用 langchain_openai 提供的 ChatOpenAI 函数,传入模型名称,返回一个模型对象。这里我们使用 Qwen/Qwen2.5-7B-Instruct 模型。
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 创建 ChatOpenAI 对象,配置为使用硅基流动 API
llm = ChatOpenAI(
temperature=0.1, # 控制输出的随机性和创造性,值越低输出越稳定可预测,值越高输出越有创意但可能偏离预期 (范围: 0.0 ~ 2.0)
model_name="Qwen/Qwen2.5-7B-Instruct", # 硅基流动支持的模型名称
openai_api_key=os.getenv("SILICONFLOW_API_KEY"), # 从环境变量获取 API 密钥
openai_api_base="https://api.siliconflow.cn/v1" # 硅基流动 API 的基础 URL
)
question = "中国的首都是哪里?"
answer = llm.invoke(question)
print(f"[Answer]: {answer}")
建议使用 pprint 库,来格式化输出模型的回答,查看模型回答的结构。
from pprint import pprint
pprint(answer)
运行以上代码,将返回一个包含模型输出的 dict。
response = llm.invoke(question)
content = response.content # AI 的回复文本
model_name = response.response_metadata["model_name"]
total_tokens = response.response_metadata["token_usage"]["total_tokens"]
# 打印结果
print(f"回复正文: {content}")
print(f"模型: {model_name}")
print(f"总 Token 用量: {total_tokens}")
下面是一个模型输出的例子:
回复正文: 中国的首都是北京。
模型: Qwen/Qwen2.5-7B-Instruct
总 Token 用量: 39
使用模型测试图片
模型配置,使用 langchain_openai 提供的 ChatOpenAI 函数,传入模型名称,返回一个模型对象。这里我们使用 THUDM/GLM-4.1V-9B-Thinking 模型。
在这个板块中就比较重要了,使用模型处理图片。通过模型处理图片,可以得到图片的描述。此时模型的强弱程度,会决定图片的描述效果。
import requests # 用于发送 HTTP 请求,下载网络图片
import base64 # 用于将图片二进制数据编码为 base64 字符串,方便传输给模型
import mimetypes # 用于根据文件路径自动推断图片的 MIME 类型(如 image/jpeg)
from IPython.display import display, HTML, Image # 在 Jupyter 环境中可视化展示图片与富文本
from langchain_openai import ChatOpenAI # 调用 OpenAI 兼容接口,创建多模态聊天模型实例
from dotenv import load_dotenv # 加载 .env 文件中的环境变量,避免明文存放密钥
import os
load_dotenv()
# 构建视觉模型
llm_imge = ChatOpenAI(
temperature=0.1, # 控制输出的随机性和创造性,值越低输出越稳定可预测,值越高输出越有创意但可能偏离预期 (范围: 0.0 ~ 2.0)
model_name="THUDM/GLM-4.1V-9B-Thinking", # 硅基流动支持的模型名称
openai_api_key=os.getenv("SILICONFLOW_API_KEY"), # 从环境变量获取 API 密钥
openai_api_base="https://api.siliconflow.cn/v1" # 硅基流动 API 的基础 URL
)
获取图片数据,并使用 base64 编码将其转换为字符串。构建一个函数来下载图片并返回图片的 base64 编码字符串。这个函数既可以处理本地图片文件,也可以处理网络图片 URL。
def encode_image(image_path):
if image_path.startswith("http://") or image_path.startswith("https://"):
# 下载图片
response = requests.get(image_path)
if response.status_code == 200:
image_content = response.content
else:
raise Exception(f"下载图片失败: {response.status_code}")
# 根据 URL 猜测 MIME 类型
mime_type, _ = mimetypes.guess_type(image_path)
if mime_type is None:
mime_type = "application/octet-stream" # 未知文件的默认 MIME 类型
else:
# 读取本地文件
try:
with open(image_path, "rb") as f:
image_content = f.read()
# 根据文件扩展名猜测 MIME 类型
mime_type, _ = mimetypes.guess_type(image_path)
if mime_type is None:
mime_type = "application/octet-stream" # 未知文件的默认 MIME 类型
except FileNotFoundError:
raise Exception(f"找不到图片文件: {image_path}")
return f"data:{mime_type};base64,{base64.b64encode(image_content).decode()}"
测试图片处理
# 测试图片处理
IMAGE_URL = "https://t3.ftcdn.net/jpg/03/77/33/96/360_F_377339633_Rtv9I77sSmSNcev8bEcnVxTHrXB4nRJ5.jpg"
encoded_image_url = encode_image(IMAGE_URL)
print(encoded_image_url)
display(Image(url=encoded_image_url)) # Display the image
创建消息
定义一个函数来生成模型所需的消息。这包括:
- 系统提示:定义 AI 的角色和任务。
- 用户提示:提供具体的任务说明。
- 已编码图像:包含 Base64 图像数据。
def create_messages(encoded_image):
system_prompt = "你是解析图像的得力助手"
user_prompt = "请详细解释这张图片"
return [
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": [
{"type": "text", "text": user_prompt},
{"type": "image_url", "image_url": {"url": encoded_image}},
],
},
]
处理结果
实时流式输出,使用 stream_response 函数,将模型输出的流式数据处理为可迭代对象。
def stream_response(llm, messages):
response = llm.stream(messages) # 流式获取 AI 响应
print("正在流式输出:")
for chunk in response:
print(chunk.content, end="", flush=True) # 实时打印每个响应块
运行程序,并传入图片路径
# 运行程序,并传入图片路径
display(Image(url=IMAGE_URL))
encoded_image_url = encode_image(IMAGE_URL)
# 创建消息和流响应
messages_url = create_messages(encoded_image_url)
stream_response(llm_imge, messages_url)
结果输出
Streaming response:
Response: The capital of the United States is Washington, D.C.
Model: Qwen/Qwen2.5-7B-Instruct
Total Tokens Used: 48
图片分析结果:
这张图片是一个数据表格,用于展示多维度信息,以下是详细解析:
1. 表格整体结构
表格标题为 "TABLE 001: LOREM IPSUM DOLOR AMIS ENIMA ACCUMER TUNA",属于占位符文字("Lorem ipsum" 常用于设计时占位,表示实际标题需替换)。表格包含 1列标题行 + 1行标题列 + 8行数据行,共4列、8行数据。
2. 列标题与对应数据类型
表格的列标题及各列数据含义如下:
- 第一列(行标题列):列出具体项目名称(如 Lorem dolor sl amet、Consecter odio 等),是数据的核心分类维度。
- 第二列 Loremis:以数值或百分比形式呈现(如 8288、123%、1005、56 等),可能是数量、占比、增长率等量化数据。
- 第三列 Amis terim:以百分比形式呈现(如 123%、87%、12%、69% 等),推测为与第二列相关的比例、增长率等百分比数据。
- 第四列 Gato lepis:以**文本(状态标签)**呈现(如 YES、NO、N/A),属于分类数据,可能是“是否满足条件”“是否适用”等状态判断。
- 第五列 Tortores:以货币金额(带
$符号)呈现(如 129、$99 等),属于财务类数据,可能是费用、价格等。
3. 各行数据示例(逐行解析)
以下是表格中8个项目的具体数据(按行顺序):
- Lorem dolor sl amet
- Loremis:8288(数值)
- Amis terim:123%(百分比)
- Gato lepis:YES(状态)
- Tortores:$89(货币)
- Consecter odio
- Loremis:123
- Amis terim:87%
- Gato lepis:NO
- Tortores:$129
- Gatoque accums
- Loremis:1005
- Amis terim:12%
- Gato lepis:NO
- Tortores:$99
- Sed hac enlim rem
- Loremis:56
- Amis terim:69%
- Gato lepis:N/A(无数据/不适用)
- Tortores:$199
- Rempus tortor just
- Loremis:5 554(数值,空格可能是排版分隔)
- Amis terim:18%
- Gato lepis:NO
- Tortores:$999
- Klimas nsecter
- Loremis:455
- Amis terim:56%
- Gato lepis:NO
- Tortores:$245
- Babisak atoque accu
- Loremis:1222
- Amis terim:2%
- Gato lepis:YES
- Tortores:$977
- Enim rem kos
- Loremis:5 002(数值,空格分隔)
- Amis terim:9%
- Gato lepis:N/A
- Tortores:$522
4. 底部文字说明
表格底部有一段占位文字(“Lorem ipsum...” 类文字),内容为:
“Lorem ipsum dolor sit amet consectetur odio non tellus noni notate accumsan. Sed hac enim. Lorem tempor justo eget scelerisque metus. Serecibus urna Vestibulum posuere. Tincidunt hendrerit volutpat. Auctor Sed urna dignissim molestie ligula. Mauris adipiscing arcu.”
这类文字是设计时常用的“占位符”,用于展示排版效果,实际场景中需替换为真实说明文字。
5. 整体用途推测
该表格可能是业务数据统计表(如产品销量、项目占比、费用分类等),通过多维度(数值、百分比、状态、货币)展示不同项目的信息,便于对比和分析。列标题和行标题的命名虽为占位,但结构符合“分类项目 + 多维度数据”的表格逻辑,属于常见的数据可视化表格形式。
综上,这张图片是一个结构清晰、多维度展示数据的示例表格,包含分类项目、数值/百分比、状态标签、货币金额等信息,底部有排版占位文字,整体用于数据展示与分析。
综合上面的内容, 制作一个简单财务报表分析的Agent
system_prompt = """你是一名专门解读表格(财务报表)的财务人工智能助理.
你的任务是分析提供的表格形式的财务报表,并以友好和清晰的方式总结有趣的见解。"""
# User prompt: Provide instructions for the task
user_prompt = """提供给你的表格是一家公司的财务报表。总结表格中有趣的见解"""
messages = [
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": [
{"type": "text", "text": user_prompt},
{"type": "image_url", "image_url": {"url": encoded_image_url}},
],
},
]
def stream_response(llm, messages):
response = llm.stream(messages) # Stream AI response
print("Streaming response:")
# Extract key components
#content = response.content # AI's response text
#model_name = response.response_metadata["model_name"]
#total_tokens = response.response_metadata["token_usage"]["total_tokens"]
# Print results
# print(f"Response: {content}")
# print(f"Model: {model_name}")
# print(f"Total Tokens Used: {total_tokens}")
for chunk in response:
print(
chunk.content, end="", flush=True
) # Print each response chunk in real time
# Execute streaming
stream_response(llm_imge, messages)
结果
Streaming response: Response: The capital of the United States is Washington, D.C. Model: Qwen/Qwen2.5-7B-Instruct Total Tokens Used: 48 以下是针对NVIDIA公司合并利润表的有趣财务见解总结,以友好清晰的方式呈现:
1. 收入与盈利的爆发式增长
公司收入从2020年的109.18亿美元(10,918百万)快速增长至2021年的166.75亿美元(16,675百万),再到2022年的269.14亿美元(26,914百万),呈现爆发式增长。同期净收入从27.96亿美元(2,796百万)增长至43.32亿美元(4,332百万),最终达到97.52亿美元(9,752百万),收入与盈利的同步增长,反映出公司在市场拓展、产品销售等方面的强劲表现,业务规模扩张直接带动了利润提升。
2. 研发投入的持续加大,体现技术领先战略
研发支出(Research and development)从2020年的28.29亿美元(2,829百万)增长至2021年的39.24亿美元(3,924百万),再到2022年的52.68亿美元(5,268百万),逐年稳步提升。研发投入的增长体现了公司在芯片、AI等领域的技术研发与新产品开发上的重视——作为科技龙头,持续的技术投入是维持行业领先地位的关键,也为长期竞争力筑牢基础。
3. 运营效率与盈利质量的提升
运营利润(Income from operations)从2020年的28.46亿美元(2,846百万)增长至2021年的45.32亿美元(4,532百万),再到2022年的100.41亿美元(10,041百万),增长幅度显著。结合收入增长与运营利润的同步提升,说明公司在成本控制、运营管理等方面效率提升,或产品结构优化(高毛利产品占比提升)带来利润改善,反映出运营质量在提升。
4. 每股收益稳步增长,股东价值提升
基本每股收益从2020年的1.15美元增长至2021年的1.76美元,再到2022年的3.91美元;稀释后每股收益也呈现类似增长趋势(1.13美元→1.73美元→3.85美元). 每股收益的提升,直接反映股东权益的收益增加,体现了公司盈利能力向股东的价值传递,股东回报持续优化。
5. 费用结构的动态优化
总运营费用(含研发、销售、管理等)随收入增长而增加,但费用增速低于收入增速,说明费用效率有所提升。同时,研发支出在收入中的占比虽略有下降(2020年约25.9%、2021年约23.5%、2022年约19.6%),但绝对值持续增长——这反映出公司在规模扩张过程中,研发投入的“相对强度”有所调整,可能是业务成熟度提升后的合理优化,既保障研发投入,又提升盈利效率。
这些见解体现了NVIDIA在收入增长、研发投入、盈利提升等方面的积极表现,也反映出公司在行业中的竞争力与增长潜力。如果您对某方面分析有更深入的需求,随时和我交流~