基于DeepSeek手搓一个LLM智能体

前言

Hello,大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者,本系列是作者参加DataWhale2025年2月份组队学习的wow-agent技术笔记文档。今天我将手把手教大家如何用DeepSeek大模型从零构建一个天气查询Agent!

在人工智能技术的发展过程中,语言模型(LLM)已经成为自然语言处理(NLP)的核心。然而,随着需求的变化,单一的语言模型不再足够满足复杂的交互需求。智能体(Agent)的概念应运而生,它能理解、决策并执行任务,而不仅仅是生成语言输出。本文将详细介绍智能体的设计思想、核心组件、优势,并展示如何构建一个自定义的智能体——天气查询 Agent。

OK,我们先介绍一下什么是Agent!🤔


一、什么是 Agent?

1. 定义

Agent(智能体) 是一种能够自主感知环境、决策并采取行动的系统。与传统的语言模型不同,Agent 不仅仅是一个生成文本的工具,而是一个具备决策能力执行能力的智能系统。通过与外部环境(如数据库、API、用户交互等)的交互,Agent 可以完成复杂的任务。

心思想:

  • 自主性:无需人为干预,独立感知环境并作出反应。
  • 灵活性:通过模块化设计,处理多种任务。
  • 可扩展性:通过集成更多服务和功能,持续增强能力。
  • 交互性:与用户和其他系统无缝互动,完成任务。

2. Agent 的核心组件

一个完整的 Agent 通常由以下核心组件构成:

组件功能描述关键技术
感知模块感知外部环境的信息,接收用户输入或外部数据。传感器、输入接口、自然语言理解(NLU)
决策模块根据感知到的信息进行推理和决策,规划下一步行动。机器学习、推理引擎、优化算法
执行模块根据决策模块的输出执行具体操作,如调用 API、操作数据库或生成回复。API 调用、数据库操作、自然语言生成(NLG)
反馈机制评估执行效果并调整决策,持续优化智能体的表现。强化学习、评估指标(如准确率、响应时间)

3. Agent 的优势

优势描述
提高效率自动化执行重复性任务,减少人工干预。
支持复杂任务能够处理多步推理和决策,适用于复杂的任务场景。
适应性强通过持续学习和环境适应,在动态变化的环境中发挥作用。
可扩展性高通过集成更多工具和服务,不断扩展智能体的能力范围。

开源社区上有这么多Agent框架,为什么我们要手搓呢?🤔


二、为什么要"手搓"Agent?

1. 主流框架的局限性

  • 依赖过多:如 Langchain 需要安装大量依赖库,部署复杂。
  • 灵活性不足:框架通常有固定的设计模式,难以完全满足定制化需求。
  • 性能开销:框架的通用性设计可能导致性能损耗,不适合轻量化场景。

2. 手搓 Agent 的优势

优势描述
轻量化仅需核心依赖库(如 openaipython-dotenv),部署简单快速。
高度定制化完全根据需求设计架构,灵活应对不同场景。
性能优化去除框架的冗余功能,专注于核心逻辑,提升执行效率。
学习价值通过手动构建,深入理解 Agent 的工作原理,提升技术能力。

3. 手搓 vs 框架

对比项手搓 Agent使用框架
依赖库数量2 个(openai + python-dotenv通常 50+ 个依赖库
部署时间15 秒内完成15 分钟以上
定制化程度完全自定义受框架限制
学习曲线需要理解底层原理框架提供抽象接口,上手较快
适用场景轻量化、定制化需求复杂任务、快速开发

4.核心价值

  • 快速部署:仅需 2 个依赖库,轻松实现轻量化部署。
  • 灵活扩展:根据需求自由添加功能模块,如数据库连接、API 调用等。
  • 成本控制:减少不必要的依赖,降低资源消耗和运行成本。
  • 技术提升:通过手动构建,深入理解 Agent 的底层逻辑和实现细节。

三、 获取 API 及接口测试

接下来,我们将使用 DeepSeek API 来构建一个简单的智能体。DeepSeek 提供了类似于 OpenAI 的接口,因此非常适合我们测试。以下是获取 API Key 和进行接口测试的步骤。

1. 获取 DeepSeek API Key

  1. 注册登录:首先,前往 DeepSeek 的平台 https://platform.deepseek.com/usage,进行注册并登录。

  1. 创建 API Key:在 DeepSeek 的控制面板中,创建一个新的 API Key,并复制保存。


🧨现在复制保存下来这个API Key即可;请确保妥善保管您的 API Key,避免泄露,否则可能导致经济损失。


2. 测试接口

接下来,我们使用 Python 的 OpenAI SDK 来测试 DeepSeek 接口。

pip3 install openai
from openai import OpenAI

client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[
        {"role": "system", "content": "You are a helpful assistant"},
        {"role": "user", "content": "Hello"},
    ],
    stream=False
)

