Nanbeige4.1-3B Agent实战:构建自动写周报+同步钉钉的智能体

每周五下午,你是不是也对着空白的周报文档发愁?回忆这周做了什么、量化工作成果、规划下周计划……一套流程下来,半小时就没了。更别提还要手动复制粘贴到钉钉里提交。

今天,咱们就用一个只有30亿参数的小模型——Nanbeige4.1-3B,来彻底解决这个痛点。我将带你一步步构建一个智能体(Agent),它能自动帮你生成结构清晰的周报,并且一键同步到钉钉。整个过程完全自动化,你只需要告诉它你这周干了啥。

1. 为什么选择Nanbeige4.1-3B来构建智能体?

在开始动手之前,你可能会问:市面上大模型那么多,为什么偏偏选这个“小个子”?

第一,它足够“聪明”且专注。 Nanbeige4.1-3B虽然只有30亿参数,但在逻辑推理和指令遵循上表现突出。对于“写周报”这种有固定格式和逻辑的任务,它完全能胜任。它就像是一个专为执行具体任务训练的高效助手,不会像一些通用大模型那样产生无关的“废话”。

第二,它原生支持工具调用。 这是构建智能体的核心。一个真正的智能体不能只会“说”,还得会“做”。Nanbeige4.1-3B支持长达600步的工具调用链,这意味着它可以先调用一个函数去查询你的日程或任务列表,再调用另一个函数来分析数据,最后调用钉钉的API提交报告。整个流程它能自己规划,无需你一步步指挥。

第三,部署成本极低。 6GB左右的显存需求,意味着你可以在绝大多数消费级显卡甚至一些云服务器上轻松运行它。完全开源也让你没有授权费用和隐私担忧。

第四,长上下文支持。 8K的上下文长度,足以让它记住我们提供的周报模板、你过往几周的周报风格以及钉钉API的调用规则,确保输出的一致性和准确性。

简单来说,用Nanbeige4.1-3B来打造这个自动周报智能体,就是用最合适的工具,解决一个明确的痛点,性价比超高。

2. 项目设计与核心思路

我们的目标是创建一个端到端的自动化流程。整个智能体的工作流可以拆解成以下几个核心环节:

  1. 信息收集:智能体需要知道你本周的工作内容。我们可以通过多种方式提供,比如直接输入文本、读取你的日历事件、或者连接任务管理工具(如Trello, Jira)。
  2. 周报生成:智能体根据收集到的信息,按照预设的周报模板,生成一份内容充实、结构清晰的周报草稿。
  3. 内容润色与确认:生成初稿后,你可以选择让智能体直接提交,或者先展示给你确认。我们也可以加入一个简单的润色环节,让语言更专业。
  4. 钉钉同步:智能体调用钉钉机器人或OA接口,将最终版的周报内容提交到指定的钉钉群或日志应用中。

为了让这个智能体真正“智能”,我们需要赋予它两种核心能力:

  • 理解与生成能力:由Nanbeige4.1-3B模型本身提供,负责理解你的输入、规划任务步骤、生成周报文本。
  • 执行与操作能力:通过“工具”(Tools)来赋予。我们将为智能体创建几个关键工具函数,例如 search_calendar_events(), generate_weekly_report(), send_to_dingtalk()

智能体的大脑(Nanbeige模型)会根据自己的判断,决定在何时调用何种工具,并处理工具返回的结果,最终完成任务。下面,我们就开始具体的搭建。

3. 环境搭建与模型部署

首先,我们需要一个能运行Nanbeige4.1-3B的环境。这里假设你已经在服务器上准备好了基础环境。

3.1 准备模型与依赖

根据项目说明,模型已经存放在 /root/ai-models/nanbeige/Nanbeige4___1-3B 路径下。我们创建一个新的工作目录来开发我们的智能体。

# 创建项目目录
mkdir -p ~/weekly_report_agent
cd ~/weekly_report_agent

# 创建并激活Python虚拟环境(推荐)
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate  # Windows

# 安装核心依赖
pip install torch transformers accelerate
# 安装用于构建智能体框架的库,这里我们使用简单的LangChain来演示概念
pip install langchain langchain-community
# 安装钉钉SDK
pip install dingtalk-sdk

3.2 加载Nanbeige4.1-3B模型

我们编写一个简单的模块来加载模型,后续供智能体框架调用。

# model_loader.py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from langchain.llms.base import LLM
from typing import Optional, List, Any, Mapping
from pydantic import Field

