通义千问1.5-1.8B-Chat-GPTQ-Int4实战:基于Agent架构的自动化任务编排

你是不是也遇到过这种情况?老板突然让你“整理一下最近AI领域的热点新闻,下班前给我个总结”,或者自己想做研究,需要“搜集几个开源大模型的评测数据,做个对比表格”。这些任务听起来简单,但做起来却要打开一堆网页,复制粘贴,再整理归纳,费时费力。

如果有个“智能小助手”能听懂你的复杂指令,自动帮你把活干了,是不是就轻松多了?今天,我们就来聊聊怎么用一个小巧但聪明的模型——通义千问1.5-1.8B-Chat的量化版本,来打造这样一个能自己“思考”和“行动”的AI Agent(智能体),让它帮你自动完成任务。

这个Agent的核心思想很简单:它不再是一个只会一问一答的聊天机器人,而是一个能理解你的复杂目标,自己规划步骤、调用工具(比如搜索网页、读写文件),最终把结果交给你的“小管家”。我们这次就用一个具体的例子——“搜集最近三天AI领域的新闻并总结”,来手把手带你看看它是怎么工作的。

1. 为什么需要AI Agent?从聊天到“做事”的跨越

传统的对话模型,比如我们常见的聊天机器人,模式是“你问一句,它答一句”。它的能力边界,基本就框定在它被训练时学到的知识里。你问它“太阳为什么东升西落”,它能给你一个很好的解释。但你如果让它“去网上查查今天北京的天气,然后告诉我该穿什么衣服”,它就无能为力了,因为它没有“手”去打开浏览器查询天气网站。

AI Agent就是为了解决这个“有脑无手”的问题而生的。你可以把它想象成一个有了“身体”的大脑。这个“大脑”(大语言模型)负责理解你的意图、规划步骤、做决策;而“身体”(各种工具和API)则负责执行具体的动作,比如搜索、计算、操作文件。

一个典型的Agent工作流程,可以概括为“思考-行动-观察”的循环:

  1. 思考:根据你的指令和当前已知信息,决定下一步该做什么。
  2. 行动:选择并调用一个合适的工具(比如“执行网络搜索”)。
  3. 观察:获取工具执行后的结果(比如搜索到的网页内容)。
  4. 带着新的观察结果,回到第1步继续“思考”,直到任务完成。

这个模式在学术上有个挺有名的框架叫 ReAct (Reasoning + Acting),它强调让模型在输出最终答案前,先把它的推理链(Reasoning)和要执行的动作(Acting)写出来,这样不仅能提升任务完成的准确性,也让整个过程变得可解释、可调试。

那么,为什么选择通义千问1.5-1.8B-Chat,并且还是GPTQ-Int4量化版呢?原因很实在:

  • 足够聪明:1.8B参数在轻量级模型中属于“优等生”,理解复杂指令和规划任务的能力已经不错。
  • 身材小巧:经过GPTQ-Int4量化后,模型体积和内存占用大幅减少,对硬件极其友好,普通家用电脑都能轻松跑起来,部署成本低。
  • 对话优化:这个Chat版本是针对对话场景微调的,更擅长理解人类的自然语言指令,这正是Agent所需要的“大脑”。

接下来,我们就看看怎么把这个小巧的“大脑”组装成一个能干的“小管家”。

2. 搭建你的第一个AI Agent系统

要构建一个Agent,我们需要准备三样东西:一个会思考的模型(大脑)、一套它能用的工具(双手)、以及一个管理它们如何协作的框架(工作流程)。我们一步步来。

2.1 环境与模型准备

首先,我们把核心“大脑”请出来。通义千问1.5-1.8B-Chat-GPTQ-Int4模型在很多开源模型社区都能找到,加载起来非常方便。这里我们用流行的transformers库和auto-gptq库来加载它。

# 安装必要的库
pip install transformers torch auto-gptq
# 加载量化模型和分词器
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline

model_name = "Qwen/Qwen1.5-1.8B-Chat-GPTQ-Int4" # 示例模型路径,请根据实际仓库调整

tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    device_map="auto",  # 自动分配设备(CPU/GPU)
    trust_remote_code=True
)