print(response.choices[0].message.content)

👌实测可用!

3. 环境变量配置

为了防止 API Key 泄露,建议使用环境变量来配置 API Key。

  1. 在项目根目录创建 .env 文件,并设置环境变量:
API_KEY=<Your DeepSeek API Key>
BASE_URL=https://api.deepseek.com
  1. 安装 python-dotenv,用于加载环境变量:
pip install python-dotenv
  1. 在代码中加载环境变量:
from dotenv import load_dotenv
import os
from openai import OpenAI

load_dotenv()

api_key = os.getenv("API_KEY")
base_url = os.getenv("BASE_URL")

client = OpenAI(api_key=api_key, base_url=base_url)

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[
        {"role": "system", "content": "You are a helpful assistant"},
        {"role": "user", "content": "介绍一下你自己!"},
    ],
    stream=False
)

print(response.choices[0].message.content)

在这里插入图片描述
测试通过!


四、构建客服 Agent

1. LangGPT 的概念

LangGPT 是一种结合结构化 Prompt 设计和角色扮演的智能体。我们可以通过定义不同的角色、行为规则和工作流来构建智能体。

结构化 Prompt 的核心思想是将输入分成不同的层级和模块,使模型更容易理解任务的结构。

2. 构建一个智能客服

我们构建一个简单的智能客服,能够处理用户的注册、查询和删除操作。客服根据用户输入判断任务,并调用相应的服务。

定义角色和任务
system_prompt = """你是一个聪明的客服。您将能够根据用户的问题将不同的任务分配给不同的人。您有以下业务线:
1.用户注册。如果用户想要执行这样的操作,您应该发送一个带有"registered workers"的特殊令牌。并告诉用户您正在调用它。
2.用户数据查询。如果用户想要执行这样的操作,您应该发送一个带有"query workers"的特殊令牌。并告诉用户您正在调用它。
3.删除用户数据。如果用户想执行这种类型的操作,您应该发送一个带有"delete workers"的特殊令牌。并告诉用户您正在调用它。
"""
角色和任务模块
registered_prompt = """
您的任务是根据用户信息存储数据。您需要从用户那里获得以下信息:
1.用户名、性别、年龄
2.用户设置的密码
3.用户的电子邮件地址
如果用户没有提供此信息,您需要提示用户提供。如果用户提供了此信息,则需要将此信息存储在数据库中,并告诉用户注册成功。
"""

query_prompt = """
您的任务是查询用户信息。您需要从用户那里获得以下信息:
1.用户ID
2.用户设置的密码
如果用户没有提供此信息,则需要提示用户提供。如果用户提供了此信息,那么需要查询数据库。如果用户ID和密码匹配,则需要返回用户的信息。
"""

