首页 / 文章 / 《实用指南:在本地构建自主AI智能体——分步指导》

《实用指南:在本地构建自主AI智能体——分步指导》

《实用指南:在本地构建自主AI智能体——分步指导》的操作流程说明:针对采用该模式的团队,包含相关契约、检查项以及可直接插入的代码模块。

4685 词

以下笔记围绕《在本地构建自主 AI 智能体:16GB 内存系统的逐步指南》梳理出一条实用路径。重点在于契约、校验以及可直接插入的代码占位符,而非激励性表述。

期望与挑战

在处理“期望与挑战”这一阶段时,首先需明确契约内容:所需输入、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放,以便操作员无需查看整个系统结构即可进行审计。 在成本较高的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次调用相同的大型语言模型。

第一部分:选择你的工具——模型选型困境——评估用于令牌生成与智能体效率的本地模型

在完成“第一部分:选择工具”这一阶段时,首先明确相关要求:所需输入、成功标志以及部分失败时的处理方式。这样的清单能确保后续代码修改的规范性。 同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误消息处理都是产品功能的一部分,而非后续需要补充的内容。 缓存稳定的系统指令和工具结构。重复发送相同的开头信息是造成资源浪费的常见原因。

竞争者:直接对比分析

在处理“竞争者:正面交锋”阶段时,首先写下合同条款:所需输入、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持透明。 优先选择小型、可测试的单元,而非庞大的脚本。当某个步骤失败时,故障应指向单一责任点,而非复杂的流程链。 在成本较高的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次调用相同的大语言模型。

Qwen3.5:4b —— 速度之王

在处理 Qwen3 5 4b 阶段时,首先写下契约:所需的输入、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 将这一阶段视为输入与经过验证的输出之间的契约。为相关成果命名,定义成功判定标准,并拒绝默许的部分完成。 在成本较高的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次调用相同的 LLM。

Llama3.1:latest (8B) — 可靠的多面手

在处理 Llama3 1 最新 8B 版本时,首先需明确相关规范:所需输入、成功标志以及部分失败时的处理方式。这份清单能确保后续的代码修改保持一致性。 在功能结果旁记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。 在耗时较高的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次调用相同的大型语言模型。 在处理 Llama3 1 最新 8B 版本时,首先需明确相关规范:所需输入、成功标志以及部分失败时的处理方式。这份清单能确保后续的代码修改保持一致性。 需同时记录正常流程与异常恢复流程。重试机制、人工审核环节以及错误处理都属于产品功能的一部分,而非后续需要补充的内容。

Gemma4:12b-it-q4_K_M —— 强大的推理引擎

Gemma4 12b-it-q4KM的推理阶段若被视为可测量的界面,效果最佳。在扩大范围之前,先记录一份成功的示例、一个失败案例以及回滚说明。相较于庞大的脚本,应优先选择小型且可测试的单元。当某一步骤失败时,故障应指向单一责任模块,而非复杂的流程链。需为每轮及每次会话设定token预算——智能工具会大量消耗上下文,设置上限可避免演示过程变成意外的费用账单。

Qwen3.5:9b-q4_K_M —— 最佳平衡之选

在将 Qwen3 5 9b-q4KM 的处理阶段视为可测量的表面时,其效果最佳。在扩大范围之前,需记录一个成功的案例、一个失败案例以及回滚说明。 应将此阶段视为输入与已验证输出之间的契约。为相关成果命名,明确成功标准,绝不允许出现无声的、不完整的处理结果。 需保持图结构的状态简洁且具有明确类型。嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,且在中断后会导致处理无法继续。

对比模型分析

将“比较模型分析”阶段视为可度量的对象来处理,其效果最佳。在扩大范围之前,先记录一份理想的测试案例、一个失败案例以及回滚说明。在功能结果旁同时记录执行时间以及令牌或查询成本。提前了解成本情况,就能避免在从演示环境过渡到共享环境时出现意外账单。为每轮对话和每次会话设定令牌预算。智能工具往往会大量消耗上下文资源,设置上限可防止演示过程变成令人意外的费用来源。

结论

将“The Verdict”阶段视为可度量的界面使用效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。 将配置置于应用程序代码之外。环境文件、密钥存储和功能标志应集中存放于一个位置,这样操作人员无需查看整个结构即可进行审计。 保持图结构的扁平化与类型化。嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,且在中断后会导致恢复失败。

第二部分:硬件准备与本地推理设置