# 创建一个文本生成的管道
chat_pipeline = pipeline(
    "text-generation",
    model=model,
    tokenizer=tokenizer,
    max_new_tokens=512
)

这样,我们的模型就准备好了。你可以简单测试一下它的基础对话能力。

2.2 给Agent装上“双手”:定义工具

一个只会空想的Agent是没用的,我们必须赋予它行动的能力。我们来定义几个在“搜集新闻并总结”这个任务中可能用到的简单工具。在实际项目中,这些工具可以连接真实的搜索引擎API、数据库等。

# 模拟的工具函数库
class AgentTools:
    """一个简单的工具集合"""
    
    @staticmethod
    def search_web(query: str):
        """模拟网络搜索功能(实际应接入SerpAPI、Google Search API等)"""
        # 这里为了演示,返回模拟数据
        print(f"[工具调用] 正在搜索: {query}")
        mock_results = [
            {"title": "大模型价格战升级,某厂商宣布API价格下调50%", "snippet": "近日,国内AI公司...", "source": "科技新闻网", "date": "2024-05-18"},
            {"title": "轻量级模型成为边缘AI新宠", "snippet": "随着终端设备算力提升...", "source": "AI产业观察", "date": "2024-05-17"},
            {"title": "多模态AI应用在内容创作领域爆发", "snippet": "从文生图到文生视频...", "source": "创新媒体", "date": "2024-05-16"}
        ]
        # 过滤一下,模拟“最近三天”的结果
        filtered_results = [r for r in mock_results if r['date'] >= "2024-05-16"]
        return filtered_results
    
    @staticmethod
    def extract_key_info(articles):
        """从搜索结果中提取关键信息(标题、核心内容)"""
        print(f"[工具调用] 正在从{len(articles)}篇文章中提取信息")
        extracted = []
        for article in articles:
            extracted.append({
                "标题": article["title"],
                "核心内容": article["snippet"],
                "来源": article["source"]
            })
        return extracted
    
    @staticmethod
    def write_summary(bullet_points):
        """根据要点,撰写一段总结性文字"""
        print(f"[工具调用] 正在撰写总结")
        # 这里可以调用模型来生成更流畅的总结,我们简单拼接一下
        summary = "近日AI领域主要动态如下:\n" + "\n".join([f"- {point}" for point in bullet_points])
        return summary
    
    @staticmethod
    def save_to_file(content, filename="news_summary.txt"):
        """将结果保存到文件"""
        print(f"[工具调用] 正在保存结果到 {filename}")
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(content)
        return f"内容已成功保存至 {filename}"

有了这些工具函数,我们的Agent就有了可以调用的“手”。下一步是告诉Agent,在什么情况下该用哪只手。

2.3 设计Agent的“工作流”:ReAct模式实践

现在,我们来设计Agent的核心逻辑。我们将实现一个简化版的ReAct循环。关键点在于,我们要求模型在回复时,遵循一个固定的格式,明确写出它的“思考”和下一步“动作”。