delete_prompt = """
您的任务是删除用户信息。您需要从用户那里获得以下信息:
1.用户ID
2.用户设置的密码
3.用户的电子邮件地址
如果用户没有提供此信息,则需要提示用户提供该信息。
"""
实现智能客服类
class SmartAssistant:
    def __init__(self):
        self.client = client

        self.system_prompt = system_prompt
        self.registered_prompt = registered_prompt
        self.query_prompt = query_prompt
        self.delete_prompt = delete_prompt

        # Using a dictionary to store different sets of messages
        self.messages = {
            "system": [{"role": "system", "content": self.system_prompt}],
            "registered": [{"role": "system", "content": self.registered_prompt}],
            "query": [{"role": "system", "content": self.query_prompt}],
            "delete": [{"role": "system", "content": self.delete_prompt}]
        }

        # Current assignment for handling messages
        self.current_assignment = "system"

    def get_response(self, user_input):
        self.messages[self.current_assignment].append({"role": "user", "content": user_input})
        while True:
            response = self.client.chat.completions.create(
                model="deepseek-chat",
                messages=self.messages[self.current_assignment],
                temperature=0.9,
                stream=False,
                max_tokens=2000,
            )

            ai_response = response.choices[0].message.content
            if "registered workers" in ai_response:
                self.current_assignment = "registered"
                self.messages[self.current_assignment].append({"role": "user", "content": user_input})
            elif "query workers" in ai_response:
                self.current_assignment = "query" 
                self.messages[self.current_assignment].append({"role": "user", "content": user_input})
            elif "delete workers" in ai_response: 
                self.current_assignment = "delete" 
                self.messages[self.current_assignment].append({"role": "user", "content": user_input})
                
            return ai_response

完整代码如下:

from dotenv import load_dotenv
import os
from openai import OpenAI

# Load environment variables from .env file
load_dotenv()

# Retrieve API key and base URL from environment variables
api_key = os.getenv("API_KEY")
base_url = os.getenv("BASE_URL")

# Initialize the OpenAI client
client = OpenAI(api_key=api_key, base_url=base_url)

# Define system prompts for different tasks
sys_prompt = """你是一个聪明的客服。您将能够根据用户的问题将不同的任务分配给不同的人。您有以下业务线:
1.用户注册。如果用户想要执行这样的操作,您应该发送一个带有"registered workers"的特殊令牌。并告诉用户您正在调用它。
2.用户数据查询。如果用户想要执行这样的操作,您应该发送一个带有"query workers"的特殊令牌。并告诉用户您正在调用它。
3.删除用户数据。如果用户想执行这种类型的操作,您应该发送一个带有"delete workers"的特殊令牌。并告诉用户您正在调用它。
"""

registered_prompt = """
您的任务是根据用户信息存储数据。您需要从用户那里获得以下信息:
1.用户名、性别、年龄
2.用户设置的密码
3.用户的电子邮件地址
如果用户没有提供此信息,您需要提示用户提供。如果用户提供了此信息,则需要将此信息存储在数据库中,并告诉用户注册成功。
"""

query_prompt = """
您的任务是查询用户信息。您需要从用户那里获得以下信息:
1.用户ID
2.用户设置的密码
如果用户没有提供此信息,则需要提示用户提供。如果用户提供了此信息,那么需要查询数据库。如果用户ID和密码匹配,则需要返回用户的信息。
"""

delete_prompt = """
您的任务是删除用户信息。您需要从用户那里获得以下信息:
1.用户ID
2.用户设置的密码
3.用户的电子邮件地址
如果用户没有提供此信息,则需要提示用户提供该信息。
"""

class SmartAssistant:
    def __init__(self):
        self.client = client

        # Define system prompts for different tasks
        self.system_prompt = sys_prompt
        self.registered_prompt = registered_prompt
        self.query_prompt = query_prompt
        self.delete_prompt = delete_prompt

        # Using a dictionary to store different sets of messages
        self.messages = {
            "system": [{"role": "system", "content": self.system_prompt}],
            "registered": [{"role": "system", "content": self.registered_prompt}],
            "query": [{"role": "system", "content": self.query_prompt}],
            "delete": [{"role": "system", "content": self.delete_prompt}]
        }

        # Current assignment for handling messages
        self.current_assignment = "system"

    def get_response(self, user_input):
        # Append user input to the current assignment's messages
        self.messages[self.current_assignment].append({"role": "user", "content": user_input})

        # Get response from the AI model
        response = self.client.chat.completions.create(
            model="deepseek-chat",
            messages=self.messages[self.current_assignment],
            temperature=0.9,
            stream=False,
            max_tokens=2000,
        )

        # Extract AI response
        ai_response = response.choices[0].message.content

        # Check for special tokens and switch assignment if necessary
        if "registered workers" in ai_response:
            self.current_assignment = "registered"
            self.messages[self.current_assignment].append({"role": "user", "content": user_input})
        elif "query workers" in ai_response:
            self.current_assignment = "query"
            self.messages[self.current_assignment].append({"role": "user", "content": user_input})
        elif "delete workers" in ai_response:
            self.current_assignment = "delete"
            self.messages[self.current_assignment].append({"role": "user", "content": user_input})

        return ai_response