将第二阶段的硬件准备视为可度量的对象来处理效果最佳。在扩大范围之前,先记录一个成功的测试案例、一个故障案例以及回滚说明。同时记录正常流程和恢复流程的文档。重试机制、人工审核环节以及死信处理都是产品本身的一部分,而非后续需要补充的内容。保持图表状态简洁且类型明确,嵌套的数据块会掩盖哪个节点编写了哪个字段的信息,还会在出现中断后导致流程无法继续。

步骤1:安装 Ollama——您的本地推理引擎

将“第一步:安装 Ollama”这一阶段视为可度量的对象来处理效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。 优先选择小型且可测试的单元,而非庞大的脚本。当某一步骤失败时,故障应能指向某个具体的责任模块,而非复杂的流程链。 在讲解循环逻辑之前,先锁定解释器及依赖项的版本。笔记本电脑与持续集成环境之间的差异是 API 演示中最常见的隐性故障原因。

Linux 安装

将 Linux 安装阶段视为可度量的工作面,效果最佳。在扩大范围之前,需记录一份完美的操作日志、一个失败案例以及回滚说明。 把这一阶段视为输入与已验证输出之间的契约。为相关成果命名,明确成功标准,绝不允许出现无声的半完成状态。 保持图表结构简洁且类型明确。嵌套的数据块会掩盖哪个节点修改了哪个字段,还会在中断后导致无法继续处理。

curl -fsSL https://ollama.com/install.sh | sh

macOS 安装

将 macOS 安装阶段视为可度量的对象来处理,效果最佳。在扩大范围之前,需记录一份理想的操作流程、一个故障案例以及回滚说明。 在功能结果旁同时记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。 保持图表状态简洁且类型明确。嵌套的数据块会掩盖哪个节点修改了哪个字段,还会在中断后导致流程无法继续。 将 macOS 安装阶段视为可度量的对象来处理,效果最佳。在扩大范围之前,需记录一份理想的操作流程、一个故障案例以及回滚说明。 需同时记录正常流程与恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的组成部分,而非后续需要补充的内容。

curl -fsSL https://ollama.com/install.sh | sh

Windows 安装

在 Windows 安装阶段,应在修改代码之前明确输入参数、该步骤的负责人以及退出标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏的状态。 优先选择小型、可测试的单元,而非冗长的脚本。当某个步骤失败时,故障应指向单一的责任主体,而非错综复杂的流程。 对于涉及资金支出或修改生产数据的操作,必须经过人工审批。编译时的连接方式并不等同于业务功能的完整性。

irm https://ollama.com/install.ps1 | iex

验证安装情况

在“验证安装”阶段,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将此阶段视为输入与已验证输出之间的契约。为相关成果命名,定义成功判定标准,并拒绝默许的半完成状态。 对于涉及资金支出或修改生产数据的操作,必须经过人工审批。编译时的配置并不等同于业务上的完整性。

ollama --version
ollama version is 0.5.x

第2步:拉取模型

在“步骤2:拉取你的阶段”中,修改代码之前需明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。应在功能结果旁记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在流程从演示环境转向共享环境时出现意外费用。当下一步操作为编写代码或调用工具时,建议使用具有架构验证的结构化输出,而非自由形式的文字描述。在“步骤2:拉取你的阶段”中,修改代码之前需明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误处理措施都是产品本身的一部分,而非后续需要补充的内容。

# For the winner
ollama pull qwen3.5:9b-q4_K_M

# For speed
ollama pull qwen3.5:4b

# For reasoning
ollama pull gemma4:e4b-q4_K_M

步骤3:启动Ollama服务器

在执行“启动服务器”这一步骤时,首先需明确相关要求:所需的输入参数、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改不会偏离原有设计。 建议采用小型、可测试的单元而非庞大的脚本。当某个步骤出现故障时,故障应能指向具体的责任模块,而非复杂的流程链。 每次调用时都要记录请求ID、模型ID以及响应延迟时间。如果没有这些记录,间歇性的服务错误就会被误认为是应用程序的缺陷。

ollama serve

步骤4:测试你的模型

在完成“第4步:测试”阶段时,首先写下相关契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 将此阶段视为输入与验证后输出之间的契约。为相关产物命名,明确成功判定标准,杜绝无声的半完成状态。 缓存稳定的系统指令和工具架构。重复发送相同的开头信息是导致资源浪费的常见原因。

ollama run qwen3.5:9b-q4_K_M "Hello, introduce yourself briefly."

第三部分:配置CrewAI——编排框架