def run_agent_react(user_query, max_steps=10):
    """
    运行一个基于ReAct思路的简单Agent
    """
    # 系统提示,告诉模型它是个Agent以及该如何工作
    system_prompt = """你是一个AI助手,能够通过调用工具来完成用户的任务。请严格按照以下格式回应:
思考:[你的推理过程,分析当前情况,决定下一步做什么]
行动:`工具名`(`参数`)
观察:[工具返回的结果]

当你认为任务已经完成,最终答案应该给用户时,请使用:
最终答案:[给用户的最终回复]
"""
    
    # 工具描述,告诉模型它有哪些工具可用
    tools_description = """
你可用的工具:
1. `search_web(query)`: 根据查询词进行网络搜索,返回相关文章列表。
2. `extract_key_info(articles)`: 从文章列表中提取关键信息(标题、核心内容)。
3. `write_summary(bullet_points)`: 根据要点列表,撰写一段连贯的总结。
4. `save_to_file(content, filename)`: 将文本内容保存到指定文件。
"""
    
    # 初始化对话历史和上下文
    full_context = system_prompt + "\n" + tools_description + "\n\n用户请求:" + user_query + "\n\n"
    history = []
    
    for step in range(max_steps):
        print(f"\n=== 步骤 {step+1} ===")
        
        # 1. 让模型“思考”并决定“行动”
        prompt = full_context + "\n".join(history) + "\n思考:"
        response = chat_pipeline(prompt, max_new_tokens=200)[0]['generated_text']
        
        # 从响应中提取“思考”和“行动”部分(这里需要简单的文本解析)
        # 这是一个简化的解析,实际应用需要更健壮的解析器
        lines = response.split('\n')
        thought = ""
        action = ""
        for line in lines:
            if line.startswith("思考:"):
                thought = line[3:].strip()
            elif line.startswith("行动:`"):
                # 提取 `工具名`(`参数`)
                action_line = line[3:].strip()
                # 简单解析出工具名和参数
                import re
                match = re.match(r'`(\w+)`\(([^)]*)\)', action_line)
                if match:
                    tool_name = match.group(1)
                    tool_param = match.group(2).strip('\"\'') # 去掉可能的引号
                    action = (tool_name, tool_param)
        
        print(f"思考: {thought}")
        if action:
            print(f"行动: 调用 {action[0]}, 参数: {action[1]}")
        
        # 2. 执行“行动”(调用工具)
        observation = ""
        if action:
            tool_name, param = action
            try:
                if tool_name == "search_web":
                    result = AgentTools.search_web(param)
                    observation = f"搜索到{len(result)}条相关结果。"
                elif tool_name == "extract_key_info":
                    # 这里需要从历史中获取articles参数,演示中我们简化处理
                    # 实际应该维护一个状态机或更复杂的上下文
                    print("(演示中,假设提取了信息)")
                    observation = "关键信息已提取完毕。"
                elif tool_name == "write_summary":
                    print("(演示中,假设撰写了总结)")
                    observation = "总结已撰写完成。"
                elif tool_name == "save_to_file":
                    print("(演示中,假设保存了文件)")
                    observation = "文件已保存。"
                else:
                    observation = f"错误:未知工具 '{tool_name}'。"
            except Exception as e:
                observation = f"工具调用出错:{e}"
        else:
            # 如果没有行动,检查是否是最终答案
            for line in lines:
                if line.startswith("最终答案:"):
                    final_answer = line[5:].strip()
                    print(f"\n任务完成!最终答案:\n{final_answer}")
                    return final_answer
            observation = "未识别出有效行动指令。"
        
        print(f"观察: {observation}")
        
        # 3. 将本轮“思考-行动-观察”加入历史,进入下一轮循环
        history.append(f"思考:{thought}")
        if action:
            history.append(f"行动:`{action[0]}`(`{action[1]}`)")
        history.append(f"观察:{observation}")
        
        # 防止无限循环
        if step == max_steps - 1:
            print("达到最大步数,任务可能未完成。")
            break
    
    return None

# 运行Agent试试看
if __name__ == "__main__":
    user_task = "搜集最近三天AI领域的新闻并总结,然后保存到文件里。"
    run_agent_react(user_task)

运行上面的代码,你会在控制台看到类似这样的输出(具体内容因模型随机性可能不同):

=== 步骤 1 ===
思考:用户需要最近三天AI领域的新闻。我需要先搜索相关信息。
行动:调用 search_web, 参数:最近三天 AI 领域 新闻
观察:搜索到3条相关结果。

=== 步骤 2 ===
思考:我已经有了新闻列表,现在需要从这些结果中提取出关键信息,以便后续总结。
行动:调用 extract_key_info, 参数:上一步的搜索结果
观察:关键信息已提取完毕。

=== 步骤 3 ===
思考:关键信息已经提取出来了,现在我需要根据这些要点,撰写一段连贯的总结文字。
行动:调用 write_summary, 参数:提取出的关键要点列表
观察:总结已撰写完成。

=== 步骤 4 ===
思考:总结已经写好了,用户要求保存到文件里。我需要调用保存文件的工具。
行动:调用 save_to_file, 参数:撰写好的总结内容, news_summary.txt
观察:文件已保存。

