从零开始搭建AI智能体团队:Python+LangChain实战教程(建议收藏)
本文详解了使用Python和LangChain构建多AI智能体团队的方法,包括问候、协调、搜索、内容抓取和摘要生成等模块。通过完整代码实现,展示了如何利用Hugging Face免费模型和DuckDuckGo工具创建自动搜索网络信息并生成摘要的系统,同时讨论了局限性与优化方向,为读者提供构建多智能体AI系统的完整指导。
你是否想过,如何让多个AI“专家”协同完成一项任务?今天,我们将使用Python和功能强大的LangChain框架搭建一个小型AI智能体团队。我们的目标是创建一个具备以下功能的系统:
- • agentHello(问候智能体):向你打招呼并获取你的名字。
- • agentInterpreter(协调智能体):担任主要协调者角色,会询问你想要研究的主题,随后调用另一个智能体查找相关网站,再让你选择一个网站并确认是否需要生成摘要。
- • agentWebSearcher(网络搜索智能体):针对你选择的主题全网搜索信息,并推荐相关URL链接。
- • agentSummarizer(摘要生成智能体):获取选定网页的内容,并生成简洁的摘要。
整个流程大致如下:agentHello(问候)→ agentInterpreter(获取研究主题)→ agentWebSearcher(查找URL)→ agentInterpreter(用户选择URL并确认是否生成摘要)→ agentContentFetcher(获取网页内容)→ agentSummarizer(生成摘要)→ agentInterpreter(展示摘要)。
我们将重点使用LangChain实现“AI相关”功能,并尽量采用免费工具,例如用DuckDuckGo进行网络搜索,用Hugging Face Hub的模型完成大语言模型(LLM)相关任务。
准备好组建你的AI团队了吗?让我们开始编码吧!
一、所需工具(你的工具箱)
-
- 已安装Python 3.8及以上版本。
-
- LangChain及相关支持库,安装命令如下(Bash终端):
pip install langchain langchain-community langchain-huggingface duckduckgo-search beautifulsoup4 sentence-transformers
- •
langchain_huggingface
:用于调用Hugging Face的模型。 - •
duckduckgo-search
:作为我们的网络搜索工具。 - •
beautifulsoup4
:供WebBaseLoader使用,用于解析HTML内容。 - •
sentence-transformers
:部分Hugging Face模型的分词器可能需要该库,或摘要生成、文本分割工具会隐式调用它。
-
- Hugging Face API令牌:我们将使用Hugging Face Hub中的模型,因此需要一个免费的Hugging Face账号和API令牌,获取步骤如下:
- • 访问huggingface.co,创建账号(若尚未拥有)。
- • 进入“Settings(设置)”→“Access Tokens(访问令牌)”→“New token(新建令牌)”,为令牌命名(例如“langchain-tutorial”),权限选择“read(只读)”通常即可。
- • 复制生成的令牌,将其设置为环境变量
HUGGINGFACEHUB_API_TOKEN
。
二、步骤1:配置环境与API密钥
使用环境变量管理API密钥是最佳实践,具体操作如下:
-
- 在项目根目录创建一个名为
.env
的文件(若使用Git,需将.env
添加到.gitignore
文件中,避免令牌泄露),文件内容如下:
HUGGINGFACEHUB_API_TOKEN="your_hf_xxxxxxxxxxxxxxxxxxxx_token_here"
- 在项目根目录创建一个名为
-
- 在Python脚本中,使用
python-dotenv
库加载该环境变量(需先安装:pip install python-dotenv
),代码如下:
import os from dotenv import load_dotenv load_dotenv() # (可选,用于验证)检查令牌是否加载成功 # hf_token = os.getenv("HUGGINGFACEHUB_API_TOKEN") # if not hf_token: # print("未找到Hugging Face API令牌!请在.env文件或环境变量中设置。") # exit()
- 在Python脚本中,使用
本教程中,请确保HUGGINGFACEHUB_API_TOKEN
已通过某种方式配置到你的环境中。
三、步骤2:agentHello——友好的问候者👋(简单Python函数)
这个智能体不需要复杂的AI功能,仅用于提供温暖的问候:
def agent_hello():
"""向用户打招呼并获取用户名。"""
print("🤖 你好!我是你的AI助手团队负责人。")
user_name = input("请问你叫什么名字? ")
print(f"👋 很高兴认识你,{user_name}!")
return user_name
四、步骤3:agentWebSearcher——信息侦察员🕵️♂️
该智能体接收一个研究主题,通过DuckDuckGo进行搜索,再利用简单的LLM链从搜索结果文本中提取几个相关URL。我们将使用Hugging Face Hub中的免费模型实现这一功能,代码如下:
from langchain_community.tools import DuckDuckGoSearchRun
from langchain_huggingface import HuggingFaceHub # 已更新的导入语句
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
import re # 用于解析URL
# 从Hugging Face Hub初始化LLM
# 我们选择一个体积较小、适合简单任务的免费模型
# 请确保环境中已设置HUGGINGFACEHUB_API_TOKEN!
repo_id = "google/flan-t5-base" # 优秀的通用模型
# 可选模型(注:以下模型可能有使用限制或需要专业订阅才能大量使用):
# repo_id = "mistralai/Mixtral-8x7B-Instruct-v0.1" # 功能更强
# repo_id = "NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO" # 另一个可选模型
# 检查令牌是否存在,若不存在则提示用户
if not os.getenv("HUGGINGFACEHUB_API_TOKEN"):
print("⚠️ 未找到Hugging Face API令牌,请设置HUGGINGFACEHUB_API_TOKEN环境变量。")
print("本演示中,依赖LLM的功能将受到限制。")
llm = None
else:
try:
llm = HuggingFaceHub(
repo_id=repo_id,
model_kwargs={"temperature": 0.7, "max_length": 128} # flan-t5-base的max_length最大约为512
)
print(f"✅ 已从Hugging Face Hub成功加载LLM模型({repo_id})。")
except Exception as e:
print(f"⚠️ 从Hugging Face Hub加载LLM时出错:{e}")
print("依赖LLM的功能将受到限制。")
llm = None
# 初始化搜索工具
search_tool = DuckDuckGoSearchRun()
# 仅当LLM加载成功时,初始化URL提取链
url_extraction_chain = None
if llm:
prompt_template_str = """
根据以下网络搜索结果文本,请提取最多3个唯一且相关的URL。
每个URL单独占一行,仅提供URL即可。
搜索结果文本:
{search_results_text}
提取的URL:
"""
url_prompt = PromptTemplate.from_template(prompt_template_str)
url_extraction_chain = LLMChain(llm=llm, prompt=url_prompt)
def agent_web_searcher(topic: str, max_urls=3) -> list:
"""
根据主题搜索网络并提取相关URL。
返回URL字符串列表。
"""
print(f"\n🔎 正在网络上搜索主题:'{topic}'...")
try:
raw_search_results = search_tool.run(topic)
except Exception as e:
print(f" 网络搜索过程中遇到错误:{e}")
return []
if not raw_search_results:
print(" 未从网络搜索到结果。")
return []
print(f"📚 原始搜索结果(前500个字符):{raw_search_results[:500]}...")
if url_extraction_chain: # 若LLM已加载且提取链已创建
try:
print("🤖 正在请求LLM从搜索结果中提取URL...")
extracted_text = url_extraction_chain.run({"search_results_text": raw_search_results})
# 从LLM的响应中解析URL(注:此正则表达式较简单,实际URL可能更复杂)
found_urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', extracted_text)
# 去重并保留原始顺序(适用于Python 3.7及以上版本)
unique_urls = list(dict.fromkeys(found_urls))
print(f"🔗 提取的URL:{unique_urls[:max_urls]}")
return unique_urls[:max_urls]
except Exception as e:
print(f" 使用LLM提取URL时出错:{e}")
print(" 正在尝试备用提取方式,或可能需要手动输入。")
# 备用方案:若LLM提取失败,直接从原始搜索结果中查找URL
found_urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', raw_search_results)
unique_urls = list(dict.fromkeys(found_urls))
if unique_urls:
print(f"🔗 备用方案——从搜索结果中直接找到的URL:{unique_urls[:max_urls]}")
return unique_urls[:max_urls]
else:
print("无法通过LLM或备用方案提取URL。")
return []
else:
# 备用方案:若LLM不可用,直接从原始搜索结果中查找URL
print("用于提取URL的LLM不可用,正在尝试基础提取方式...")
found_urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', raw_search_results)
unique_urls = list(dict.fromkeys(found_urls))
if unique_urls:
print(f"🔗 备用方案——从搜索结果中直接找到的URL:{unique_urls[:max_urls]}")
return unique_urls[:max_urls]
else:
print("无法通过基础提取方式获取URL。")
return []
五、步骤4:agentContentFetcher——网页内容抓取者🕸️
该智能体使用LangChain的WebBaseLoader从指定URL中获取文本内容,代码如下:
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
def agent_content_fetcher(url: str):
"""从指定URL获取内容并进行分割。"""
print(f"\n🌎 正在从以下URL获取内容:{url}...")
try:
loader = WebBaseLoader(web_paths=(url,))
# (可选)若某些网站加载异常,可添加错误处理或超时设置
docs = loader.load()
if not docs:
print("无法从该URL获取任何内容。")
return None
print(f"📄 内容获取成功,文档数量:{len(docs)}")
# 合并所有文档的内容(WebBaseLoader可能会按标签分割内容)
full_content = "\n".join([doc.page_content for doc in docs])
# 分割文本,以便摘要生成工具更易处理
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=4000, # 可根据LLM的上下文窗口和摘要策略调整
chunk_overlap=200
)
split_docs = text_splitter.create_documents([full_content])
print(f"✂️ 内容已分割为{len(split_docs)}个片段,用于后续摘要生成。")
return split_docs # 返回Document对象列表
except Exception as e:
print(f"从{url}获取或分割内容时出错:{e}")
return None
六、步骤5:agentSummarizer——内容浓缩者📝
该智能体接收LangChain Document格式的抓取内容,使用load_summarize_chain
生成摘要,代码如下:
from langchain.chains.summarize import load_summarize_chain
# 复用步骤3中初始化的llm实例
# 若llm为None,则无法进行摘要生成
def agent_summarizer(documents, url: str):
"""对获取的内容生成摘要。"""
if not llm:
print("\n⚠️ LLM不可用,跳过摘要生成步骤。")
return "因LLM不可用,已跳过摘要生成。"
if not documents:
print("\n⚠️ 未提供待摘要的文档,跳过摘要生成步骤。")
return "因未提供内容,已跳过摘要生成。"
print(f"\n✍️ 正在为以下URL的内容生成摘要:{url}...")
# 链类型说明:
# "map_reduce":适合较长文档,先分别处理片段再整合
# "stuff":更简单,但处理长文档时可能超出LLM上下文限制
# "refine":另一种可选类型,适合逐步优化摘要
# 考虑到Flan-T5的上下文窗口较小,对任意网页内容使用"map_reduce"更安全
chain_type = "map_reduce"
try:
summarize_chain = load_summarize_chain(llm, chain_type=chain_type)
summary = summarize_chain.run(documents) # 若使用较新版本LangChain,可替换为.invoke
# 较新版本LangChain(0.1.x及以上)推荐用法:
# summary = summarize_chain.invoke({"input_documents": documents}, return_only_outputs=True)["output_text"]
print(f"\n✅ 摘要生成完成!")
return summary
except Exception as e:
print(f" 生成摘要时出错:{e}")
return "因错误导致无法生成摘要。"
七、步骤6:agentInterpreter——指挥者与用户界面🗣️
这是整个应用的核心,负责根据用户输入协调其他智能体的调用,代码如下:
def agent_interpreter(user_name: str):
"""
协调智能体交互,根据用户输入调用其他智能体。
"""
print(f"\n好了,{user_name},我们开始吧!")
while True:
topic = input("➡️ 你今天想研究哪个主题或网站?(输入'quit'退出): ")
if topic.lower() == 'quit':
break
suggested_urls = agent_web_searcher(topic)
if not suggested_urls:
print("未找到与该主题相关的具体URL,请尝试其他主题。")
continue
print("\n以下是为你找到的相关URL:")
for i, url in enumerate(suggested_urls):
print(f" {i+1}. {url}")
while True:
try:
choice_num_str = input(f"➡️ 请输入你想处理的URL编号(1-{len(suggested_urls)}),或输入's'重新搜索,或输入'q'退出当前主题: ")
if choice_num_str.lower() == 'q':
break # 退出内层循环,回到主题选择或退出流程
if choice_num_str.lower() == 's':
# 退出内层循环,回到外层循环重新选择主题
print("那我们重新搜索一个主题吧。")
return # 退出当前interpreter调用,主循环会根据需求重启
choice_num = int(choice_num_str)
if 1 <= choice_num <= len(suggested_urls):
chosen_url = suggested_urls[choice_num - 1]
print(f"你选择的URL:{chosen_url}")
summarize_decision = input(f"➡️ 是否需要我获取该URL的内容并生成摘要?(yes/no): ").lower()
if summarize_decision == 'yes':
documents_to_summarize = agent_content_fetcher(chosen_url)
if documents_to_summarize:
summary = agent_summarizer(documents_to_summarize, chosen_url)
print("\n--- 摘要 ---")
print(summary)
print("--- 摘要结束 ---")
else:
print(f"抱歉,无法从{chosen_url}获取内容以生成摘要。")
else:
print("好的,不生成该URL的摘要。")
another_url_choice = input("➡️ 是否需要处理本次搜索结果中的其他URL?(yes/no): ").lower()
if another_url_choice != 'yes':
break # 退出内层URL选择循环,回到主题选择或退出流程
else:
print("编号无效,请从列表中选择。")
except ValueError:
print("输入无效,请输入数字、's'或'q'。")
except Exception as e:
print(f"发生意外错误:{e}")
break # 安全退出,避免程序崩溃
another_topic_choice = input(f"\n➡️ {user_name},是否想研究其他主题?(yes/no): ").lower()
if another_topic_choice != 'yes':
break # 退出外层循环,结束交互
print(f"\n希望这个AI团队对你有帮助,{user_name}!再见啦~ 👋")
八、步骤7:整合所有模块——主流程🚀
创建主函数,按顺序运行所有智能体,代码如下:
def main():
user_name = agent_hello()
if user_name: # 若用户提供了名字,则继续
agent_interpreter(user_name)
if __name__ == "__main__":
main()
九、工作原理与“智能体”核心特性
-
- agentHello:基于简单Python代码,用于营造友好的交互氛围。
-
- agentWebSearcher:
- • 使用LangChain的
DuckDuckGoSearchRun
工具实现搜索功能。 - • 结合LangChain的
LLMChain
、PromptTemplate
和HuggingFaceHub LLM完成“AI任务”:从非结构化文本(搜索结果)中提取结构化信息(URL),这是典型的智能体核心步骤。
-
- agentContentFetcher:
- • 使用LangChain的
WebBaseLoader
(文档加载器)从外部来源获取数据。 - • 使用LangChain的
RecursiveCharacterTextSplitter
(文本分割器)为LLM预处理数据。
-
- agentSummarizer:
- • 使用LangChain的
load_summarize_chain
(预构建摘要链),该链专为摘要生成设计,由HuggingFaceHub LLM提供动力。
-
- agentInterpreter:
- • 这个Python函数充当“指挥者”,自身不依赖LLM做决策(为简化流程并避免基础流程控制产生LLM成本),但会调用其他依赖LLM的组件,同时管理用户交互流程。
这套系统展示了一个基础的多组件架构:部分组件依赖AI(使用LLM和LangChain抽象层),部分组件则基于简单Python逻辑实现。
十、当前局限与AI团队的优化方向
-
- 免费LLM性能:
google/flan-t5-base
这类免费模型虽易获取,但在处理复杂任务(如从杂乱文本中提取URL、生成高质量流畅摘要)时,性能和细腻度可能不及大型商用模型,且上下文窗口较小。
- 免费LLM性能:
-
- 错误处理:当前错误处理仅为基础级别,实际应用需更健壮的错误管理机制。
-
- URL提取可靠性:基于LLM的URL提取思路可行,但效果受LLM能力和搜索结果页面复杂度影响;备用的正则表达式提取方式也较为基础。
-
- 缺乏复杂智能体交互的“状态”管理:当前“协调者”(agentInterpreter)通过函数调用管理流程,若需实现更复杂的状态化对话或智能体动态任务委派,可引入:
- • LangGraph:LangChain旗下用于构建状态化多智能体应用的库,支持循环流程、显式状态管理和复杂状态转换,是实现“真正多智能体系统”的理想工具。
-
- 网页内容抓取问题:
WebBaseLoader
功能强大,但部分网站可能拦截爬虫、使用复杂JavaScript渲染或要求登录,导致抓取失败。
- 网页内容抓取问题:
-
- 用户界面:当前为命令行应用,可使用Streamlit或Gradio为其封装简单的可视化界面。
十一、结语:你的首个AI团队已组建完成!🎉
恭喜你!你已设计并(有望)运行了一个基于LangChain的多组件AI系统。你学会了如何将简单Python函数与LangChain的高级组件(工具、文档加载器、LLM链、预构建摘要链)结合,且全程使用免费可获取的资源。
这个项目是绝佳的起点,你可以思考如何优化每个“智能体”、增强协调逻辑(例如引入LangGraph),或为AI团队添加新能力。多智能体系统的领域广阔且充满活力,未来可期!
普通人如何抓住AI大模型的风口?
领取方式在文末
为什么要学习大模型?
目前AI大模型的技术岗位与能力培养随着人工智能技术的迅速发展和应用 , 大模型作为其中的重要组成部分 , 正逐渐成为推动人工智能发展的重要引擎 。大模型以其强大的数据处理和模式识别能力, 广泛应用于自然语言处理 、计算机视觉 、 智能推荐等领域 ,为各行各业带来了革命性的改变和机遇 。
目前,开源人工智能大模型已应用于医疗、政务、法律、汽车、娱乐、金融、互联网、教育、制造业、企业服务等多个场景,其中,应用于金融、企业服务、制造业和法律领域的大模型在本次调研中占比超过 30%。
随着AI大模型技术的迅速发展,相关岗位的需求也日益增加。大模型产业链催生了一批高薪新职业:
人工智能大潮已来,不加入就可能被淘汰。如果你是技术人,尤其是互联网从业者,现在就开始学习AI大模型技术,真的是给你的人生一个重要建议!
最后
只要你真心想学习AI大模型技术,这份精心整理的学习资料我愿意无偿分享给你,但是想学技术去乱搞的人别来找我!
在当前这个人工智能高速发展的时代,AI大模型正在深刻改变各行各业。我国对高水平AI人才的需求也日益增长,真正懂技术、能落地的人才依旧紧缺。我也希望通过这份资料,能够帮助更多有志于AI领域的朋友入门并深入学习。
真诚无偿分享!!!
vx扫描下方二维码即可
加上后会一个个给大家发
大模型全套学习资料展示
自我们与MoPaaS魔泊云合作以来,我们不断打磨课程体系与技术内容,在细节上精益求精,同时在技术层面也新增了许多前沿且实用的内容,力求为大家带来更系统、更实战、更落地的大模型学习体验。
希望这份系统、实用的大模型学习路径,能够帮助你从零入门,进阶到实战,真正掌握AI时代的核心技能!
01 教学内容
-
从零到精通完整闭环:【基础理论 →RAG开发 → Agent设计 → 模型微调与私有化部署调→热门技术】5大模块,内容比传统教材更贴近企业实战!
-
大量真实项目案例: 带你亲自上手搞数据清洗、模型调优这些硬核操作,把课本知识变成真本事!
02适学人群
应届毕业生: 无工作经验但想要系统学习AI大模型技术,期待通过实战项目掌握核心技术。
零基础转型: 非技术背景但关注AI应用场景,计划通过低代码工具实现“AI+行业”跨界。
业务赋能突破瓶颈: 传统开发者(Java/前端等)学习Transformer架构与LangChain框架,向AI全栈工程师转型。
vx扫描下方二维码即可
本教程比较珍贵,仅限大家自行学习,不要传播!更严禁商用!
03 入门到进阶学习路线图
大模型学习路线图,整体分为5个大的阶段:
04 视频和书籍PDF合集
从0到掌握主流大模型技术视频教程(涵盖模型训练、微调、RAG、LangChain、Agent开发等实战方向)
新手必备的大模型学习PDF书单来了!全是硬核知识,帮你少走弯路(不吹牛,真有用)
05 行业报告+白皮书合集
收集70+报告与白皮书,了解行业最新动态!
06 90+份面试题/经验
AI大模型岗位面试经验总结(谁学技术不是为了赚$呢,找个好的岗位很重要)
07 deepseek部署包+技巧大全
由于篇幅有限
只展示部分资料
并且还在持续更新中…
真诚无偿分享!!!
vx扫描下方二维码即可
加上后会一个个给大家发
更多推荐
所有评论(0)