跳至主要内容

零基础教程 | 使用 Amazon Bedrock 和 DeepSeek 模型搭建企业智能客服系统(基于 Flask)

前言

本教程将引导您快速构建一个智能客服系统,结合 Amazon Bedrock、DeepSeek 大模型和企业知识库,通过 Flask 框架搭建 Web 服务,实现智能问答功能。本教程专注于 Flask 应用的本地搭建和功能实现,适合希望在本地环境中测试和开发智能客服系统的企业用户。对于未来计划将系统部署到微信公众号、网页客服或内部系统的用户,Flask 应用也可以作为后端服务,便于与这些平台进行集成。

前提条件

难度:初级

时间:20 分钟

所需费用:参考 Bedrock 价格页面

受众:业务开发人员

相关产品:Amazon Bedrock

上次更新时间:2025 年 5 月 12 日

示例代码:有

相关行业:通用

前提条件:亚马逊云科技海外区域账户,Amazon Bedrock 及相关模型使用权限

1. 登录亚马逊云科技海外区域账号

全部打开

2. 企业知识数据的准备与导入

全部打开

    • 在控制台顶部搜索栏中输入“S3”,点击进入 Amazon S3 控制台

    • 点击【Create bucket】(创建存储桶),输入存储桶名称

    • 填写存储桶名字,其他设置保持默认,再次点击【Create bucket】(创建存储桶)

    • 创建完成后,点击进入该 bucket

    • 点击【Upload】(上传)

    • 上传你的知识文档,例如 PDF、DOCX、TXT、HTML 等格式的文件

    • 例如,我们将一份 txt 格式的 “2025 年公司考勤管理制度” 上传到 S3 存储桶(其中做了一些自定义设置,以便于验证知识库调用)

3. 开通 Amazon Bedrock 和 DeepSeek 模型权限

全部打开

    • 在 AWS 控制台的搜索框中输入 “Bedrock”,然后点击 Amazon Bedrock

    • 进入 Amazon Bedrock 页面后,找到页面中的 “Model access”(模型访问)设置板块,仔细检查自身账号是否已具备 DeepSeek 的使用权限

    • 如果没有 DeepSeek 模型的使用权限,可点击页面上的 “申请” 按钮获得权限。

4. 创建企业知识库(Knowledge base)

全部打开

    • 返回 Bedrock 控制台,点击左侧【Knowledge Base】(知识库),进入知识库管理页面。

    • 点击【Create】(创建),根据准备的数据类型,选择开始创建流程

    • 自定义知识库名称 Knowledge Base Name:如 company - kb

    • 设置知识库数据来源:选择 S3,因为要连接到我们刚才上传的 S3 存储桶

    • 设置完成,点击【next】(下一步)

    • 选择 S3 数据源

    • 选择我们上传文档的 S3 Bucket

    • 继续点击【next】(下一步)

    • 设置嵌入模型:

    • 建议选择 Amazon Titan Embeddings(Bedrock 原生)

    • 设置向量存储:这里可以保留默认 (Amazon OpenSearch Serverless)

    • 点击【next】(下一步) 后,确认设置,点击【Create knowledge base】(创建知识库)。

    • 等待几分钟,知识库文档会自动进行解析、嵌入并构建索引。

5. 使用 Python 基于知识库调用 DeepSeek 模型

