跳至主要内容

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

前言

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

前提条件

难度:初级

时间:20 分钟

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

受众:业务开发人员

相关产品:Amazon Bedrock

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

示例代码:有

相关行业:通用

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

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

全部打开

  • 登录你的 AWS 账号。

 

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 价格页面,费用可使用新版免费套餐获得的服务抵扣金抵扣