在完成第三部分的设置阶段时,首先需写下相关规范:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 在功能结果旁记录执行时间以及令牌或查询成本。提前明确成本信息,可避免在系统从演示环境过渡到共享环境时出现意外费用。 在耗时的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次收取相同的LLM调用费用。 在完成第三部分的设置阶段时,首先需写下相关规范:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及死信处理都是产品功能的一部分,而非后续需要补充的内容。

系统要求

将“系统需求”阶段视为可度量的对象来处理效果最佳。在扩大范围之前,先记录一份理想的测试用例、一个故障案例以及回滚说明。 优先选择小型且可测试的单元,而非庞大的脚本。当某个步骤出现故障时,故障应指向单一责任模块,而非复杂的流程链。 保持图表状态简洁且具有类型定义。嵌套的数据结构会掩盖哪个节点修改了哪个字段的信息,还会在流程中断后导致无法继续执行。

第一步:安装 uv(现代 Python 包管理工具)

第一步:将UV阶段视为可测量的表面来处理,这样效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。 将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,明确成功标准,绝不允许出现悄无声息的半完成状态。 在教授循环逻辑之前,先锁定解释器及依赖项。在笔记本电脑与持续集成环境之间的差异是API演示中最常见的隐性故障原因。

curl -LsSf https://astral.sh/uv/install.sh | sh
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

第二步:安装CrewAI CLI

将第二步的CrewAI安装阶段视为可度量的对象来处理效果最佳。在扩大范围之前,先记录一份理想的运行日志、一个故障案例以及回滚说明。在功能结果旁同时记录执行时间以及令牌或查询成本。提前了解成本情况,就能避免在从演示环境过渡到共享环境时出现意外费用。要保持图结构的状态简洁且类型明确,嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,还会在进程中断后导致无法继续运行。

uv tool install crewai

第三步:创建你的Crew项目

将“第三步:创建你的舞台”视为一个可度量的结构来使用效果最佳。在扩大范围之前,先记录一份成功的案例、一个失败案例以及回滚说明。 将配置与应用程序代码分开。环境文件、密钥存储和功能标志应集中存放于一个位置,这样操作人员无需查看整个结构就能进行审计。 保持数据结构的层次简单且类型明确。嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,还会在出现中断后导致无法继续处理。

crewai create crew my_agent_team
cd my_agent_team
my_agent_team/
├── src/
│   └── my_agent_team/
│       ├── __init__.py
│       ├── crew.py
│       ├── agents.py
│       ├── tasks.py
│       └── main.py
├── .env
└── pyproject.toml

第四步:安装依赖项

将第4步“安装依赖项”视为可度量的工作环节最为有效。在扩大范围之前,需记录一个成功的执行案例、一个失败案例以及回滚说明。同时文档化正常流程与恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的一部分,而非后续需要补充的内容。要保持图结构简洁且类型明确,嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,还会在中断后导致流程无法继续。

uv pip install -e .

第5步:安装其他工具

将第5步“安装附加组件”视为可度量的工作面来处理效果最佳。在扩大范围之前,先记录一份成功的示例、一个失败案例以及回滚说明。 优先选择小型且可测试的单元,而非庞大的脚本。当某一步骤失败时,故障应能指向单一责任主体,而非复杂的流程链。 使用结构明确的工具,并标注清晰的副作用信息。主机需要在自动批准之前知道哪些调用会改变状态。

uv pip install crewai-tools langchain-ollama python-pptx

第4部分:组建你的代理团队

将“第四部分:构建你的阶段”视为一个可度量的界面使用效果最佳。在扩大范围之前,先记录一份优秀的案例、一个失败案例以及回滚说明。 把这一阶段视为输入与已验证输出之间的契约。为相关成果命名,明确成功标准,绝不允许默默地只完成部分工作。 保持图结构的状态简洁且具有类型约束。嵌套的数据块会掩盖是哪个节点修改了哪个字段,还会在中断后导致无法继续处理。

架构

将架构阶段视为可度量的对象来处理时,其效果最佳。在扩大范围之前,需记录一份理想的操作流程、一个故障案例以及回滚说明。 在功能结果旁同时记录处理时间以及令牌或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。 保持图结构简洁且类型明确。嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,还会在出现中断后导致流程无法继续。 将架构阶段视为可度量的对象来处理时,其效果最佳。在扩大范围之前,需记录一份理想的操作流程、一个故障案例以及回滚说明。 需同时记录正常处理路径和故障恢复路径。重试机制、人工审核流程以及死信处理都是产品本身的组成部分,而非后续需要补充的功能。

