如何使用Python构建一个人工智能文件分析工具
如果你曾经打开过一份30页的PDF文件,然后心想“我绝对不可能读完这一切”,那么你就已经理解了为什么文件分析人工智能工具会非常有用。 想象一下,当你上传一篇研究论文、简历、CSV文件、商业报告或PDF文档后,只需简单地问这样一个问题: “其中最重要的发现是什么?” 人工智能工具无需你手动浏览整个文件,就能理解文件的内容,并回答相关问题。 在本教程中,我们正是要构建这样的工具。我们将使用Python编写一个适合初学者的 AI文件分析工具 ,它能够: 从你的电脑中接收文件 将文件上传到人工智能模型中 读取文件的内容 理解自然语言提出的问题 分析文件 给出有用的答案 处理各种类型的问题,而无需我们为
如果你曾经打开过一份30页的PDF文件,然后心想“我绝对不可能读完这一切”,那么你就已经理解了为什么文件分析人工智能工具会非常有用。
想象一下,当你上传一篇研究论文、简历、CSV文件、商业报告或PDF文档后,只需简单地问这样一个问题:
“其中最重要的发现是什么?”
人工智能工具无需你手动浏览整个文件,就能理解文件的内容,并回答相关问题。
在本教程中,我们正是要构建这样的工具。我们将使用Python编写一个适合初学者的AI文件分析工具,它能够:
从你的电脑中接收文件
将文件上传到人工智能模型中
读取文件的内容
理解自然语言提出的问题
分析文件
给出有用的答案
处理各种类型的问题,而无需我们为每种可能的情况编写单独的函数
我们将使用Python和OpenAI API来构建这个项目。
关键在于,我们不会只是复制粘贴代码就期望它能够正常运行。我们会逐行分析代码,确保你了解每一部分的功能。
通过本教程的学习,你不仅会掌握如何构建这个项目,还会理解许多实际应用中的人工智能工具所采用的基本架构。
我们将涵盖的内容:
我们实际上在构建什么?
在编写代码之前,让我们先明确“AI智能体”到底指的是什么。
一个普通的AI聊天机器人可能的工作流程如下:
用户 → 提出问题 → AI → 给出答案
而AI智能体的工作方式则更加灵活:
用户 → 明确目标 → 智能体 → 判断所需操作 → 使用工具/数据 → 分析信息 → 给出答案
在我们的项目中,“数据”其实就是一份文件。
例如,如果我们给智能体提供一篇名为“ai-research.pdf”的研究论文,然后询问它:“这篇论文的主要论点是什么?”那么智能体就需要完成以下步骤:
接收用户的问题。
访问该文件。
阅读相关内容。
理解这些内容。
对信息进行分析。
生成答案。
AI模型负责处理语言理解和推理工作,而我们的Python程序则负责协调整个流程。
这种分工非常重要。
模型并不能自动读取用户电脑上的文件。我们必须让应用程序为模型提供访问文件的权限。
OpenAI目前的API支持将上传的文件作为输入数据传递给“Responses API”,这样模型就能直接分析这些文件了。
我们将使用哪些技术?
我们的项目将会采用以下技术:
Python:我们的编程语言
OpenAI Python SDK:帮助Python与OpenAI API进行交互
Responses API:我们用来与模型交互的API接口
上传的文件:智能体将分析的数据源
提示语:指导智能体执行操作的指令
在初期阶段,我们会刻意保持项目的简单性。
你不需要使用LangChain、向量数据库、React或复杂的后端系统。
等你掌握了这个基础版本后,再逐步添加这些技术也不迟。
步骤1:创建项目
首先,为该项目创建一个文件夹。
例如:
file-analysis-agent/
在这个文件夹中,最终会包含以下文件:
file-analysis-agent/
│
├── agent.py
├── requirements.txt
└── .env
每个文件都有其特定的用途。
agent.py:我们的Python应用程序就保存在这个文件中。requirements.txt:这个文件告诉Python项目需要哪些外部包。.env:我们可以将API密钥存储在的这个文件中,而不会直接将其写入Python代码中。
将敏感信息隐藏在源代码之外,是一个非常重要的习惯,应该尽早养成。
步骤2:创建虚拟环境
在项目文件夹内打开终端。
运行以下命令:
python -m venv venv
这样就会创建一个Python虚拟环境。
虚拟环境为你的项目提供了独立的Python包集合。可以把它想象成为这个项目专门准备的一个“Python工作空间”。
在Windows系统中,可以使用以下命令激活虚拟环境:
venv\Scripts\activate
在macOS或Linux系统中,则使用:
source venv/bin/activate
激活虚拟环境后,终端提示符的前面应该会显示类似以下的内容:
(venv)
步骤3:安装OpenAI SDK
现在来安装官方的OpenAI Python包:
pip install openai
SDK为我们提供了许多Python类和方法,这些工具使得调用API变得非常方便。
如果没有SDK,我们就必须手动构造HTTP请求。
使用SDK后,我们可以像这样编写Python代码:
clientresponses.create...
而无需手动构建整个HTTP请求流程。
目前OpenAI的快速入门指南中,是建议使用Responses API作为进行API请求的起点。
步骤4:创建你的API密钥
要与OpenAI的API进行交互,你需要一个API密钥。请通过你的OpenAI开发者账户来生成这个密钥。
**绝对不要**将真实的API密钥直接写入源代码中,例如这样:
api_key = "sk-your-real-key"
这种做法是错误的。
如果你将项目上传到GitHub上,很可能会不小心泄露这个密钥。因此,应该将其存储为环境变量。
例如,在Windows PowerShell中,可以这样操作:
$env:OPENAI_API_KEY="your_api_key_here"
在macOS/Linux系统中,则使用:
export OPENAI_API_KEY="your_api_key_here"
OpenAI SDK能够自动读取OPENAI_API_KEY这个环境变量。
步骤5:创建requirements.txt文件
创建一个名为“requirements.txt”的文件:
requirements.txt
将其内容放入如下代码中:
openai
现在,其他开发者就可以使用以下命令来安装该项目所需的依赖库:
pip install -r requirements.txt
这虽然是一件小事,但却是一种非常实用的专业习惯。
步骤6:创建Python文件
创建一个名为“agent.py”的文件:
agent.py
文件的开头应写上以下代码:
from openai import OpenAI
让我们来详细解释这段代码。
from:Python中的from关键字允许我们从其他模块中导入内容。openai:这就是我们之前安装的Python包。import OpenAI:我们正在从该包中导入OpenAI类。
现在我们可以创建一个OpenAI客户端了。
添加以下代码:
client = OpenAI()
这样我们就创建好了API客户端。你可以把client看作是我们的应用程序与OpenAI API之间的连接点。每当我们需要与API进行交互时,都会使用这个客户端。
例如:
response = clientresponses.create...
客户端会负责处理底层的HTTP通信工作。
步骤7:向用户请求文件路径
我们希望应用程序能够允许用户指定要处理的文件路径。
添加以下代码:
file_path = input("请输入文件的路径:')
现在我们来解释这一行代码的作用。
input()函数会等待用户输入内容。
例如,终端可能会显示如下提示:
请输入文件的路径:
用户可以输入诸如“research.pdf”这样的文件路径。
Python会将用户输入的文本存储在file_path变量中。
因此,当用户输入“research.pdf”后,我们实际上就有了以下代码:
file_path = "research.pdf"
现在我们的程序就已经知道用户想要分析的是哪个文件了。
步骤8:检查文件是否存在
在上传任何文件之前,先确认文件确实存在是非常重要的。
我们可以使用Python内置的os模块来完成这个检查。
添加以下代码:
import os
然后编写如下判断语句:
if not os.path.exists(file_path):
print("文件未找到。")
exit()让我们来详细分析一下这段代码。
`os`模块为Python提供了用于与操作系统交互的工具。
其中其中一个工具就是:
os.path.exists()
这个函数用于检查某个路径下是否存在文件或文件夹。
`if`语句用来判断某个条件是否成立。
if not os.pathexists(file_path):
这意味着:
如果文件不存在……
关键字`not`会反转这个判断结果。
如果:
os.path.exists(file_path)
返回`True`,那么`not True`就会变成`False`;但如果文件确实不存在,`False`就会变成`True`。
因此,只有当文件找不到时,`if`语句内的代码才会被执行。
接下来,`print()`函数会输出:
文件未找到。
`exit()`函数则会终止程序的运行。
这样就可以防止我们的应用程序尝试上传根本不存在的文件。
步骤9:上传文件
现在来到有趣的部分了:我们需要将文件发送到API服务器。
添加以下代码:
with open(file_path, "rb") as file:
uploaded_file = client.files.create(
file=file,
purpose="user_data"
)
这段代码看起来可能有点复杂,但实际上并不难理解。
我们一步一步来分析它吧。
了解`open()`函数
第一行代码是:
with open(file_path, "rb") as file:
`open()`函数用于打开文件。
它的第一个参数是:
file_path也就是用户输入的文件路径。
第二个参数是:
"rb"这表示:
r表示以读取模式打开文件b表示以二进制模式打开文件
因为我们处理的是上传的文件,而不是普通的文本文件,所以才使用二进制模式。
`with`语句非常重要,因为它能确保我们在使用完文件后自动关闭它。
变量`file`表示被打开的文件对象。
上传文件
在`with`代码块中,我们有:
uploaded_file = client.files.create(
这段代码请求OpenAI API创建一个用于存储上传文件的目录。
参数`file`表示:
file=file我们传入了被打开的文件对象。
然后,:
purpose="user_data"这个参数告诉API,上传的文件是用于存储用户数据的。
文件API提供了`user_data`这一功能,以便更灵活地使用文件。
完成上传后,OpenAI会返回有关上传文件的信息。我们将这些信息存储在以下变量中:
uploaded_file其中一个有用的属性是:
uploaded_file.id这个ID用于标识上传的文件。
步骤10:查看上传文件的ID
添加以下代码:
print("上传的文件ID为:", uploaded_file.id)现在你将会看到类似这样的输出:
上传的文件ID为:file-abc123这个ID非常重要。
在我们的本地计算机上,该文件的名称是:
research.pdf而API识别该文件的名称则是:
file-abc123在将文件发送给模型时,我们可以使用这个ID。
步骤11:创建智能体的指令
现在我们需要告诉AI它的任务是什么。
创建如下代码:
instructions = """ 你是一个文件分析助手。 你的任务是仔细分析用户提供的文件,并根据文件中的信息回答问题。 如果文件中没有相关信息,就明确说明该信息并不存在于文件中。 不要编造事实。 在合适的情况下,可以使用标题和列表项来组织你的回答。 """这种文本被称为指令或提示语。
使用三引号:
"""... """可以让我们创建多行的文本字符串。
现在,我们的智能体已经明确了自己的职责。
它知道:
自己应该完成什么任务
应该使用哪些信息来完成任务
当缺少相关信息时应该如何处理
应该如何格式化自己的回答
其中,这条指令:
不要编造事实。
对于文件分析任务来说尤为重要。
我们希望模型能够区分以下两种情况:
“文件中明确写明了这一点。”
和:
“我认为这可能是正确的。”
这两者是完全不同的。
步骤12:询问用户他们想要了解什么
现在我们需要知道用户具体想了解什么问题。
添加以下代码:
question = input("您希望我分析哪些内容?')
例如,用户可以输入:
这篇论文中最重要的三个结论是什么?
或者:
研究人员采用了哪种研究方法?正是在这里,我们的应用程序展现出了它的灵活性。
我们不需要为每一种可能的问题都单独编写Python函数,用户可以自然地提出问题。
步骤13:将文件和问题发送给模型
现在,我们终于可以生成响应内容了。
添加以下代码:
response = clientresponses.create(
model="gpt-5",
instructions=instructions,
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": question
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
这是整个项目中最重要的部分。
让我们仔细了解一下它的工作原理吧。
了解`client.responses.create()`
首先,我们使用以下代码:
clientresponses.create(
我们正在请求Responses API生成一个响应结果。
OpenAI API允许在Responses API中接收文件作为输入数据,也可以使用上传文件的ID作为`input_file`参数。
了解模型
我们在代码中指定了:
model="gpt-5"
这一指定告诉API应该使用哪个模型来处理这个请求。
模型是负责理解问题并分析所提供的信息的部分。
你选择的模型可能会随时间发生变化,因此应将模型名称视为应用程序中可配置的部分,而不是硬编码在系统架构中的固定元素。
了解`instructions`
接下来是这部分代码:
instructions=instructions
还记得我们之前定义的那个变量吗?
instructions = """
你是一个文件分析助手。
...
"""
我们将这些指令传递给API请求,这样模型就能知道自己应该扮演什么角色。
了解`input`
接下来是这个部分:
input=[
`input`参数包含了我们提供给模型的信息。
在我们的例子中,我们提供的信息包括:
用户提出的问题
文件内容
这一点非常重要,因为如果不对AI模型提供相应的文件,它就无法回答与文件相关的问题。
了解用户输入的信息
在`input`参数中,我们还包含了以下内容:
{
"role": "user",
这一指定告诉API,当前这些数据代表了用户的输入信息。
然后:
"content": [
这部分内容包含了该消息的实际内容。
发送问题
第一个内容项是:
{
"type": "input_text",
"text": question
}
这部分内容告诉模型:
这里有一些文本输入内容。
而实际使用的文本则来自:
question
这是用户输入的内容。
如果用户输入的是:
主要结论是什么?
那么模型就会收到这个问题。
发送文件
下一个内容项是:
{
"type": "input_file",
"file_id": uploaded_file.id
}
这部分内容告诉API:
这里有一个文件需要上传。
而:
uploaded_file.id
这一信息则明确指出了我们要上传的是哪个文件。
因此,我们的请求实际上包含以下内容:
问题:
“主要结论是什么?”
文件:
research.pdf
模型就可以在用户提出问题的背景下分析这个文件了。
步骤14:打印答案
我们把响应结果存储在了:
response
但我们并不想打印整个响应对象,而是想要获取生成后的文本。
SDK提供了这样的方式:
response.output_text
因此,我们可以添加以下代码:
print("\n智能体:\n")
print(response.output_text)
第一个print()语句会输出一些空格,然后打印:
智能体:
第二个print()语句则会输出实际的答案。
我们的第一个完整版本
目前,我们的整个agent.py文件内容如下:
import os
from openai import OpenAI
client = OpenAI()
file_path = input("请输入文件的路径: ")
if not os.path.exists(file_path):
print("文件未找到。")
exit')
with open(file_path, "rb") as file:
uploaded_file = client.files.create(
file=file,
purpose="user_data"
)
print("上传的文件ID为:", uploaded_file.id)
instructions = """
你是一个文件分析助手。
你的任务是仔细分析用户提供的文件,并根据文件中的信息回答问题。
如果文件中没有相关的信息,就明确说明这些信息并不存在于文件中。
不要编造事实。
在适当的情况下,可以使用标题和项目符号来组织你的回答。
"
question = input("你希望我分析什么内容? ")
response = clientresponses.create(
model="gpt-5",
instructions=instructions,
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": question
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
print("\n智能体:\n")
print(response.output_text)
这已经是一个功能完备的文件分析人工智能应用了。
但我们还可以让它变得更好。
步骤15:运行应用程序
将如下文件放入你的项目文件夹中:
research.pdf
然后运行以下命令:
python agent.py
你会看到这样的提示:
请输入文件的路径:
输入文件名:
research.pdf
接着你会看到如下信息:
文件已上传:file-abc123
接下来会询问:
用五个要点总结主要研究结果。
该应用程序会分析文件并给出答案。
为什么这被称为“智能代理”?
乍一看,这似乎只是一个普通的API调用。从技术层面来说,我们的第一个版本确实是一个相当简单的智能代理系统。
关键在于智能代理的循环机制。
一般来说,一个智能代理会具备以下要素:
目标
操作指令
信息获取能力
可使用的工具
推理机制
执行动作的能力
输出结果
我们的应用程序也包含了这些要素。
用户首先设定目标:
分析这篇研究论文。
操作指令决定了智能代理的行为方式:
你是一个文件分析助手。文件本身提供了所需的信息:
research.pdf模型处理这些信息后,应用程序会返回分析结果。
随着技术的发展,智能代理还可以使用文件搜索、网络查询、函数调用等外部工具。OpenAI的平台目前支持内置工具以及自定义功能模块,以便进一步扩展智能代理的功能。
步骤16:将其发展成真正的对话系统
我们目前的应用程序只允许用户提出一个问题。
这虽然有用,但还不够理想。
想象一下,如果你上传了一篇研究论文,每次想要再提问题时都得重新启动程序,那就太不方便了。
我们可以通过让用户反复提问来解决这个问题。
question = input("你希望我分析什么内容吗? ")我们可以改成这样:
while True: question = input("\n请提出问题(或输入‘exit’退出):") if question.lower() == "exit": break现在我们来详细解释这个代码。
while True:创建一个无限循环。它会不断询问用户问题,直到收到停止指令为止。
question = input(...):用户输入新的问题。
question.lower():将用户输入的问题转换为小写形式,以便后续处理。例如:
EXIT会变成:
exit而:
Exit也会变成:
exit这样就能让我们的退出判断更加可靠了。
最后,
break关键字可以用来终止循环。因此:if question.lower() == "exit": break的意思是:
如果用户输入“exit”,程序就会停止提问。
步骤17:将AI请求放入循环中
现在,API请求需要在循环内部执行。
我们的代码结构变为:
while True: question = input("\n请提出一个问题(或输入‘exit’):") if question.lower() == "exit": break response = clientresponses.create( model="gpt-5", instructions=instructions, input=[ { "role": "user", "content": [ { "type": "input_text", "text": question }, { "type": "input_file", "file_id": uploaded_file.id } ] } ] ) print("\n智能助手:现在,用户可以针对同一个文件提出多个问题。
请提出一个问题: 这篇论文是关于什么的?然后:
请提出一个问题: 研究人员采用了哪种研究方法?接着:
请提出一个问题: 这项研究存在哪些最大的局限性?最后:
请提出一个问题: exit这样,这个应用程序就会显得更加像一个真正的助手了。
步骤18:优化智能助手的指令
一个优秀的AI应用程序并不仅仅在于调用API,指令的内容也非常重要。
我们可以让这些指令更加具体、清晰。
instructions = """ 你是一个AI文件分析助手。 你的任务是分析用户提供的文件。 请遵守以下规则: 1. 以用户提供的文件作为主要信息来源。 2. 直接回答用户的问题。 3>不要编造文件中没有提到的内容。 4>如果文件中的信息不足以回答问题,就直接说明这一点。 5>在总结时,重点介绍最重要的内容。 6>在对比不同观点时,要清楚地说明它们之间的相似之处和差异。 7>在分析研究结果时,要区分结果、方法和结论。 8>除非用户要求使用专业术语,否则请使用简单的语言进行表达。 9>使用项目符号来使答案更易于理解。 10>如果你进行了推论,请明确标注这一点。 """这种方式要有效得多。
我们实际上是在为人工智能设定一套规则。
为什么良好的指示非常重要
想象一下,如果你对某人说:
“请阅读这份文件。”
他们可能会阅读这份文件,然后告诉你各种各样的内容。
但现在,如果你说:
“请阅读这份文件,找出其中的研究问题,总结研究方法,归纳主要结论,并用简单的语言解释这些结论的局限性。”
第二种指示显然要有用得多。
人工智能的工作原理也是如此。你越清晰地定义任务要求,模型就越容易产生一致的结果。
步骤19:添加错误处理机制
目前,我们的程序假设一切都会顺利进行。
但在实际应用中,这种情况是不可能发生的。文件上传可能会失败,API可能会返回错误信息,用户输入的路径可能是无效的,或者网络也会出现临时故障。
我们可以使用
try和except来处理这些情况。例如:
try: response = clientresponses.create( model="gpt-5", instructions=instructions, input=[ { "role": "user", "content": [ { "type": "input_text", "text": question }, { "type": "input_file", "file_id": uploaded_file.id } ] } ] ) print(response.output_text) except Exception as error: print("发生了错误:") print(error)
try:位于try块内的代码是那些可能会出错的代码。
except:如果出现了错误,Python会跳转到except块来执行相应的处理代码。
Exception as error:这种写法用于捕获具体的错误类型,以便我们能够将其显示出来。这样一来,整个应用程序不会因为出现错误而崩溃,用户看到的只会是这样一条提示:
发生了错误: ...对于实际开发的应用程序来说,通常还需要更复杂的日志记录和错误处理机制,但这个例子已经是一个很好的起点。
步骤20:验证文件扩展名
我们还可以检查用户选择的文件类型。
可以添加以下代码:
allowed_extensions = { ".pdf", ".txt", ".docx", ".csv" }这样,我们就定义了一组应用程序应该支持的文件扩展名。
接下来,我们可以使用以下代码来获取文件的扩展名:
extension = os.path.splitext(file_path)[1].lower()让我们来详细解释一下这个代码的作用。
os.path.splitext()这种方法可以将文件名与其扩展名分开。
以以下示例为例:
research.pdf处理后,我们会得到:
research以及:
.lower()会将扩展名转换为小写形式。因此,RESEARCH.PDF会变成:if extension not in allowed_extensions: print("不支持的文件类型。") exit()这样就可以防止用户上传那些我们的应用程序无法处理的文件类型。在扩展应用程序之前,一定要先确认所选API和模型支持哪些文件类型。OpenAI的文件处理相关文档中明确列出了支持的各种输入格式。步骤21:在界面中添加文件名显示
我们可以让终端的使用体验更加友好一些。
原来是这样写的:print("上传的文件为:", uploaded_file.id)现在可以改成:print(f"\n文件已成功上传:{os.path.basename(file_path)}")字符串前加上`f`,就可以创建一个f-string。这样我们就可以在`{}`中插入Python变量了。例如:f"文件已成功上传:{os.path.basename(file_path)}"
运行后就会显示:
文件已成功上传:research.pdf
os.path基底名()
这个函数可以从路径中提取出仅文件名部分。
如果用户输入:
documents/research.pdf
那么:
os.path基底名(file_path)
会返回:
步骤22:构建最终的干净版本
现在,让我们把所有这些部分整合到一起。
以下是经过优化后的应用程序代码:
import os
from openai import OpenAI
# 创建OpenAI客户端。
client = OpenAI()
# 询问用户要上传的文件路径。
file_path = input("请输入文件路径:").strip()
# 确保文件存在。
if not os.path.exists(file_path):
print("文件未找到。")
exit()
# 支持的文件类型。
allowed_extensions = {
".pdf",
".txt",
".docx",
".csv"
}
# 获取文件扩展名。
extension = os.path.splitext(file_path)[1].lower()
# 检查文件类型是否被支持。
if extension not in allowedExtensions:
print(f"不支持的文件类型:{extension}")
print("支持的文件类型有:", ", ".join(allowed_extensions))
exit()
# 上传文件。
try:
with open(file_path, "rb") as file:
uploaded_file = client.files.create(
file=file,
purpose="user_data"
)
except Exception as error:
print("文件无法上传。")
print(error)
exit()
print(f"\n文件已成功上传:{os.path基底名(file_path)}")
# 定义智能体的行为规则。
instructions = """
你是一个AI文件分析助手。
你的任务是分析用户提供的文件。
请遵循以下规则:
1. 以用户提供的文件作为主要分析依据。
2. 直接回答用户的问题。
3. 不要编造文件中没有的信息。
4. 如果文件中的信息不足以回答问题,就直接说明这一点。
5. 在总结内容时,重点介绍最重要的信息。
6>在比较不同观点时,要清楚地说明它们之间的相似之处和差异。
7>在分析研究资料时,要区分方法、结果和结论。
8>除非用户要求使用专业术语,否则请使用简单的语言进行表达。
9>使用项目符号可以使答案更易于理解。
10>如果你得出了某种推论,请明确标明这一点。"
# 开始对话。
print("\n你的文件已经准备好进行分析了。」)
print("你可以提出关于这个文件的问题。」)
print("完成后输入‘exit’来结束对话。")
while True:
# 从用户那里获取问题。
question = input("\n你:").strip()
# 如果用户想要退出程序,就停止运行。
if question.lower() == "exit":
print("再见!")
break
# 如果用户没有输入任何内容,就提示他们重新输入问题。
if not question:
print("请输入一个问题。")
continue
# 将问题和文件发送给模型进行处理。
try:
response = client.responses.create(
model="gpt-5",
instructions=instructions,
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": question
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
# 显示智能体的回复结果。
print("\n智能体回答:")
print(response.output_text)
except Exception as error:
print("\n智能体在处理过程中遇到了错误。」)
print(error)
让我们来了解一下这个架构吧
在这个阶段,暂时抛开代码来看会更有帮助。我们的应用程序由多个层次构成。
第1层:用户界面
终端会提示:
请输入文件的路径:
以及:
您:
用户就是通过这种方式与我们的应用程序进行交互的。
第2层:文件处理
Python会检查:
os.path.exists(file_path)
然后会打开文件:
open(file_path, "rb")
这一层负责处理本地文件。
第3层:文件上传
应用程序会将文件发送给API:
client.files.create...
API会返回一个文件ID。
第4层:代理指令
我们会定义如下内容:
instructions
这些指令用于告诉模型应该如何运行。
第5层:用户请求
用户会提出这样的问题:
主要分析结果是什么?
第6层:模型
模型会接收以下信息:
指令内容
用户提出的问题
文件内容
然后模型会生成相应的答案。
第7层:输出结果
我们会将如下内容显示给用户:
response.output_text
这种分层结构非常有用,因为它能让项目在后续开发过程中更易于扩展。
为什么不需要手动提取每一份PDF文件
初学者可能会想:
“为什么不先使用Python来提取所有文本呢?”
这当然是可行的。你可以使用诸如PyPDF、python-docx或pandas这样的库,来自行读取不同格式的文件。
之后,你可以将提取出的文本发送给AI模型进行处理。
这种做法在需要自定义预处理步骤时确实很有用,但也会增加工作量。
因为你需要分别为不同的文件格式编写相应的处理逻辑:
PDF → 提取文本
DOCX → 提取文本
CSV → 读取数据行
TXT → 读取文本内容
而且你还得想办法将所有这些处理结果发送给模型。
而对于文件输入来说,API可以直接接收文件,这样就能简化那些支持此类输入方式的应用程序的架构设计。
但是对于非常大的文件该怎么办呢?
在这里,事情就变得有趣起来了。
想象一下,如果有用户上传了一份包含2000页内容的文档集,你肯定不会想把所有这些内容都一次性发送到API中去进行处理吧。
相反,你可能需要一个能够搜索出最相关内容的系统。这时,信息检索技术就显得非常重要了。
一种常见的架构如下:
文档
↓
被分割成多个部分
↓
生成嵌入向量
↓>
存储可搜索的表示形式
↓>
用户提出问题
↓>
找到相关内容
↓>
将相关信息传递给模型
↓>
生成答案
这种方法通常与检索增强生成技术(即RAG)联系在一起。
OpenAI也提供了一种文件搜索工具,该工具可以利用向量存储来查找上传的文件。
在我们的第一个项目中,我们有意没有采用RAG技术,因为这样做会一次性引入太多复杂的概念。
首先应该了解直接文件分析的方法,然后学习信息检索技术,最后再将这两种技术结合起来。
直接文件输入与RAG的区别
理解这两者之间的区别是非常有用的。
直接文件输入
你只需向模型提供某个特定请求所需的文件即可。
上传文件:research-paper.pdf
问题:这篇研究论文的主要结论是什么?
这种方法简单易懂,非常适合许多小型应用场景。
RAG
如果你拥有大量的文档,那么这种方法会更加实用。
100篇研究论文
50份报告
20本手册
对于每个问题,你不需要将所有相关文件都提供给模型,而是先在文档集合中搜索相关信息,然后再将这些信息传递给模型。
这种方法对于处理大型知识库来说更具可扩展性。
步骤23:让智能体能够更好地处理不同类型的文件
不同类型的文件包含的信息各不相同。
研究论文
这种文件可能包含研究内容。
姓名,年龄,分数
亚历克斯,17,91
萨姆,18,87
CSV文件可能包含表格数据。
一篇长篇论文
DOCX文件则可能包含文章内容。
一个优秀的智能体应该能够识别自己正在处理的是哪种类型的信息。
我们可以通过调整指令来体现这一点。
instructions = """
你是一个AI文件分析助手。
首先,请确定上传的文件包含哪些类型的信息。
如果文件是研究论文:
- 明确研究主题。
- 说明研究方法。
- 总结研究结果。
- 阐述结论。
- 指出研究的局限性。
如果文件包含表格数据:
- 列出所有列名。
- 描述其中的重要规律。
- 如有可能,找出异常值。
- 清晰地分析数据趋势。
- 不要随意编造数值结果。
如果文件是一份普通文档:
- 明确其主要用途。
- 概括其中的重要内容。
- 根据文档内容回答问题。
在任何情况下:
- 一定要以文件中的信息作为主要依据。
- 不要编造事实。
- 清晰地区分事实和推论。
> 当文件中的信息不足以回答问题时,要明确说明这一点。
- 使用简单明了的语言进行交流。
"""
现在,我们的智能助手已经掌握了更多关于它可以执行哪些任务的信息。
步骤24:为智能助手指定具体的职责
你可以将这种指令视为智能助手的工作描述。
例如:
你是一名人工智能研究助理。
这样的描述相当笼统。
但如果是:
你是一名专门负责分析学术论文的人工智能研究助理。
这种描述就具体多了。
我们还可以进一步细化:
你是一名专门帮助学生理解学术论文的人工智能研究助理。
这样,我们就为智能助手明确了服务对象。
模型就可以根据这些信息来调整自己的解释方式。
这就是一种无需编写大量代码就能让人工智能应用变得更有用的方法。
步骤25:添加分析模式
如果我们允许用户选择不同的分析模式,那么这个应用就会变得更加有用。
例如:
1. 概括内容
2. 详细解释
3> 找出关键点
4> 进行深入分析
5> 提出问题
我们可以这样设计用户界面:
mode = input(
"\n请选择一种模式:"
"概括内容、详细解释、深入分析,还是提出问题?"
)
然后根据用户的选择来调整提示信息。
例如:
if mode.lower() == "summarize":
task = "概括文件中的主要信息。"
elif mode.lower() == "explain":
task = "用简单的语言解释这个文件的内容。"
elif mode.lower() == "analyze":
task = "对这个文件进行详细分析。"
else:
task = question
这就是一个简单的例子,说明了如何通过应用程序逻辑来控制人工智能模型。
虽然语言内容还是由人工智能生成的,但具体该执行哪种任务则是由我们的Python程序决定的。
步骤26:为什么这种方法不同于将所有答案都硬编码进去
想象一下,如果你需要支持以下这些问题:
概括这个文件的内容。
它的核心观点是什么?
它有哪些局限性?
它的目标用户是谁?
有什么证据可以支持这个结论?
从技术上讲,你可以为每个问题编写一个单独的Python函数。但这样做很快就会变得非常繁琐。
相反,我们可以让用户以自然的方式提出问题:
question = input("你想了解什么?')
人工智能会处理用户输入的语言信息,而我们的应用程序则会提供相应的文件和背景资料。
这就是在应用程序中使用语言模型的最大优势之一。
步骤27:安全问题不容忽视
现在,让我们来谈谈一个虽然不如人工智能部分那么令人兴奋,但却极其重要的话题——安全性问题。
切勿泄露你的API密钥。
错误的做法:
client = OpenAI(
api_key="sk-real-secret-key"
)
正确的做法:
client = OpenAI()
应该将密钥存储在环境变量中。
同时,也千万不要将敏感信息提交到GitHub上。
你的`.gitignore`文件应该包含以下内容:
.env
venv/
__pycache__/
如果你决定在本地使用`.env`文件,一定要确保Git会忽略这些文件。
步骤28:谨慎处理敏感文件
文件分析工具可能会处理敏感信息,因此在上传以下类型的数据之前,你必须慎重考虑:
医疗记录
财务信息
密码
私营公司的文件
个人身份证明文件
学校的机密档案
你的应用程序的隐私保护要求取决于你所处理的数据类型。
不要把AI API当作一个可以随意上传电脑上所有文件的工具。
在部署处理敏感信息的文件分析应用程序之前,一定要了解提供商当前的数据控制措施、数据保留政策等。OpenAI在其平台文档中详细说明了这些内容。
开发者常犯的错误
常见错误#1:将API密钥放在GitHub上
绝对不要这样做:
api_key = "your-secret-key"
然后将其提交到GitHub上。
应该使用环境变量来存储密钥。
常见错误#2:认为AI能理解文件中的所有内容
仅仅因为你上传了一个文件,并不意味着你的应用程序就能自动解决其中包含的所有问题。
模型分析文件的能力取决于以下因素:
文件类型
文件大小
文件结构
模型的功能限制
API的使用限制
你提供的指令的清晰度
问题的复杂程度
在设计应用程序时,必须考虑到这些限制因素。
常见错误#3:要求模型“直接进行分析”
这样的指令:
分析这个文件。
过于模糊,无法让模型明确知道应该做什么。
更好的指令应该是:
找出文件的主要论点,总结相关证据,说明分析方法,并指出该分析的局限性。
清晰明确的指令才能使任务更加容易完成。
常见错误#4:忽视分析结果中的异常信息
AI模型可能会生成错误的信息。
因此,我们的使用说明中包含了以下内容:
请不要编造信息。
以及:
如果文件中的信息不够充分,请明确说明这一点。
不过,你仍然需要自行验证那些重要的信息。
对于那些涉及高风险的应用场景来说,你需要更完善的评估与验证机制。
常见错误#5:向各个地方发送大量数据
如果你拥有成千上万的文档,千万不要把它们全部包含在每一次请求中。
在这种情况下,检索系统就会派上用场了——先进行搜索,然后再将最相关的信息提供给模型。
常见错误#6:试图一次性完成所有开发工作
初学者常犯的一个错误就是试图同时开始使用以下这些技术:
React
FastAPI
LangChain
PostgreSQL
Pinecone
Docker
Kubernetes
OpenAI
Authentication
RAG
Agents
请千万不要这样做。
否则,你花费在调试基础设施上的时间将会远远超过学习AI技术所花的时间。
正确的做法应该是先从以下这些基础开始:
Python
+
OpenAI API
+
文件处理相关功能
先确保这些基础部分能够正常运行,然后再逐步添加其他功能。
最终程序的工作原理
让我们来总结一下这个程序的整体工作流程。
用户首先运行以下命令:
python agent.py
程序会询问用户:
请输入文件的路径:
用户输入文件路径后,Python会检查该文件是否存在。
如果文件存在,程序会将其上传到服务器:
client.files.create...
API会返回一个文件ID,应用程序会将这个ID保存下来。
随后,用户会再次被询问:
使用说明
+
问题内容
+
文件路径
模型会对这些信息进行分析,最后程序会输出分析结果:
response.output_text
用户就能得到答案了。
这就是一个用于文件分析的AI系统的核心工作流程。
需要牢记的最重要代码段
如果其他内容你都忘记了,也请务必记住这个代码结构:
from openai import OpenAI
client = OpenAI()
with open("research.pdf", "rb") as file:
uploaded_file = client.files.create(
file=file,
purpose="user_data"
)
response = clientresponses.create(
model="gpt-5",
instructions="仔细分析上传的文件。",
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "主要论点是什么?"
},
{
"type": "input_file",
"file_id": uploaded_file.id
}
]
}
]
)
print(response.output_text)
重要的思维模型是:
打开文件
↓
上传文件
↓
获取文件ID
↓
发送问题及文件ID
↓
模型分析文件
↓
输出答案
一旦你理解了这个流程,就可以在此基础上构建更加复杂的应用程序。
利用这个工具可以构建什么
这个简单的项目可以成为许多实际应用的基础。
AI研究助手
上传学术论文后,可以询问:
这项研究的核心问题是什么?
主要的研究成果有哪些?
简历分析器
上传简历后,可以询问:
学习辅助工具
上传教科书章节后,可以请求:
法律文件助手
上传文件后,可以针对其内容提出问题,同时要特别注意隐私保护、信息准确性以及必要的法律保障措施。
其中最重要的发展趋势有哪些?
最后的思考
一开始,构建一个能够读取文件的AI系统可能会让人觉得很复杂。
但仔细分析之后会发现,其核心理念其实非常简单。
你的Python应用程序负责完成准备工作。
API为AI模型提供了访问权限。
文件本身包含了所需的信息。
指令明确了AI系统需要执行的任务。
用户提出问题,AI系统进行处理。
模型分析信息后生成相应的答案。
真正有趣的部分在于后续的发展过程。
一旦你掌握了如何让AI模型访问文件,就可以开始添加检索功能、数据库、网络搜索机制、用户界面以及多步骤工作流程。
正是这些元素,使得简单的AI脚本能够发展成真正的应用程序。
最棒的是:在开始构建之前,你并不需要完全了解所有的AI技术细节。
从小处入手,先让系统能处理一个文件,回答一个问题,弄清楚每一行代码的作用,然后再逐步添加新的功能。
这样,你就会从“我想构建一个AI系统”变成“我真的构建出了一个AI系统”。
祝编程愉快!
相关文章
如何修复泄露的API密钥:开发人员必备的Git安全指南
想象一下这样的场景:你工作到很晚,终于让代码运行成功了,准备将其推送到GitHub上。 你执行了以下操作: git add . git commit -m "修复API集成问题" git push 几分钟后,你发现了一些异常现象:API的使用量突然增加了。可能是出现了意外的请求、新的云资源被使用了,甚至账单金额也比预期要高得多。 然后你发现了问题的根源: const apiKey = "sk_live_123456789"; 你的API密钥竟然被保存在Git仓库中去了。 这种情况确实很令人紧张,但也是可以解决的。 最重要的一点是: 如果API密钥已经被提交到了Git仓库中,那么即使你立即将其删
阅读全文
如何利用WCAG 2.2标准打造更加易于访问的网站
一个网站可能看起来很专业,使用鼠标操作时也能运行得非常顺畅,但对某些用户来说,使用它仍然会遇到困难。 有时,某个表单会仅通过颜色来提示用户出现了问题;固定的页眉可能会完全覆盖当前处于键盘焦点位置的元素;登录表单可能会阻止用户从密码管理工具中复制密码并粘贴到表单中;而某个自定义按钮,用鼠标点击时可以正常使用,但当人们使用键盘操作时却毫无反应。 这些其实都是开发过程中做出的决策,并非只有在进行无障碍性审核时才会出现的问题。 《Web内容无障碍性指南》为识别和消除这些障碍提供了统一的标准。WCAG 2.2是最新的WCAG 2建议标准,世界万维网联盟也建议开发人员和各类组织在可能的情况下使用WCAG
阅读全文
如何使用 Shadcn UI 在 React 中构建可扩展的客户身份验证及入职流程
任何具有合规性要求的B2B SaaS产品(比如涉及银行业务、贷款服务、工资发放或加密货币相关的应用)在开发初期都会遇到同样的问题:在允许企业使用你的平台之前,你必须先核实他们的身份。 这意味着需要收集企业的类型信息、审核他们的注册文件,并向用户展示他们的验证进度,但整个流程不能让人感觉像是在填写繁琐的海关表格一样。 本文详细介绍了如何利用Shadcn UI构建一个功能完备的三步客户身份验证流程:包括用于显示操作进度的步骤提示组件、用于选择账户类型的单选组、用于上传文件的区域,以及用于显示验证状态的警告提示。你会看到实际的代码实现,而不仅仅是简化后的示例代码,同时也会了解到每个设计决策背后的理由
阅读全文
如何使用针对用户的OAuth访问机制来构建人工智能代理程序【完整手册】
当你的AI代理同时为多个人提供服务时,每一次工具调用都必须明确:该代理究竟是在代表哪位用户行事。让我们通过构建一个能够与Slack和GitHub连接的AI代理来学习如何解决这个问题。 当使用Slack时,系统会使用 해당用户的 workspace;而在GitHub上创建问题时,也会以该用户的身份在其有权访问的仓库中操作。虽然代理可能会犯错,但它绝对不能使用错误用户的权限来进行操作。 解决这个问题的方法分为两个部分,而这两个部分都在本教程的前半部分进行了讲解: 每位用户都需要单独授权。 Alice为自己授权Slack,Bob也为自己授权Slack。 代理传递的是标识符,而不是令牌。 像 alic
阅读全文