你是否想过,如何让多个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团队了吗?让我们开始编码吧!
在这里插入图片描述

一、所需工具(你的工具箱)

    1. 已安装Python 3.8及以上版本。
    1. 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模型的分词器可能需要该库,或摘要生成、文本分割工具会隐式调用它。
    1. 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密钥是最佳实践,具体操作如下:

    1. 在项目根目录创建一个名为.env的文件(若使用Git,需将.env添加到.gitignore文件中,避免令牌泄露),文件内容如下:
    HUGGINGFACEHUB_API_TOKEN="your_hf_xxxxxxxxxxxxxxxxxxxx_token_here"
    
    1. 在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()
    

本教程中,请确保HUGGINGFACEHUB_API_TOKEN已通过某种方式配置到你的环境中。

三、步骤2:agentHello——友好的问候者👋(简单Python函数)

这个智能体不需要复杂的AI功能,仅用于提供温暖的问候:

def agent_hello():
    """向用户打招呼并获取用户名。"""
    print("🤖 你好!我是你的AI助手团队负责人。")
    user_name = input("请问你叫什么名字? ")
    print(f"👋 很高兴认识你,{user_name}!")
    return user_name

一直在更新,更多的大模型学习和面试资料已经上传带到CSDN的官方了,有需要的朋友可以扫描下方二维码免费领取【保证100%免费】👇👇

在这里插入图片描述
四、步骤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()

九、工作原理与“智能体”核心特性

    1. agentHello:基于简单Python代码,用于营造友好的交互氛围。
    1. agentWebSearcher
  • • 使用LangChain的DuckDuckGoSearchRun工具实现搜索功能。
  • • 结合LangChain的LLMChainPromptTemplate和HuggingFaceHub LLM完成“AI任务”:从非结构化文本(搜索结果)中提取结构化信息(URL),这是典型的智能体核心步骤。
    1. agentContentFetcher
  • • 使用LangChain的WebBaseLoader(文档加载器)从外部来源获取数据。
  • • 使用LangChain的RecursiveCharacterTextSplitter(文本分割器)为LLM预处理数据。
    1. agentSummarizer
  • • 使用LangChain的load_summarize_chain(预构建摘要链),该链专为摘要生成设计,由HuggingFaceHub LLM提供动力。
    1. agentInterpreter
  • • 这个Python函数充当“指挥者”,自身不依赖LLM做决策(为简化流程并避免基础流程控制产生LLM成本),但会调用其他依赖LLM的组件,同时管理用户交互流程。

这套系统展示了一个基础的多组件架构:部分组件依赖AI(使用LLM和LangChain抽象层),部分组件则基于简单Python逻辑实现。

十、当前局限与AI团队的优化方向

    1. 免费LLM性能google/flan-t5-base这类免费模型虽易获取,但在处理复杂任务(如从杂乱文本中提取URL、生成高质量流畅摘要)时,性能和细腻度可能不及大型商用模型,且上下文窗口较小。
    1. 错误处理:当前错误处理仅为基础级别,实际应用需更健壮的错误管理机制。
    1. URL提取可靠性:基于LLM的URL提取思路可行,但效果受LLM能力和搜索结果页面复杂度影响;备用的正则表达式提取方式也较为基础。
    1. 缺乏复杂智能体交互的“状态”管理:当前“协调者”(agentInterpreter)通过函数调用管理流程,若需实现更复杂的状态化对话或智能体动态任务委派,可引入:
  • LangGraph:LangChain旗下用于构建状态化多智能体应用的库,支持循环流程、显式状态管理和复杂状态转换,是实现“真正多智能体系统”的理想工具。
    1. 网页内容抓取问题WebBaseLoader功能强大,但部分网站可能拦截爬虫、使用复杂JavaScript渲染或要求登录,导致抓取失败。
    1. 用户界面:当前为命令行应用,可使用Streamlit或Gradio为其封装简单的可视化界面。

十一、 AI大模型从0到精通全套学习大礼包

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

只要你是真心想学AI大模型,我这份资料就可以无偿共享给你学习。大模型行业确实也需要更多的有志之士加入进来,我也真心希望帮助大家学好这门技术,如果日后有什么学习上的问题,欢迎找我交流,有技术上面的问题,我是很愿意去帮助大家的!

如果你也想通过学大模型技术去帮助就业和转行,可以扫描下方链接👇👇
大模型重磅福利:入门进阶全套104G学习资源包免费分享!
在这里插入图片描述

01.从入门到精通的全套视频教程

包含提示词工程、RAG、Agent等技术点
在这里插入图片描述

02.AI大模型学习路线图(还有视频解说)

全过程AI大模型学习路线

在这里插入图片描述
在这里插入图片描述

03.学习电子书籍和技术文档

市面上的大模型书籍确实太多了,这些是我精选出来的

在这里插入图片描述
在这里插入图片描述

04.大模型面试题目详解

在这里插入图片描述

在这里插入图片描述

05.这些资料真的有用吗?

这份资料由我和鲁为民博士共同整理,鲁为民博士先后获得了北京清华大学学士和美国加州理工学院博士学位,在包括IEEE Transactions等学术期刊和诸多国际会议上发表了超过50篇学术论文、取得了多项美国和中国发明专利,同时还斩获了吴文俊人工智能科学技术奖。目前我正在和鲁博士共同进行人工智能的研究。

所有的视频由智泊AI老师录制,且资料与智泊AI共享,相互补充。这份学习大礼包应该算是现在最全面的大模型学习资料了。

资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。

在这里插入图片描述
在这里插入图片描述

智泊AI始终秉持着“让每个人平等享受到优质教育资源”的育人理念‌,通过动态追踪大模型开发、数据标注伦理等前沿技术趋势‌,构建起"前沿课程+智能实训+精准就业"的高效培养体系。

课堂上不光教理论,还带着学员做了十多个真实项目。学员要亲自上手搞数据清洗、模型调优这些硬核操作,把课本知识变成真本事‌!

在这里插入图片描述
如果说你是以下人群中的其中一类,都可以来智泊AI学习人工智能,找到高薪工作,一次小小的“投资”换来的是终身受益!

应届毕业生‌:无工作经验但想要系统学习AI大模型技术,期待通过实战项目掌握核心技术。

零基础转型‌:非技术背景但关注AI应用场景,计划通过低代码工具实现“AI+行业”跨界‌。

业务赋能 ‌突破瓶颈:传统开发者(Java/前端等)学习Transformer架构与LangChain框架,向AI全栈工程师转型‌。

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