文章目录
-
- 前言
- 1. 整个架子先搭起来
-
- 1.1 流程图长这样
- 1.2 有一个大坑,先给你们挖出来
- 2. 让 Agent 学会"看图说话"
-
- 2.1 代码就这么几行
- 2.2 这玩意儿真实用处在哪
- 3. PDF 这玩意儿,是文档界的泥石流
-
- 3.1 PDF 分三种,命运各不相同
- 3.2 解析代码,拿走不谢
- 3.3 几个踩过的坑,免费送你
- 4. Excel/CSV:让 Agent 学会算账
-
- 4.1 核心代码
- 5. 让 Agent 学会画图
-
- 5.1 代码长这样
- 6. 把这些零件拼成一台机器
-
- 6.1 完整工作流代码
- 7. 真上生产,还有五件事得想清楚
-
- 7.1 在线和离线必须分家
- 7.2 视觉模型是真贵
- 7.3 OCR 结果要加一道人工审核
- 7.4 文件安全别偷懒
- 7.5 生态已经成熟了
P.S. 推荐一个大神的教程给想要了解或者学习人工智能知识的读者,这个教程里内容讲解通俗易懂且风趣幽默,对我帮助很大。我想与大家分享这个宝藏教程,请点击下方链接查看,
传送门https://blog.csdn.net/qq_74013365
前言
先吐槽一句:以前我们说 Agent,那叫"文字劳动力",你问它答,跟客服机器人似的,除了话多没什么本事。
这回不一样了,得让它长眼睛、长手、长计算器。不然你发张图过去,它只能回你一句"抱歉,我看不见",那感觉跟给你奶奶发微信视频通话是一样的——她接起来喊的第一句永远是:“喂?你说啥?我听不清!”
1. 整个架子先搭起来
思路其实不复杂:模型负责"看懂",LangGraph 负责"调度",工具负责"下苦活"。
别一上来就想让它十八般武艺全会,那不叫 Agent,那叫你妈——你妈才是又能看孩子、又能修水管、还能顺便把你骂一顿的全能选手。
1.1 流程图长这样
用户输入(文字 + 图片/文件)
↓
路由节点(判断模态)
↓
┌────┴─────────────────────┐
│ 图片 → 视觉分析节点 │
│ PDF → 文档解析节点 │
│ Excel→ 数据分析节点 │
│ 画图 → 图像生成节点 │
└──────────────────────────┘
↓
整合节点(汇总结果输出)
1.2 有一个大坑,先给你们挖出来
在线问答和离线入库必须分开。
什么意思?你让用户对着一个 200 页的扫描件等 OCR,等个三五分钟,他早关页面去刷短视频了。人类的耐心现在跟手机电量一样,20% 以下就开始焦虑。
2. 让 Agent 学会"看图说话"
以前你跟模型说"这张图里有啥",它的反应相当于你把试卷递到一个闭着眼的人面前。现在好了,换个支持视觉的模型,把图片转成 Base64 直接喂过去,它就真能瞅了。
2.1 代码就这么几行
import base64
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm_vision = ChatOpenAI(model="gpt-4o", temperature=0)
def encode_image(path: str) –> str:
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
def analyze_image(image_path: str, question: str) –> str:
"""让模型看图并回答问题"""
b64 = encode_image(image_path)
message = HumanMessage(content=[
{"type": "text", "text": question},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}}
])
return llm_vision.invoke([message]).content
# 示例
result = analyze_image("factory_equipment.jpg", "这台设备有没有潜在故障?")
2.2 这玩意儿真实用处在哪
工厂巡检拍个照,让模型看设备有没有异常;前端小哥截个图,让模型帮你定位 bug;设计师出稿,让模型先过一遍。
你品品,以前这些活谁干?测试同学干,一天看几百张图,看到最后他眼里代码和外卖订单都长一样。
3. PDF 这玩意儿,是文档界的泥石流
我跟你讲,做技术这么多年,什么格式都能忍,就是 PDF 不能忍。它表面上是"通用文档",实际上是"谁打开谁傻眼"。
3.1 PDF 分三种,命运各不相同
| 原生文本 PDF | 可直接复制文字 | PyPDF2 / pdfplumber 直接提取 |
| 扫描版 PDF | 本质是图片 | OCR(PaddleOCR / Tesseract) |
| 混合 PDF | 文字+图表混排 | 分层提取:文字走文本,图表走 OCR |
最绝的是那种扫描版 PDF——你右键复制,复制出来一段空白,仿佛在跟空气对话。这种文件你发给产品经理,他还会回你一句:“哎,我这边能打开啊。”
3.2 解析代码,拿走不谢
import pdfplumber
from PIL import Image
import pytesseract
def parse_pdf(pdf_path: str) –> str:
"""解析 PDF,自动判断是否需要 OCR"""
full_text = []
with pdfplumber.open(pdf_path) as pdf:
for i, page in enumerate(pdf.pages):
# 1. 尝试提取文本
text = page.extract_text() or ""
# 2. 如果文本太少,可能是扫描件,走 OCR
if len(text.strip()) < 50:
image = page.to_image(resolution=200)
ocr_text = pytesseract.image_to_string(
image.original, lang="chi_sim+eng"
)
text = ocr_text
# 3. 提取表格(转成 Markdown)
tables = page.extract_tables()
table_text = ""
for table in tables:
if table:
header = "| " + " | ".join(table[0]) + " |"
sep = "| " + " | ".join(["—"] * len(table[0])) + " |"
rows = "\\n".join(
"| " + " | ".join(row) + " |" for row in table[1:]
)
table_text += f"\\n{header}\\n{sep}\\n{rows}\\n"
full_text.append(f"— 第 {i+1} 页 —\\n{text}\\n{table_text}")
return "\\n".join(full_text)
3.3 几个踩过的坑,免费送你
第一,多栏排版的 PDF,提取出来的文字顺序是乱的,它能把左边一栏第三段接到右边一栏第一段后面,比你周一早上的脑子还混乱。
第二,表格提取是老大难,pdfplumber 和 camelot 得搭配着用,跟中医开方子似的,单味药治不好病。
第三,大文件千万别一股脑塞给模型,它没崩,你钱包先崩了。
4. Excel/CSV:让 Agent 学会算账
很多团队里有个角色叫"数据分析师",其实主要工作不是分析,是"把老板发的那张图里的数据再核一遍"。
现在让 Agent 干这活,思路就一条:先转成结构化数据,再交给代码解释器或者模型去算。别上来就让模型看 Excel,它看 Excel 跟你看股票 K 线一样——图是清楚的,钱是没的。
4.1 核心代码
import pandas as pd
def analyze_excel(file_path: str, question: str) –> str:
"""分析 Excel/CSV 文件"""
# 1. 读取文件
if file_path.endswith(".csv"):
df = pd.read_csv(file_path)
else:
df = pd.read_excel(file_path)
# 2. 生成数据摘要(让模型了解数据结构)
summary = {
"shape": df.shape,
"columns": list(df.columns),
"dtypes": df.dtypes.astype(str).to_dict(),
"sample": df.head(3).to_dict(orient="records"),
"describe": df.describe().to_dict(),
}
# 3. 让模型基于摘要决定下一步操作
prompt = f"""你是数据分析师。基于以下数据摘要,回答用户问题。
如果需要进行计算或绘图,请输出 Python 代码。
数据摘要:{summary}
用户问题:{question}
回答或输出可执行的 Python 代码。"""
response = llm.invoke(prompt).content
# 如果返回代码,交给代码解释器执行
return response
配上代码解释器之后,它能自己画折线图、柱状图,甚至给你整一个数据透视表。听起来很爽是吧?
是很爽,直到它给你算错了一个数,然后一本正经地输出:"根据分析,贵公司今年利润率为 1200%。"老板看完激动得差点给你涨工资,你吓得连夜改报表。
5. 让 Agent 学会画图
以前做产品,写完文案想配图,得打开设计网站,搜半小时,下素材,抠图,加水印,最后用了一张去年国庆的图。
现在直接调 DALL·E 3 或者 Stable Diffusion,一句话的事。
5.1 代码长这样
from openai import OpenAI
client = OpenAI()
def generate_image(prompt: str, size: str = "1024×1024") –> str:
"""生成图片并返回 URL"""
response = client.images.generate(
model="dall-e-3",
prompt=prompt,
size=size,
quality="standard",
n=1,
)
return response.data[0].url
# 作为 Agent 工具注册
image_gen_tool = {
"name": "generate_image",
"description": "根据文字描述生成图片",
"parameters": {
"type": "object",
"properties": {
"prompt": {"type": "string", "description": "图片描述"}
},
"required": ["prompt"]
}
}
写诗配图、产品概念图、营销海报草图,都能整。
但友情提示:它画出来的东西,经常有一种"梦境般的超现实感"。你让它画一只猫,它能给你画出来一只六条腿、尾巴分叉、眼神深邃的猫。你拿去给老板看,老板说:"嗯,有创意。"你心里想:这是 bug,不是创意。
6. 把这些零件拼成一台机器
前面都是零件,现在用 LangGraph 把它们串起来。
别害怕,这玩意儿不是让你学什么新框架,本质上就是画流程图——只不过以前你是在白板上画,现在是在代码里画。画完一跑,流程就自己转起来了。
6.1 完整工作流代码
from typing import TypedDict, Optional
from langgraph.graph import StateGraph, END
class MultiModalState(TypedDict):
query: str
image_path: Optional[str]
file_path: Optional[str]
parsed_content: str
analysis_result: str
final_output: str
def router_node(state: MultiModalState) –> str:
"""根据输入类型路由到不同处理节点"""
if state.get("image_path"):
return "vision"
elif state.get("file_path"):
ext = state["file_path"].split(".")[–1].lower()
if ext in ("pdf",):
return "document"
elif ext in ("xlsx", "xls", "csv"):
return "spreadsheet"
return "text_only"
def vision_node(state: MultiModalState) –> MultiModalState:
result = analyze_image(state["image_path"], state["query"])
return {"analysis_result": result}
def document_node(state: MultiModalState) –> MultiModalState:
# 截断后交给模型总结
prompt = f"请总结以下文档内容,回答用户问题:{state['query']}\\n\\n{content[:15000]}"
result = llm.invoke(prompt).content
return {"analysis_result": result}
def spreadsheet_node(state: MultiModalState) –> MultiModalState:
# 调用前面的 Excel 分析逻辑
result = analyze_excel(state["file_path"], state["query"])
return {"analysis_result": result}
def text_only_node(state: MultiModalState) –> MultiModalState:
result = llm.invoke(state["query"]).content
return {"analysis_result": result}
def integrate_node(state: MultiModalState) –> MultiModalState:
return {"final_output": state["analysis_result"]}
# 构建图
workflow = StateGraph(MultiModalState)
workflow.add_node("router", router_node)
workflow.add_node("vision", vision_node)
workflow.add_node("document", document_node)
workflow.add_node("spreadsheet", spreadsheet_node)
workflow.add_node("text_only", text_only_node)
workflow.add_node("integrate", integrate_node)
workflow.set_entry_point("router")
workflow.add_conditional_edges("router", router_node, {
"vision": "vision",
"document": "document",
"spreadsheet": "spreadsheet",
"text_only": "text_only",
})
for node in ["vision", "document", "spreadsheet", "text_only"]:
workflow.add_edge(node, "integrate")
workflow.add_edge("integrate", END)
app = workflow.compile()
# 使用示例
result = app.invoke({
"query": "这份财报的核心数据是什么?",
"file_path": "financial_report.pdf",
})
print(result["final_output"])
跑起来之后你会发现,这玩意儿跟你公司的组织架构图长得几乎一样:一个路由节点当老板,下面四个部门各干各的,最后一个整合节点当秘书,把结果汇总给你。
唯一的区别是——这台机器不会请假,不会要年终奖,也不会在周五下午三点问你"周末要不要一起聚一下"。
7. 真上生产,还有五件事得想清楚
7.1 在线和离线必须分家
文档入库走异步:OCR、校验、分块、向量化,一步一步来。在线问答只查已经索引好的结果。别让用户等,用户不是你对象,不会跟你耗。
7.2 视觉模型是真贵
先做预处理:裁剪、压缩、能 OCR 转文本的就别让视觉模型看。不然你跑一个月,账单寄过来,你以为公司被黑客入侵了。
7.3 OCR 结果要加一道人工审核
低置信度的结果别直接入库,不然你向量库里全是"二零二三年营收壹亿贰仟万元整"被识别成"二零二三年营收壹亿贰任元整"这种东西。
7.4 文件安全别偷懒
上传的文件要做类型校验、大小限制、病毒扫描。你永远不知道用户会传上来什么——可能是一份财报,也可能是一个伪装成 PDF 的可执行文件。互联网上什么人都有,就跟小区业主群一样。
7.5 生态已经成熟了
2026 年了,LangGraph 已经原生支持多模态 Agent 编排,Deep Agents 框架也把多模态能力加进来了。别再自己从零撸轮子了,你撸不过社区的,就跟你在家做饭永远比不过外卖小哥送得快一个道理。
行,就唠到这。多模态这事儿,说白了就是让 Agent 从"只会打字的文员"进化成"能看图、能算账、能画图的实习生"。
实习生还会犯错,Agent 也会。但它胜在不抱怨、不摸鱼、不请假——只要你别把账单看了。
P.S. 推荐一个大神的教程给想要了解或者学习人工智能知识的读者,这个教程里内容讲解通俗易懂且风趣幽默,对我帮助很大。我想与大家分享这个宝藏教程,请点击下方链接查看,传送门https://blog.csdn.net/qq_74013365
网硕互联帮助中心




评论前必须登录!
注册