你是否想过,如何让多个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

四、步骤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团队已组建完成!🎉

恭喜你!你已设计并(有望)运行了一个基于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全栈工程师转型‌。

image.png

vx扫描下方二维码即可
在这里插入图片描述

本教程比较珍贵,仅限大家自行学习,不要传播!更严禁商用!

03 入门到进阶学习路线图

大模型学习路线图,整体分为5个大的阶段:
图片

04 视频和书籍PDF合集

图片

从0到掌握主流大模型技术视频教程(涵盖模型训练、微调、RAG、LangChain、Agent开发等实战方向)

图片

新手必备的大模型学习PDF书单来了!全是硬核知识,帮你少走弯路(不吹牛,真有用)
图片

05 行业报告+白皮书合集

收集70+报告与白皮书,了解行业最新动态!
图片

06 90+份面试题/经验

AI大模型岗位面试经验总结(谁学技术不是为了赚$呢,找个好的岗位很重要)图片
在这里插入图片描述

07 deepseek部署包+技巧大全

在这里插入图片描述

由于篇幅有限

只展示部分资料

并且还在持续更新中…

真诚无偿分享!!!
vx扫描下方二维码即可
加上后会一个个给大家发

在这里插入图片描述

Logo

更多推荐