# Example usage
if __name__ == "__main__":
    assistant = SmartAssistant()
    while True:
        user_input = input("You: ")
        if user_input.lower() in ["exit", "quit"]:
            break
        response = assistant.get_response(user_input)
        print(f"Assistant: {response}")

运行测试:
在这里插入图片描述
运行成功,一切正常!🙂


五、构建一个天气查询Agent

1. 构建思路

这个天气查询 Agent 会通过与 DeepSeek 的 API 交互,接收用户输入的城市或地点,查询该地点的天气情况,并返回给用户。我们需要将天气查询的功能嵌入到一个 Agent 中。

为了实现这个功能,我们需要几个步骤:

  1. 获取天气信息(通过外部 API,例如 高德天气API)。
  2. 处理用户输入,判断是否包含查询天气的指令。
  3. 如果用户输入的是查询天气的请求,就通过调用天气 API 获取信息。
  4. 输出天气信息。

高德天气API申请教程看这里:https://blog.csdn.net/qq_51055690/article/details/126885110

2. 代码实现

import openai
import os
from dotenv import load_dotenv
import requests

# 加载环境变量
load_dotenv()

# 配置 OpenAI API 和 DeepSeek API
api_key = os.getenv("API_KEY")
base_url = os.getenv("BASE_URL")

# 设置 DeepSeek 客户端
client = openai.OpenAI(api_key=api_key, base_url=base_url)

# 高德地图天气 API
weather_api_key = os.getenv("WEATHER_API_KEY")
weather_base_url = "https://restapi.amap.com/v3/weather/weatherInfo"

class WeatherAgent:
    def __init__(self):
        self.client = client
        self.system_prompt = "你是一个智能助手,能够提供天气查询服务。请用户提供城市名,查询并返回当地的天气情况。"
        self.messages = [{"role": "system", "content": self.system_prompt}]
    
    def get_weather_info(self, city_name):
        """查询天气信息(带错误处理)"""
        params = {
            'key': weather_api_key,
            'city': city_name,
            'extensions': 'base',
            'output': 'JSON'
        }
        
        try:
            response = requests.get(weather_base_url, params=params)
            response.raise_for_status()  # 自动触发HTTP错误
            
            weather_data = response.json()
            if weather_data.get('status') != '1':
                return f"请求失败:{weather_data.get('infocode', '未知错误')}"
                
            lives = weather_data.get('lives', [])
            if not lives:
                return "该城市无天气数据"
                
            live_data = lives[0]
            return (
                f"当前天气:{live_data['weather']}\n"
                f"温度:{live_data['temperature']}°C\n"
                f"湿度:{live_data['humidity']}%\n"
                f"更新时间:{live_data['reporttime']}"
            )
            
        except requests.exceptions.RequestException as e:
            return f"网络请求失败:{str(e)}"
        except KeyError as e:
            return f"数据解析错误:缺少字段 {str(e)}"

    def get_response(self, user_input):
        """改进后的响应逻辑"""
        self.messages.append({"role": "user", "content": user_input})
        
        # 通过AI识别城市名(更精准)
        prompt = f"""
        用户问:{user_input}
        请严格按以下格式回答,只需返回城市名,提取的城市要符合查询标准,尽量是标准城市命名:
        {{
            "city": "提取到的城市名"
        }}
        如果无法识别则返回:{{"city": null}}
        """
        
        # 调用模型提取城市
        extraction_response = self.client.chat.completions.create(
            model="deepseek-chat",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.3,
            max_tokens=50
        )
        
        # 解析城市名
        try:
            city_info = eval(extraction_response.choices[0].message.content)
            city_name = city_info.get('city')
        except:
            city_name = None
        
        if city_name:
            weather_info = self.get_weather_info(city_name)
            return weather_info
        else:
            # 普通对话
            response = self.client.chat.completions.create(
                model="deepseek-chat",
                messages=self.messages,
                temperature=0.7,
                stream=False,
                max_tokens=1000
            )
            return response.choices[0].message.content