全部打开

    • 安装 Python,可以使用 Anaconda,一键装好 Python 和虚拟环境 ,安装完成后,打开 “Anaconda Prompt”

    • 在 Anaconda Prompt 中输入以下代码,创建并进入项目文件夹:

    mkdir flask_chatbot

    cd flask_chatbot

    • 创建虚拟环境

      conda create -n flask_bot_env python=3.10

      conda activate flask_bot_env

    • 为 Python 安装必要库:

      pip install flask boto3 langchain langchain-community python-dotenv

    • 继续在 Anaconda Prompt 中配置 AWS 登录授权

      aws configure

    • 这里需要输入你的:AWS Access Key ID,AWS Secret Access Key,默认 Region

    • 以上这些信息可以在 AWS 的 IAM 中获取或者新建 access key,具体 IAM 使用方法可参考相关教程

    • 在 Anaconda Prompt 中创建项目环境设置.env 文件:

    echo AWS_DEFAULT_REGION=xxx(你的bedrock所在区域)> .env

    echo AWS_ACCESS_KEY_ID=xxx (你的ACCESS_KEY_ID)>> .env

    echo AWS_SECRET_ACCESS_KEY=xxx (你的SECRET_ACCESS_KEY)>>> .env

    • 成功后,会在项目文件夹中看到 .env文件

    • 创建主文件 app.py 保存在项目文件夹中

    • Python 文件代码如下:

      import os

      import logging

      from flask import Flask, render_template, request, jsonify

      from flask_cors import CORS

      import boto3

      from dotenv import load_dotenv

      # 加载环境变量

      load_dotenv()

      # 初始化 Flask 应用

      app = Flask(__name__)

      CORS(app)

      # 设置日志

      logging.basicConfig(level=logging.INFO)

      logger = logging.getLogger(__name__)

      # 初始化 AWS 会话

      session = boto3.Session(

      aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),

      aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),

      region_name=os.getenv("AWS_DEFAULT_REGION", "us-east-1")

      )

      # 初始化 Bedrock 客户端

      bedrock_runtime = session.client("bedrock-runtime")

      bedrock_agent = session.client("bedrock-agent-runtime")

      # 配置参数

      # 使用 Amazon DeepSeek 的跨区域推理配置文件 ARN

      MODEL_ARN = "你的 model ARN" # 可替换为其他模型

      KNOWLEDGE_BASE_ID = "你的知识库ID" # 在控制台查看 Knowledge Base ID

      @app.route("/")

      def home():

      return render_template("index.html")

      @app.route("/chat", methods=["POST"])

      def chat():

      try:

      data = request.get_json()

      user_message = data.get("message", "").strip()

      if not user_message:

      return jsonify({"message": "消息不能为空"}), 400

      logger.info(f"用户输入: {user_message}")

      logger.info("开始连接知识库并生成回答...")

      # 调用 Bedrock Agent 进行知识库检索和生成回答

      response = bedrock_agent.retrieve_and_generate(

      input={"text": user_message},

      retrieveAndGenerateConfiguration={

      "type": "KNOWLEDGE_BASE",

      "knowledgeBaseConfiguration": {

      "knowledgeBaseId": KNOWLEDGE_BASE_ID,

      "modelArn": MODEL_ARN,

      "retrievalConfiguration": {

      "vectorSearchConfiguration": {

      "numberOfResults": 3

      }

      },

      "generationConfiguration": {

      "inferenceConfig": {

      "textInferenceConfig": {

      "temperature": 0.3,

      "maxTokens": 1024,

      "topP": 0.9

      }

      },

      "promptTemplate": {

      "textPromptTemplate": """\n\nHuman: 请根据以下知识库内容用中文回答问题:

      <context>

      $search_results$

      </context>

      问题: $input$

      \n\nAssistant:"""

      }

      }

      }

      }

      )

      logger.info("成功连接知识库,生成回答完成。")

      # 提取回答内容

      bot_reply = response.get("output", {}).get("text", "未能生成回答")

      # 提取引用来源

      citations = response.get("citations", [])

      sources = []

      for c in citations:

      references = c.get("retrievedReferences", [])

      for ref in references:

      s3_uri = ref.get("location", {}).get("s3Location", {}).get("uri", "")

      excerpt = ref.get("content", {}).get("text", "")[:100]

      sources.append({

      "title": s3_uri.split("/")[-1] if s3_uri else "未知文档",

      "excerpt": excerpt + "..."

      })

      return jsonify({

      "message": bot_reply,

      "sources": sources

      })

      except Exception as e:

      logger.error(f"请求失败: {str(e)}", exc_info=True)

      return jsonify({"message": f"请求失败: {str(e)}"}), 500

      if name == "__main__":

      app.run(host="0.0.0.0", port=5000, debug=True)

    • 在代码中的配置参数部分,需要填入知识库 ID 和 model ARN.

    • 知识库 ID 可以在 Bedrock 的 knowledge base 中找到

    • 在项目文件夹中创建客服对话面

    • index.html 代码可以参考如下:

      <!DOCTYPE html>

      <html lang="zh-CN">

      <head>

      <meta charset="UTF-8">

      <meta name="viewport" content="width=device-width, initial-scale=1.0">

      <title>智能客服助手</title>

      <style>

      body {

      font-family: 'Arial', sans-serif;

      max-width: 800px;

      margin: 0 auto;

      padding: 20px;

      background-color: #f5f5f5;

      }

      #chat-container {

      background: white;

      border-radius: 10px;

      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);

      overflow: hidden;

      }

      #chat-box {

      height: 500px;

      padding: 20px;

      overflow-y: auto;

      }

      .message {

      margin-bottom: 15px;

      padding: 10px 15px;

      border-radius: 18px;

      max-width: 70%;

      word-wrap: break-word;

      }

      .user-message {

      background: #007bff;

      color: white;

      margin-left: auto;

      }

      .bot-message {

      background: #e9ecef;

      color: black;

      margin-right: auto;

      }

      #input-area {

      display: flex;

      padding: 15px;

      background: #f8f9fa;

      border-top: 1px solid #ddd;

      }

      #user-input {

      flex: 1;

      padding: 10px;

      border: 1px solid #ddd;

      border-radius: 20px;

      outline: none;

      }

      #send-button {

      margin-left: 10px;

      padding: 10px 20px;

      background: #007bff;

      color: white;

      border: none;

      border-radius: 20px;

      cursor: pointer;

      }

      </style>

      </head>

      <body>

      <div id="chat-container">

      <div id="chat-box"></div>

      <div id="input-area">

      <input type="text" id="user-input" placeholder="输入消息..." />

      <button id="send-button">发送</button>

      </div>

      </div>

      <script>

      const chatBox = document.getElementById("chat-box");

      const userInput = document.getElementById("user-input");

      function addMessage(role, content) {

      const messageDiv = document.createElement("div");

      messageDiv.classList.add("message", ${role}-message);

      messageDiv.textContent = content;

      chatBox.appendChild(messageDiv);

      chatBox.scrollTop = chatBox.scrollHeight;

      }

      document.getElementById("send-button").addEventListener("click", sendMessage);

      userInput.addEventListener("keypress", (e) => {

      if (e.key === "Enter") sendMessage();

      });

      function sendMessage() {

      const message = userInput.value.trim();

      if (!message) return;

      addMessage("user", message);

      userInput.value = "";

      fetch("/chat", {

      method: "POST",

      headers: { "Content-Type": "application/json" },

      body: JSON.stringify({ message })

      })

      .then(response => response.json())

      .then(data => {

      addMessage("bot", data.message);

      })

      .catch(error => {

      addMessage("bot", "服务暂时不可用,请稍后再试");

      console.error("Error:", error);

      });

      }

      </script>

      </body>

      </html>

    • 在项目根目录中放置 requirements.txt 文件,其中内容如下:

      flask==3.0.3

      boto3==1.36.3

      flask-cors==5.0.1

      python-dotenv==0.21.0

    • 完成以上准备后,最终项目文件夹的结构如下:

    • 现在,您已经成功配置了 Flask 应用,并集成了 Amazon Bedrock 上的 DeepSeek 模型和企业知识库。可以通过以下命令在 Anaconda Prompt 中运行 app.py 文件,启动智能客服系统。

    • 运行 app.py 启动 Flask 服务后,使用浏览器访问 http://127.0.0.1:5000/,可以加载出flask框架下的智能客服

    • 我们尝试提出与知识库内容相关的问题,程序成功通过 Amazon Bedrock 的 API 调用了 DeepSeek 模型,并基于预设的知识库提供了准确的回答。例如,当我们询问“公司考勤制度是怎么样的?”时,系统会结合上传的考勤制度文件,生成详尽的解答。

6. 退出/清理环境

全部打开

    Amazon Bedrock 控制台中的 Playground 属于即开即用型服务,使用完毕后无需额外退出操作即可结束会话,无需担心资源占用问题。但需要注意的是,知识库底层依赖的 Amazon OpenSearch Serverless(用于向量化数据的存储与检索)会单独计费。因此,如果确定短期内不再使用该知识库,建议按照以下顺序清理资源,以避免产生不必要的费用:

    • 在 Bedrock 里面删除 knowledge base

    • 在 OpenSearch 里面删除 collections

    • 在 S3 服务中删除上传的 S3 文件:

小结

全部打开

    通过本教程的 6 个步骤,您已成功搭建了一个企业级的知识库问答系统。整个流程主要在 Amazon Bedrock 控制台中完成,几乎无需编写代码,适合零基础用户快速上手。企业可以持续上传更多文档至 S3 存储桶,丰富知识库内容。该系统适用于多种场景,如员工培训、客户支持、产品问答等,有效提升信息获取效率。

费用评估和优惠

目前通过 Bedrock 调用 DeepSeek 费用可以参考 Bedrock 价格页面,费用可使用新版免费套餐获得的服务抵扣金抵扣