=== 步骤 5 ===
思考:所有步骤都已完成。搜索、提取、总结、保存文件的任务都已经执行完毕。现在可以给用户最终答复了。
最终答案:已完成您的要求。我已搜索了最近三天AI领域的新闻,提取了关键信息,并撰写了一份总结,内容已保存至“news_summary.txt”文件中。主要新闻涉及大模型市场价格动态、轻量级模型发展趋势以及多模态AI应用等内容。

看,这个Agent就像一个有条不紊的项目经理,自己把任务拆解(拆成搜索、提取、总结、保存),然后一步步调用工具去完成,最后向你汇报。整个过程是透明的,你能看到它的“思考”过程。

3. 让Agent更实用:优化与扩展思路

上面的例子是一个最基础的演示。要打造一个真正实用的Agent,我们还需要考虑更多。

3.1 工具描述的优化

在给模型的系统提示中,我们对工具的描述可以更详细、更结构化,这样模型才能更准确地理解何时该调用哪个工具。例如,使用类似以下格式:

tools_description_detailed = """
你拥有以下工具,请仔细阅读描述决定是否使用:
- 名称:search_web
  描述:此工具用于在互联网上搜索最新信息。当你需要获取实时、非模型训练数据内的信息时使用它。
  参数:`query` (字符串类型),一个明确的搜索关键词。
  返回:一个包含标题、摘要、来源和日期的文章列表。

- 名称:extract_key_info
  描述:此工具用于从一堆文本(如文章列表)中,提炼出最核心的要素,如事件、观点、数据等。
  参数:`text_list` (列表类型),一个包含文本对象的列表。
  返回:一个结构化或简化后的信息列表。
...
"""

3.2 引入“记忆”与状态管理

我们的简单例子中,工具之间的参数传递(比如把search_web的结果传给extract_key_info)是靠“想象”的。现实中,我们需要一个状态管理机制。可以维护一个全局的working_memory字典,或者使用更高级的框架(如LangChain)来管理对话历史和工具执行结果,确保信息能在不同的步骤间正确传递。

3.3 处理复杂任务与错误

一个健壮的Agent需要能处理意外情况。比如:

  • 工具调用失败:网络搜索API超时了怎么办?我们应该在“观察”中反馈这个错误,并让模型决定是重试还是换种方法。
  • 任务分解不清:用户说“帮我分析一下公司的销售数据并预测下季度趋势”。这个任务可能需要先调用read_database工具,再调用data_analysis工具,最后调用generate_report工具。模型需要具备更强的复杂任务分解能力。
  • 验证结果:在给出最终答案前,是否可以增加一个self_check(自我检查)步骤,让模型评估当前结果是否已满足用户要求?

4. 总结与展望

通过这个实战项目,我们看到了如何将一个轻量级的对话模型(通义千问1.5-1.8B-Chat-GPTQ-Int4)从一个“知识库”升级为一个“行动派”。核心在于引入了ReAct这类“思考-行动”框架,并为其配备了可调用的工具函数。这使得AI能够突破自身知识库的局限,真正与外部世界互动,完成从信息查询到内容生成再到文件处理的一系列自动化任务。

这种基于Agent的架构,其想象空间非常大。你可以根据不同的场景,为它装备不同的“工具套装”:

  • 个人效率助手:集成日历(安排会议)、邮件(发送摘要)、文档(整理笔记)工具。
  • 数据分析Agent:集成数据库查询、Python计算、图表生成工具,自动完成数据提取、分析和可视化报告。
  • 客服工单处理Agent:集成用户数据库、知识库搜索、工单系统API,自动回答常见问题或生成初步处理意见。

当然,我们今天的实现还比较基础。工业级的Agent系统会涉及更复杂的规划算法(如Chain of Thought, Tree of Thoughts)、更可靠的工具调用解析、以及长期记忆管理等。但万变不离其宗,其核心思想依然是:让大语言模型担任“指挥官”和“决策者”,协调一系列专业化“工具”来共同完成复杂目标。

用通义千问这样的小模型来入门实践Agent架构,成本低、速度快,非常适合学习和原型验证。当你摸清了其中的门道,完全可以迁移到更强大的模型上,去构建更智能、更可靠的自动化工作流。不妨就从今天这个能帮你“搜新闻”的小助手开始,动手试试吧。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

更多推荐