步骤1:配置大语言模型

在第一步“配置阶段”中,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏的状态。相比冗长的脚本,更应采用小型且可测试的单元。当某个步骤失败时,故障原因应能指向单一责任主体,而非复杂的流程链。如果后续步骤是代码或工具调用,相比自由形式的文字描述,带有架构验证的结构化输出更为合适。

from langchain_ollama import OllamaLLM

def get_llm():
    """ Initialize the local LLM for CrewAI."""
    return OllamaLLM(
        model="qwen3.5:9b-q4_K_M",
        base_url="http://localhost:11434",
        temperature=0.3,  # Lower = more deterministic
        top_p=0.9,
    )

第二步:定义你的智能体

在“第二步:定义你的阶段”中,应在修改代码之前明确输入内容、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,定义成功判定标准,并拒绝默许的半完成状态。 对于涉及资金支出或更改生产数据的操作,必须经过人工审批。编译时的连接并不等同于业务上的完整性。

from crewai import Agent
from crewai_tools import SerperDevTool, FileReadTool
from .llm_config import get_llm

# Initialize tools
search_tool = SerperDevTool()  # Requires Serper API key (free tier available)
file_tool = FileReadTool()
def create_coding_agent():
    """Agent specialized in writing and reviewing code."""
    return Agent(
        role="Senior Software Engineer",
        goal="Write clean, efficient, and well-documented code that solves the given problem",
        backstory="""You are a senior software engineer with 15 years of experience
        across multiple programming languages. You specialize in Python, JavaScript,
        and system architecture. You write code that is not only functional but
        also maintainable and follows best practices.""",
        tools=[file_tool],  # Can read existing files
        llm=get_llm(),
        verbose=True,
        allow_delegation=False,
    )
def create_research_agent():
    """Agent specialized in deep research and report writing."""
    return Agent(
        role="Lead Research Analyst",
        goal="Conduct thorough research and synthesize findings into comprehensive reports",
        backstory="""You are a seasoned research analyst with a PhD in Computer Science.
        You have expertise in finding, verifying, and synthesizing information from
        multiple sources. Your reports are known for their depth, clarity, and
        actionable insights.""",
        tools=[search_tool],  # Can search the web
        llm=get_llm(),
        verbose=True,
        allow_delegation=False,
    )
def create_presentation_agent():
    """Agent specialized in creating PowerPoint presentations."""
    return Agent(
        role="Senior Presentation Designer",
        goal="Transform research findings into compelling, visually-appealing PowerPoint presentations",
        backstory="""You are a presentation designer with 10 years of experience
        creating executive-level decks for Fortune 500 companies. You know how to
        structure information for maximum impact and create slides that tell a
        compelling story.""",
        tools=[],  # We'll handle PPT generation separately
        llm=get_llm(),
        verbose=True,
        allow_delegation=False,
    )

第三步:定义你的任务

在第三步“定义你的阶段”中,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。应在功能结果旁记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在流程从演示环境转向共享环境时出现意外费用。对于会消耗资金或修改生产数据的操作,必须经过人工审批。编译时的配置并不等同于业务功能的完整性。在第三步“定义你的阶段”中,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误处理措施都是产品不可或缺的部分,而非后续需要补充的内容。

from crewai import Task

def create_coding_task(topic, requirements):
    """Task for the coding agent."""
    return Task(
        description=f"""
        Write a Python solution for the following problem:

        Topic: {topic}
        Requirements: {requirements}

        Your response should include:
        1. Complete, working Python code
        2. Explanation of the approach
        3. Time and space complexity analysis
        4. Example usage

        Make sure the code is production-ready and includes error handling.
        """,
        expected_output="A complete Python solution with documentation and analysis.",
        agent=None,  # Will be assigned later
    )
def create_research_task(query):
    """Task for the research agent."""
    return Task(
        description=f"""
        Conduct in-depth research on the following topic:

        Query: {query}

        Your research should cover:
        1. Current state of the art
        2. Key players and technologies
        3. Challenges and limitations
        4. Future trends and predictions
        5. Actionable recommendations

        Cite your sources and provide a well-structured report.
        """,
        expected_output="A comprehensive research report with citations.",
        agent=None,  # Will be assigned later
    )