class NanbeigeLLM(LLM):
    """自定义LangChain LLM封装,用于加载Nanbeige4.1-3B模型"""
    model_path: str = "/root/ai-models/nanbeige/Nanbeige4___1-3B"
    temperature: float = 0.6
    top_p: float = 0.95
    max_new_tokens: int = 1024

    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        # 这里使用一个简化的调用,实际生产环境需要更复杂的会话模板处理
        inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
        with torch.no_grad():
            outputs = self.model.generate(
                **inputs,
                max_new_tokens=self.max_new_tokens,
                temperature=self.temperature,
                top_p=self.top_p,
                do_sample=True
            )
        response = self.tokenizer.decode(outputs[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True)
        return response

    @property
    def _llm_type(self) -> str:
        return "nanbeige-3b"

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        print(f"正在加载模型: {self.model_path}")
        self.tokenizer = AutoTokenizer.from_pretrained(self.model_path, trust_remote_code=True)
        self.model = AutoModelForCausalLM.from_pretrained(
            self.model_path,
            torch_dtype=torch.bfloat16,
            device_map="auto",
            trust_remote_code=True
        )
        print("模型加载完毕!")

# 实例化我们的LLM
llm = NanbeigeLLM()

4. 构建智能体工具与逻辑

智能体的核心是工具。我们来定义几个关键工具。为了简化,我们先模拟工具的功能,你可以根据实际情况替换为真实的API调用。

4.1 定义工具函数

# tools.py
import json
from datetime import datetime, timedelta
from typing import Dict, List

def get_week_summary_from_input(user_input: str) -> str:
    """
    工具1:从用户输入中提取本周工作摘要。
    在实际应用中,这里可以替换为从日历API、任务管理系统API读取数据。
    """
    # 这里我们直接返回用户输入作为模拟。
    # 更智能的做法是让模型先对输入进行总结和结构化。
    return f"用户提供的本周工作摘要:{user_input}"

def generate_report_with_template(summary: str, template: str) -> str:
    """
    工具2:根据摘要和周报模板生成周报草稿。
    """
    # 这是一个简单的模板填充。更高级的做法是让LLM根据摘要和模板自由发挥。
    report_draft = template.replace("{{WEEKLY_SUMMARY}}", summary)
    report_draft += f"\n\n生成时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
    return report_draft

def polish_report_content(draft: str) -> str:
    """
    工具3:对周报草稿进行润色(例如,优化措辞,检查格式)。
    """
    # 这里我们构造一个提示词,让LLM进行润色。
    polish_prompt = f"""
    请对以下周报草稿进行润色,使其语言更专业、条理更清晰、重点更突出。直接返回润色后的完整内容。

    周报草稿:
    {draft}
    """
    # 在实际调用中,这里应该调用 llm(polish_prompt)
    # 为演示,我们模拟一个润色后的结果
    polished = draft + "\n\n【已由智能体润色,语言更加精炼】"
    return polished

def send_report_to_dingtalk(report_content: str, webhook_url: str) -> Dict:
    """
    工具4:将周报内容发送到钉钉。
    需要先在钉钉群添加自定义机器人,并获取其Webhook地址。
    """
    import requests
    import json

    headers = {'Content-Type': 'application/json'}
    # 钉钉机器人消息格式
    data = {
        "msgtype": "markdown",
        "markdown": {
            "title": "每周工作周报",
            "text": f"**本周工作周报**\n\n{report_content}"
        }
    }
    # 注意:实际发送需要替换为你的真实webhook_url,并处理安全设置(如加签)
    # response = requests.post(webhook_url, headers=headers, data=json.dumps(data))
    # return response.json()
    print(f"[模拟] 正在发送周报到钉钉,Webhook: {webhook_url}")
    print(f"[模拟] 发送内容预览:\n{report_content[:200]}...")
    return {"errcode": 0, "errmsg": "ok", "模拟状态": "发送成功"}

# 定义一个周报模板
WEEKLY_REPORT_TEMPLATE = """
**一、本周工作总结 (YYYY-MM-DD ~ YYYY-MM-DD)**
{{WEEKLY_SUMMARY}}

**二、重点项目/任务进展**
1.  **项目A**: 已完成XXX,当前进度YY%。
2.  **项目B**: 进行中,遇到了ZZZ问题,已通过AAA方案解决。

**三、遇到的问题与解决方案**
-   问题1: ...
-   解决方案: ...

**四、下周工作计划**
1.  计划1: ...
2.  计划2: ...

**五、所需支持/资源**
-   无 / 需要...
"""

4.2 构建智能体执行流程

现在,我们将工具和模型组合起来,形成一个简单的顺序执行流程。在更复杂的框架中,你可以使用LangChain的AgentExecutor来让模型自主决定调用哪个工具。

# agent_workflow.py
from tools import *
from model_loader import llm
import json

def run_weekly_report_agent(user_input: str, dingtalk_webhook: str = None):
    """
    运行周报智能体的主流程
    """
    print("="*50)
    print("智能体启动:开始处理周报任务")
    print("="*50)

    # 步骤1:收集信息
    print("\n[步骤1] 信息收集...")
    weekly_summary = get_week_summary_from_input(user_input)
    print(f"收集到摘要:{weekly_summary[:100]}...")

    # 步骤2:生成周报草稿
    print("\n[步骤2] 生成周报草稿...")
    report_draft = generate_report_with_template(weekly_summary, WEEKLY_REPORT_TEMPLATE)
    print("草稿生成完成。")

    # 步骤3:润色周报(可选)
    print("\n[步骤3] 润色周报内容...")
    final_report = polish_report_content(report_draft)
    print("润色完成。")

    # 展示最终周报
    print("\n" + "="*50)
    print("生成的周报内容:")
    print("="*50)
    print(final_report)
    print("="*50)

    # 步骤4:同步到钉钉(如果提供了Webhook)
    if dingtalk_webhook:
        print(f"\n[步骤4] 同步周报到钉钉...")
        result = send_report_to_dingtalk(final_report, dingtalk_webhook)
        if result.get('errcode') == 0:
            print("✅ 周报已成功同步至钉钉!")
        else:
            print(f"❌ 钉钉同步失败:{result}")
    else:
        print("\n⚠️  未提供钉钉Webhook,跳过同步步骤。")

    print("\n" + "="*50)
    print("智能体任务执行完毕!")
    print("="*50)
    return final_report

# 模拟运行
if __name__ == "__main__":
    # 假设这是用户输入的本周工作
    my_week_input = """
    本周主要完成了智能体项目POC开发,包括环境搭建、模型加载测试和基础工具链编写。
    参加了两次技术方案评审会。解决了部署环境中一个CUDA版本兼容性问题。
    下周计划完成智能体的钉钉集成和UI界面优化。
    """
    # 替换成你的钉钉机器人Webhook地址
    dingtalk_url = "https://oapi.dingtalk.com/robot/send?access_token=your_token_here"

    # 运行智能体(暂时注释掉钉钉同步,先测试生成)
    report = run_weekly_report_agent(my_week_input) #, dingtalk_url)

运行这个脚本,你将看到智能体一步步执行,并输出生成的周报。虽然现在看起来是一个脚本顺序执行,但我们已经搭好了骨架。接下来,我们要让Nanbeige模型成为真正的“大脑”,来指挥这些工具。

5. 进阶:让模型自主规划与调用工具

上面的流程是固定的。一个真正的智能体应该能根据你的目标(“帮我写周报并发到钉钉”),自己决定先做什么、后做什么。我们需要用上Nanbeige4.1-3B的工具调用能力。

这里我们使用一个简化的逻辑来模拟智能体的思考过程:

# advanced_agent.py
from model_loader import llm
from tools import WEEKLY_REPORT_TEMPLATE, send_report_to_dingtalk
import re

class WeeklyReportAgent:
    def __init__(self):
        self.available_tools = {
            "get_summary": "从用户输入提取本周工作摘要。",
            "generate_draft": "根据摘要和模板生成周报草稿。",
            "polish_content": "对文本内容进行润色,使其更专业。",
            "send_to_dingtalk": "将最终周报内容发送到钉钉群。"
        }
        self.conversation_history = []

    def _think_and_plan(self, user_goal: str) -> List[str]:
        """让模型根据目标规划工具调用步骤"""
        planning_prompt = f"""
        你是一个周报助手智能体。你的目标是:{user_goal}。
        你可以使用以下工具:
        {json.dumps(self.available_tools, indent=2, ensure_ascii=False)}

        请规划出完成这个目标需要按顺序调用哪些工具(列出工具名即可)。
        例如:["get_summary", "generate_draft", "polish_content", "send_to_dingtalk"]
        请直接返回一个JSON列表,不要有其他解释。
        """
        # 调用Nanbeige模型进行规划
        # 注意:实际中需要更复杂的提示工程来确保返回格式正确
        plan_text = llm._call(planning_prompt)
        # 简单提取JSON列表
        try:
            plan = json.loads(plan_text)
        except json.JSONDecodeError:
            # 如果模型返回的不是纯JSON,尝试提取
            match = re.search(r'\[.*\]', plan_text)
            if match:
                plan = json.loads(match.group())
            else:
                plan = ["get_summary", "generate_draft", "polish_content", "send_to_dingtalk"] # 默认计划
        print(f"智能体规划的执行步骤:{plan}")
        return plan

    def execute_plan(self, user_input: str, user_goal: str, dingtalk_webhook: str = None):
        """执行规划好的步骤"""
        print("🤖 智能体开始思考规划...")
        plan = self._think_and_plan(user_goal)

        context = {"user_input": user_input, "dingtalk_webhook": dingtalk_webhook}
        report_content = ""

        for step in plan:
            print(f"\n▶️  执行步骤:{step}")
            if step == "get_summary":
                # 模拟工具执行
                context['summary'] = f"提取自用户输入:{context['user_input']}"
                print(f"   结果:{context['summary'][:80]}...")
            elif step == "generate_draft":
                draft = WEEKLY_REPORT_TEMPLATE.replace("{{WEEKLY_SUMMARY}}", context.get('summary', ''))
                context['draft'] = draft
                report_content = draft
                print("   结果:周报草稿已生成。")
            elif step == "polish_content":
                # 这里可以真正调用llm进行润色
                polished = context.get('draft', '') + "\n\n【内容已优化】"
                context['final_report'] = polished
                report_content = polished
                print("   结果:周报已润色。")
            elif step == "send_to_dingtalk" and dingtalk_webhook:
                if 'final_report' in context:
                    result = send_report_to_dingtalk(context['final_report'], dingtalk_webhook)
                    print(f"   结果:钉钉同步状态 - {result.get('模拟状态')}")
            else:
                print(f"   警告:未知或跳过的工具 '{step}'")

        print("\n🎉 智能体执行流程结束。")
        return report_content

# 使用进阶智能体
if __name__ == "__main__":
    agent = WeeklyReportAgent()
    goal = "根据我提供的工作内容,生成一份专业的周报,并发送到钉钉工作群。"
    user_input = "本周完成了项目后端APIv2的开发与测试,修复了3个关键Bug。下周启动前端联调。"
    
    final_report = agent.execute_plan(user_input, goal) #, dingtalk_webhook=your_webhook)
    print("\n最终生成的周报:")
    print(final_report)

这个进阶版本展示了智能体的核心思想:模型规划,工具执行。Nanbeige4.1-3B根据我们的目标,自主规划出需要调用 get_summary -> generate_draft -> polish_content -> send_to_dingtalk 这一系列工具。在实际更成熟的框架中,这一步会更加自动和鲁棒。

6. 总结与展望

通过上面的步骤,我们完成了一个基于Nanbeige4.1-3B的自动周报智能体从零到一的构建。我们来回顾一下关键点:

  • 模型选型精准:Nanbeige4.1-3B以其优秀的指令遵循、工具调用能力和低部署成本,成为构建垂直领域智能体的理想选择。
  • 架构清晰:我们将系统分解为信息收集、报告生成、内容润色和钉钉同步四个模块,并通过工具函数的形式实现,耦合度低,易于扩展。
  • 智能体思维:从固定流程升级到让模型自主规划,体现了智能体的核心价值——理解意图并自主完成任务。

下一步可以如何优化?

  1. 信息源集成:将 get_week_summary_from_input 工具替换为真实的集成。例如,连接你的Google Calendar、Jira、GitLab,自动拉取会议、任务和代码提交记录,让信息收集完全自动化。
  2. 使用成熟的Agent框架:将核心逻辑迁移到LangChain、AutoGen或CrewAI等框架中。这些框架提供了更强大的工具调用、记忆管理和多智能体协作能力。
  3. 增加交互与确认:在关键步骤(如发送钉钉前)加入用户确认环节,提高系统的可控性。
  4. 个性化与学习:让智能体学习你过往周报的写作风格和常用词汇,使生成的周报更符合你的个人习惯。
  5. 部署为常驻服务:可以将其封装成一个Web API或钉钉机器人,设定每周五下午自动触发,实现真正的“无人值守”。

这个项目不仅仅是一个周报工具,更是一个小型AI智能体的开发范本。你可以用同样的模式(Nanbeige4.1-3B + 自定义工具),去解决会议纪要生成、数据报告分析、客服自动应答等无数个具体场景的问题。动手试试吧,你会发现,让AI成为你的高效助手,其实并不复杂。


获取更多AI镜像

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

更多推荐