# 测试
if __name__ == "__main__":
    agent = WeatherAgent()
    
    test_cases = [
        "北京天气怎么样?",
        "上海市浦东新区今天会下雨吗",
        "帮我查一个不存在的城市的天气",  # 测试错误处理
        "讲个笑话"
    ]
    
    for query in test_cases:
        print(f"用户:{query}")
        print(f"助手:{agent.get_response(query)}\n")

3. 代码解释

环境变量加载
load_dotenv()  # 加载环境变量
api_key = os.getenv("API_KEY")
base_url = os.getenv("BASE_URL")
weather_api_key = os.getenv("WEATHER_API_KEY")

通过 .env 文件加载 API 密钥,避免硬编码敏感信息。

天气查询接口
weather_base_url = "https://restapi.amap.com/v3/weather/weatherInfo"

我们使用 高德地图 提供的天气查询 API。你可以注册 高德天气地图 获取 API Key。

WeatherAgent 类
  • get_weather_info:调用 OpenWeatherMap API 获取天气信息。返回天气、温度、湿度等数据。
  • get_response:根据用户输入的指令生成智能回应。如果用户请求查询天气,则调用 get_weather_info 获取并返回天气数据。
测试输入
    test_cases = [
        "北京天气怎么样?",
        "上海市浦东新区今天会下雨吗",
        "帮我查一个不存在的城市的天气",  # 测试错误处理
        "讲个笑话"
    ]

4. 如何运行

  • 安装所需的库:
pip install openai python-dotenv requests
  • 在项目根目录创建 .env 文件,添加以下内容:
API_KEY=你的DeepSeek API密钥
BASE_URL=https://api.deepseek.com
WEATHER_API_KEY=你的OpenWeatherMap API密钥
  • 运行 Python 脚本,输入天气查询请求,Agent 会返回天气信息。

运行结果如下:
在这里插入图片描述


运行测试通过!没有问题,今天我们就学到这里!😉👌🎉

文章参考

项目地址


thank_watch

如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.

内容概要:本文详细介绍了最强开源推理模型DeepSeek R1的本地部署和调用方法。首先概述了DeepSeek R1的核心特性及其在多个领域的优秀表现,包括使用强化学习技术显著提升模型推理能力,并与OpenAI同类型的顶级模型媲美。然后,深入探讨了部署过程的具体步骤,强调DeepSeek R1在DeepSeek V3基础上进行了有监督细调后再经强化学习训练而成的独特性。文中还提到了本地运行的支持方式,包括但不限于通过GitHub项目获取必要的代码和工具、通过HuggingFace和魔搭平台下载模型权重。具体部署过程中涉及到的工具包涵盖转换模型权重的convert.py、文本生成功能的generate.py以及其他用于推理加速的重要组件。针对不同的硬件和软件需求,官方推荐了诸如TensorRT-LLM、SG-Lang等框架,并分别阐述其特点及应用场景。对于希望简化部署难度的人群,文档提到Ollama、SGLang、LMDeploy和vLLM等多种高效的调用方法,其中Ollama可以一键部署,而LMDeploy支持高性能的在线服务调用。最后简述了几种典型的模型调用示例,方便读者快速开始尝试DeepSeek R1的使用。 适合人群:具有计算机背景的专业开发人员、科研工作者或者希望探索前沿大模型应用的学生和技术爱好者。 使用场景及目标:适用于想要理解和使用DeepSeek R1模型的研究员,以及希望通过该模型构建或改进产品的企业级用户;目标在于指导用户顺利完成DeepSeek R1的本地部署、了解各个辅助工具的特点、掌握多种调用方式的具体命令与参数配置。 其他说明:建议感兴趣的用户关注最新的更新日志和技术文档以保持信息同步;此外,鼓励参与社区讨论和贡献反馈来促进项目的不断完善和发展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GISer Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值