def create_presentation_task(research_findings):
    """Task for the presentation agent."""
    return Task(
        description=f"""
        Create a PowerPoint presentation based on the following research:

        {research_findings}

        The presentation should include:
        1. Title slide with a compelling title
        2. Executive summary
        3. Key findings (3-5 slides)
        4. Visual data representation
        5. Recommendations
        6. Conclusion and next steps

        Provide a detailed outline and slide content.
        """,
        expected_output="A detailed PowerPoint presentation outline with slide content.",
        agent=None,  # Will be assigned later
    )

第4步:协调团队工作

在执行第4步“协调团队工作”时,首先写下相关契约:所需的输入参数、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 建议使用小型、可测试的单元而非庞大的脚本。当某一步骤失败时,故障应指向单一的责任模块,而非复杂的流程链。 在成本较高的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次调用相同的LLM接口。

from crewai import Crew, Process
from .agents import (
    create_coding_agent,
    create_research_agent,
    create_presentation_agent
)
from .tasks import (
    create_coding_task,
    create_research_task,
    create_presentation_task
)

def create_crew(topic, query, requirements):
    """Create and configure the multi-agent crew."""

    # Initialize agents
    coding_agent = create_coding_agent()
    research_agent = create_research_agent()
    presentation_agent = create_presentation_agent()

    # Create tasks
    coding_task = create_coding_task(topic, requirements)
    research_task = create_research_task(query)

    # Assign agents to tasks
    coding_task.agent = coding_agent
    research_task.agent = research_agent

    # The presentation task depends on research findings
    # We'll create it dynamically after research is complete

    return Crew(
        agents=[coding_agent, research_agent, presentation_agent],
        tasks=[coding_task, research_task],
        process=Process.sequential,  # Tasks run in order
        verbose=True,
    )
def run_crew(topic, query, requirements):
    """Run the multi-agent crew and return results."""
    crew = create_crew(topic, query, requirements)
    result = crew.kickoff()
    return result

第5步:主入口点

在处理第5步“主要阶段”时,首先写下相关契约:所需的输入参数、成功信号以及部分失败时的处理方式。这份清单能确保后续的代码修改保持一致性。 将这一阶段视为输入与验证后输出之间的契约。为相关成果命名,明确成功判定标准,杜绝无声的半完成状态。 在成本较高的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次调用相同的LLM接口。

import os
from .crew import run_crew

def main():
    """Main entry point for the multi-agent system."""

    # Define your project
    topic = "Building a REST API with FastAPI"
    query = "Best practices for FastAPI REST API development in 2026"
    requirements = """
    - Python 3.11+
    - FastAPI framework
    - PostgreSQL database
    - JWT authentication
    - Docker deployment
    """

    print("🚀 Starting multi-agent workflow...")
    print("=" * 50)

    # Run the crew
    result = run_crew(topic, query, requirements)

    print("\n✅ Workflow complete!")
    print("=" * 50)
    print("\n📊 Results:")
    print(result)

    return result
if __name__ == "__main__":
    main()

第5部分:自动生成PowerPoint演示文稿

在处理第5部分“自动生成PowerPoint演示文稿”阶段时,首先写下相关契约:所需的输入参数、成功信号以及部分失败时的处理方式。这份清单能确保后续的代码修改保持一致性。

第1步:创建PPT生成器

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
from pptx.dml.color import RGBColor
import os

def create_presentation_from_content(content, filename="presentation.pptx"):
    """
    Generate a PowerPoint presentation from structured content.

    Args:
        content: Dictionary with slide titles and content
        filename: Output filename
    """
    prs = Presentation()

    # Set slide dimensions (16:9)
    prs.slide_width = Inches(13.333)
    prs.slide_height = Inches(7.5)

    # Title Slide
    title_slide_layout = prs.slide_layouts[0]
    slide = prs.slides.add_slide(title_slide_layout)
    slide.shapes.title.text = content.get("title", "AI-Generated Presentation")
    slide.placeholders[1].text = content.get("subtitle", "Powered by CrewAI + Ollama")

    # Content Slides
    for slide_data in content.get("slides", []):
        bullet_slide_layout = prs.slide_layouts[1]
        slide = prs.slides.add_slide(bullet_slide_layout)

        # Title
        slide.shapes.title.text = slide_data.get("title", "Untitled")

        # Content
        content_text = slide.placeholders[1]
        content_frame = content_text.text_frame
        content_frame.clear()

        for point in slide_data.get("points", []):
            p = content_frame.add_paragraph()
            p.text = point
            p.level = 0
            p.font.size = Pt(18)

    # Save
    prs.save(filename)
    print(f"✅ Presentation saved as: {filename}")
    return filename
def generate_ppt_from_research(research_text, topic):
    """
    Generate a PPT from research findings using the presentation agent.
    """
    from .agents import create_presentation_agent
    from .llm_config import get_llm

    # Have the presentation agent structure the content
    agent = create_presentation_agent()

    prompt = f"""
    Based on the following research about "{topic}", create a structured
    presentation outline with 6-8 slides.

    Research:
    {research_text[:2000]}  # Limit to avoid context overflow

    Return a JSON object with the following structure:
    {{
        "title": "Presentation title",
        "subtitle": "Subtitle or tagline",
        "slides": [
            {{
                "title": "Slide title",
                "points": ["Point 1", "Point 2", "Point 3"]
            }}
        ]
    }}
    """

    # Get structured output from the agent
    response = agent.llm.invoke(prompt)

    # Parse the response (simplified - in production, use proper JSON parsing)
    import json
    try:
        # Extract JSON from response
        content = json.loads(response)
    except:
        # Fallback: create a simple structure
        content = {
            "title": f"Research on {topic}",
            "subtitle": "AI-Generated Presentation",
            "slides": [
                {"title": "Introduction", "points": ["Overview of research"]},
                {"title": "Key Findings", "points": ["Finding 1", "Finding 2"]},
                {"title": "Recommendations", "points": ["Recommendation 1"]}
            ]
        }

    # Generate the PPT
    filename = f"{topic.replace(' ', '_')}_presentation.pptx"
    return create_presentation_from_content(content, filename)

第2步:将PPT生成功能集成到Crew系统中

from .ppt_generator import generate_ppt_from_research

def run_full_workflow(topic, query, requirements):
    """Run the complete workflow including PPT generation."""

    # Step 1: Run the crew (coding + research)
    crew_result = run_crew(topic, query, requirements)

    # Step 2: Extract research findings (simplified - in production, parse properly)
    research_findings = crew_result  # This would be the research agent's output

    # Step 3: Generate PowerPoint
    ppt_file = generate_ppt_from_research(research_findings, topic)

    return {
        "crew_result": crew_result,
        "presentation_file": ppt_file
    }

第6部分:常见陷阱及解决方法

问题1:CrewAI尝试连接Ollama时出现“连接被拒绝”

litellm.APIConnectionError: OllamaException - [Errno 111] Connection refused
llm = OllamaLLM(
    model="qwen3.5:9b-q4_K_M",
    base_url="http://localhost:11434",  # Ensure this is correct
)

问题2:模型无法遵循工具调用规范

问题3:内存不足错误

问题4:智能体陷入递归循环

问题5:令牌生成速度过慢

第7部分:运行你的第一个多智能体工作流

完整设置流程

#!/usr/bin/env python3
"""
Complete Multi-Agent System with Ollama and CrewAI
"""

import os
import sys
from src.my_agent_team.crew import run_full_workflow
def main():
    print("""
    ╔═══════════════════════════════════════════════════════╗
    ║     🤖 Multi-Agent AI System - Local Edition         ║
    ║     Powered by Ollama + CrewAI + Qwen3.5:9b         ║
    ╚═══════════════════════════════════════════════════════╝
    """)

    # Check if Ollama is running
    import requests
    try:
        response = requests.get("http://localhost:11434")
        print("✅ Ollama is running!")
    except:
        print("❌ Ollama is not running. Please start it with: ollama serve")
        sys.exit(1)

    # Define your project
    topic = input("Enter your project topic (e.g., 'Building a REST API with FastAPI'): ")
    query = input("Enter your research query (e.g., 'Best practices for FastAPI'): ")
    requirements = input("Enter your requirements (e.g., 'Python, PostgreSQL, JWT'): ")

    print("\n🚀 Starting multi-agent workflow...")
    print("=" * 60)

    try:
        result = run_full_workflow(topic, query, requirements)

        print("\n✅ Workflow complete!")
        print("=" * 60)
        print(f"\n📄 Presentation saved as: {result['presentation_file']}")
        print("\n📊 Crew Results:")
        print(result['crew_result'])

    except Exception as e:
        print(f"\n❌ Error: {e}")
        print("\n💡 Troubleshooting tips:")
        print("1. Make sure Ollama is running: ollama serve")
        print("2. Check if the model is downloaded: ollama list")
        print("3. Ensure you have enough memory (close other apps)")
        print("4. Check the error message above for specific issues")
if __name__ == "__main__":
    main()

开始运行!

python run.py

第8部分:性能优化检查清单

内存优化

速度优化

可靠性优化

总结:你成功了!

最后思考

操作检查清单