SpringAI+DeepSeek大模型应用开发——2 大模型应用开发架构

目录

2.大模型开发

2.1 模型部署

2.1.1 云服务-开放大模型API

2.1.2 本地部署

搜索模型

运行大模型

2.2 调用大模型

接口说明

提示词角色

​编辑

会话记忆问题

2.3 大模型应用开发架构

2.3.1 技术架构

纯Prompt模式

FunctionCalling

RAG检索增强

Fine-tuning

2.3.2 技术选型

2.大模型开发

2.1 模型部署

首先大模型应用开发并不是在浏览器中跟AI聊天。而是通过访问模型对外暴露的API接口,实现与大模型的交互

因此,需要有一个可访问的大模型,通常有三种选择:

2.1.1 云服务-开放大模型API

部署在云服务器上,部署维护简单,部署方案简单,全球访问 ,缺点:数据隐私,网络依赖,长期成本问题

通常发布大模型的官方、大多数的云平台都会提供开放的、公共的大模型服务。以下是一些国内提供大模型服务的云平台

这些开放平台并不是免费,而是按照调用时消耗的token来付费,每百万token通常在几毛~几元钱,而且平台通常都会赠送新用户百万token的免费使用权;

以百炼大模型为例 大模型服务平台百炼_企业级大模型开发平台_百炼AI应用构建-阿里云

注册一个阿里云账号==>然后访问百炼平台,开通服务(首次开通应该会赠送百万token的使用权,包括DeepSeek-R1模型、qwen模型。)

==>申请API_KEY(百炼平台右上角个人中心)==>创建APIKEY==>进入模型广场

选择一个自己喜欢的模型,然后点击API调用示例,即可进入API文档页===>立即体验==>进入API调用大模型的试验台==>模拟调用大模型接口

2.1.2 本地部署

数据安全,不依赖网络,成本低,缺点:初期成本高,部署麻烦周期长

最简单的方案是使用ollama Download Ollama on macOS,当然这种方式不推荐,阉割版

访问官网下载查看对应模型的本地调用即可

OllamaSetup.exe所在目录打开cmd命令行,然后输入命令如下:

OllamaSetup.exe /DIR=你要安装的目录位置

安装完成后,还需要配置一个环境变量,更改Ollama下载和部署模型的位置。配置完成如图:

搜索模型
  • Ollama是一个模型管理工具和平台,它提供了很多国内外常见的模型,可以在其官网上搜索自己需要的模型:Ollama Search;

  • 搜索DeepSeek-R1后,进入DeepSeek-R1页面,会发现DeepSeek-R1也有很多版本:

运行大模型

选择自己电脑合适的模型后,Ollama会给出运行模型的命令: 打开cmd运行即可

ollama run deepseek-r1:7b  #运行大模型
/bye   #退出当前大模型
ollama ps #查看运行的大模型

Ollama是一个模型管理工具,有点像Docker,而且命令也很像,常见命令如下:

ollama serve      # Start ollama
ollama create     # Create a model from a Modelfile
ollama show       # Show information for a model
ollama run        # Run a model
ollama stop       # Stop a running model
ollama pull       # Pull a model from a registry
ollama push       # Push a model to a registry
ollama list       # List models
ollama ps         # List running models
ollama cp         # Copy a model
ollama rm         # Remove a model
ollama help       # Help about any command

2.2 调用大模型

调用大模型并不是在浏览器中跟AI聊天,而是通过访问模型对外暴露的API接口,实现与大模型的交互;所以要学习大模型应用开发,就必须掌握模型的API接口规范

目前大多数大模型都遵循OpenAI的接口规范,是基于Http协议的接口。因此请求路径、参数、返回值信息都是类似的,可能会有一些小的差别。具体需要查看大模型的官方API文档。

以DeepSeek官方给出的文档为例:

# Please install OpenAI SDK first: `pip3 install openai`from openai import OpenAI# 1.初始化OpenAI客户端,要指定两个参数:api_key、base_url
client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")# 2.发送http请求到大模型,参数比较多
response = client.chat.completions.create(# 2.1.选择要访问的模型model="deepseek-chat",# 2.2.发送给大模型的消息messages=[{"role": "system", "content": "You are a helpful assistant"},{"role": "user", "content": "Hello"},],# 2.3.是否以流式返回结果stream=False
)
print(response.choices[0].message.content)
接口说明
  • 请求方式:通常是POST,因为要传递JSON风格的参数;

  • 请求路径:与平台有关

    • DeepSeek官方平台:https://api.deepseek.com;

    • 阿里云百炼平台:https://dashscope.aliyuncs.com/compatible-mode/v1;

    • 本地ollama部署的模型:http://localhost:11434;

  • 安全校验:开放平台都需要提供API_KEY来校验权限,本地Ollama则不需要;

  • 请求参数:参数很多,比较常见的有:

    • model:要访问的模型名称;

    • messages:发送给大模型的消息,是一个数组;

    • stream

      • true,代表响应结果流式返回;

      • false,代表响应结果一次性返回,但需要等待;

    • temperature:取值范围[0:2),代表大模型生成结果的随机性,越小随机性越低。DeepSeek-R1不支持;

  • 注意,这里请求参数中的messages是一个消息数组,而且其中的消息要包含两个属性:

    • role:消息对应的角色;

    • content:消息内容;也被称为提示词(Prompt),也就是发送给大模型的指令。

提示词角色

常用的消息的角色有三种:

其中System类型的消息非常重要!影响了后续AI会话的行为模式;

  • 比如,当我们询问AI对话产品(文心一言、DeepSeek等)“你是谁” 这个问题的时候,每一个AI的回答都不一样,这是怎么回事呢?

  • 这其实是因为AI对话产品并不是直接把用户的提问发送给LLM,通常都会在user提问的前面通过System消息给模型设定好背景

  • 所以,当你问问题时,AI就会遵循System的设定来回答了。因此,不同的大模型由于System设定不同,回答的答案也不一样;

## Role
System: 你是邓超
## Example
User: 你是谁
Assisant: 到!gogogo,黑咖啡品味有多浓!我只要汽水的轻松,大热天做个白日梦,梦见我变成了彩虹
我是邓超啊!哈哈,你没看错,就是那个又帅又幽默的邓超!怎么样,是不是被我的魅力惊到了?😎 
会话记忆问题

为什么要把历史消息都放入Messages中,形成一个数组呢?

这是因为大模型是没有记忆的,因此在调用API接口与大模型对话时,每一次对话信息都不会保留,但是可以发现AI对话产品却能够记住每一轮对话信息,根据这些信息进一步回答,这是怎么回事呢?

答案就是Messages数组;

只需要每一次发送请求时,都把历史对话中每一轮的User消息、Assistant消息都封装到Messages数组中,一起发送给大模型,这样大模型就会根据这些历史对话信息进一步回答,就像是拥有了记忆一样;

2.3 大模型应用开发架构

2.3.1 技术架构

目前,大模型应用开发的技术架构主要有四种

纯Prompt模式

不同的提示词能够让大模型给出差异巨大的答案;

不断雕琢提示词,使大模型能给出最理想的答案,这个过程就叫做提示词工程(Prompt Engineering);

很多简单的AI应用,仅仅靠一段足够好的提示词就能实现了,这就是纯Prompt模式;流程如图:

FunctionCalling

大模型虽然可以理解自然语言,更清晰地弄懂用户意图,但是确无法直接操作数据库、执行严格的业务规则。这个时候就可以整合传统应用与大模型的能力了;

  1. 把传统应用中的部分功能封装成一个个函数(Function);

  2. 在提示词中描述用户的需求,并且描述清楚每个函数的作用,要求AI理解用户意图,判断什么时候需要调用哪个函数,并且将任务拆解为多个步骤(Agent);

  3. 当AI执行到某一步,需要调用某个函数时,会返回要调用的函数名称、函数需要的参数信息;

  4. 传统应用接收到这些数据以后,就可以调用本地函数。再把函数执行结果封装为提示词,再次发送给AI;

  5. 以此类推,逐步执行,直到达成最终结果。

RAG检索增强

检索增强生成(Retrieval-Augmented Generation,简称RAG)已成为构建智能问答系统的关键技术。

模型从知识角度存在很多限制:

  • 时效性差:大模型训练比较耗时,其训练数据都是旧数据,无法实时更新;

  • 缺少专业领域知识:大模型训练数据都是采集的通用数据,缺少专业数据;

把最新的数据或者专业文档都拼接到提示词,一起发给大模型,不就可以了?

现在的大模型都是基于Transformer神经网络,Transformer的强项就是所谓的注意力机制。它可以根据上下文来分析文本含义

但是,上下文的大小是有限制的,GPT3刚刚出来的时候,仅支持2000个token的上下文。所以海量知识库数据是无法直接写入提示词的;

RAG原理

RAG 的核心原理是将检索技术与生成模型相结合,结合外部知识库或私有数据源来检索相关信息来指导和增强生成模型的输出,有效解决了传统大语言模型的知识更新滞后和"幻觉"问题。

其核心工作流程分为三个阶段:

  1. 接收请求: 首先,系统接收到用户的请求(例如提出一个问题)

  2. 信息检索(R): 系统从一个大型文档库中检索出与查询最相关的文档片段。这一步的目标是找到那些可能包含答案或相关信息的文档。这里不一定是从向量数据库中检索,但是向量数据库能反应相似度最高的几个文档(比如说法不同,意思相同),而不是精确查找

    • 文本拆分:将文本按照某种规则拆分为很多片段;

    • 文本嵌入(Embedding):根据文本片段内容,将文本片段归类存储;

    • 文本检索:根据用户提问的问题,找出最相关的文本片段;

  3. 生成增强(A): 将检索到的文档片段与原始查询一起输入到大模型(如chatGPT)中,注意使用合适的提示词,比如原始的问题是XXX,检索到的信息是YY,给大模型的输入应该类似于: 请基于YYY回答XXXX。

  4. 输出生成(G): 大模型LLM 基于输入的查询和检索到的文档片段生成最终的文本答案,并返回给用户

由于每次都是从向量库中找出与用户问题相关的数据,而不是整个知识库,所以上下文就不会超过大模型的限制,同时又保证了大模型回答问题是基于知识库中的内容;

Fine-tuning

模型微调,就是在预训练大模型(比如DeepSeek、Qwen)的基础上,通过企业自己的数据做进一步的训练,使大模型的回答更符合自己企业的业务需求。这个过程通常需要在模型的参数上进行细微的修改,以达到最佳的性能表现;

在进行微调时,通常会保留模型的大部分结构和参数,只对其中的一小部分进行调整。减少了训练时间和计算资源的消耗。

微调的过程包括以下几个关键步骤:

  1. 选择合适的预训练模型:根据任务的需求,选择一个已经在大量数据上进行过预训练的模型,如Qwen-2.5;

  2. 准备特定领域的数据集:收集和准备与任务相关的数据集,这些数据将用于微调模型;

  3. 设置超参数:调整学习率、批次大小、训练轮次等超参数,以确保模型能够有效学习新任务的特征;

  4. 训练和优化:使用特定任务的数据对模型进行训练,通过前向传播、损失计算、反向传播和权重更新等步骤,不断优化模型的性能;

2.3.2 技术选型
  • 从开发成本由低到高来看,四种方案的排序:Prompt < Function Calling < RAG < Fine-tuning

  • 所以在选择技术时通常也应该遵循"在达成目标效果的前提下,尽量降低开发成本"这一首要原则。然后可以参考以下流程来思考:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901983.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯12. 日期问题

日期问题 原题目链接 题目描述 小明正在整理一批历史文献。这些历史文献中出现了很多日期。 小明知道这些日期都在 1960 年 1 月 1 日 至 2059 年 12 月 31 日 之间。 令小明头疼的是&#xff0c;这些日期采用的格式非常不统一&#xff1a; 有的采用 年/月/日有的采用 月…

STM32使用rand()生成随机数并显示波形

一、随机数生成 1、加入头文件&#xff1a;#include "stdlib.h" 2、定义一个用作生成随机数种子的变量并加入到滴答定时器中不断自增&#xff1a;uint32_t run_times 0; 3、设置种子&#xff1a;srand(run_times);//每次生成随机数前调用一次为佳 4、生成一个随…

『前端样式分享』联系我们卡片式布局 自适应屏幕 hover动效 在wikijs中使用 (代码拿来即用)

目录 预览效果分析要点响应式网格布局卡片样式&#xff1a;阴影和过渡效果 代码优化希望 长短不一的邮箱地址在左右居中的同时,做到左侧文字对齐(wikijs可用)总结 欢迎关注 『前端布局样式』 专栏&#xff0c;持续更新中 欢迎关注 『前端布局样式』 专栏&#xff0c;持续更新中…

【ubuntu】在Linux Yocto的基础上去适配Ubuntu的wifi模块

一、修改wifi的节点名 1.找到wifi模块的PID和VID ifconfig查看wifi模块网络节点的名字&#xff0c;发现是wlx44876393bb3a&#xff08;wlxmac地址&#xff09; 通过udevadm info -a /sys/class/net/wlx44876393bba路径的命令去查看wlx44876393bba的总线号&#xff0c;端口号…

健康养生:开启活力生活新篇章

在当代社会&#xff0c;熬夜加班、久坐不动、外卖快餐成为许多人的生活常态&#xff0c;随之而来的是各种亚健康问题。想要摆脱身体的疲惫与不适&#xff0c;健康养生迫在眉睫&#xff0c;它是重获活力、拥抱美好生活的关键。​ 应对不良饮食习惯带来的健康隐患&#xff0c;饮…

【verilog】多个 if 控制同一个变量(后面会覆盖前面)非阻塞赋值真的并行吗?

非阻塞赋值 (<) 是“并行”的&#xff0c;但是代码顺序会影响结果&#xff1f;”这正是 Verilog 的硬件描述本质 vs 行为语义之间的微妙之处。 &#x1f4a1;1. 非阻塞赋值真的并行吗&#xff1f; 是的&#xff01;非阻塞赋值 < 从行为上是并行的&#xff0c;也就是说&a…

前沿篇|CAN XL 与 TSN 深度解读

引言 1. CAN XL 标准演进与设计目标 2. CAN XL 物理层与帧格式详解 3. 时间敏感网络 (TSN) 关键技术解析 4. CAN XL + TSN 在自动驾驶领域的典型应用

vscode、cherry studio接入高德mcp服务

最近mcp协议比较火&#xff0c;好多平台都已经开通了mcp协议&#xff0c;今天来接入下高德的mcp看看效果如何。 话不多说&#xff0c;咱们直接开干。 先来看下支持mcp协议的工具有cusor、cline等等。更新cherrystudio后发现上面也有mcp服务器了。今天咱就来试试添加高德的mcp协…

Triton(2)——Triton源码接结构

1 triton 3.0.0 源码结构 triton docs/&#xff1a;项目文档 cmake/&#xff1a;构建配置相关 bin/&#xff1a;工具、脚本 CmakeLists.txt&#xff1a;cmake 配置文件 LSCENSE README.md Pyproject.toml&#xff1a;python 项目配置文件 utils/&#xff1a;项目配置文…

React 事件处理基础

React 中最常见的两个需求&#xff0c;一个是列表渲染&#xff0c;另一个就是绑定点击事件。 这一篇就是从最基础的按钮点击开始&#xff0c;分四个阶段&#xff0c;逐步理解 React 中事件的写法和参数传递方式。 &#x1f4cd;阶段一&#xff1a;最简单的点击事件 function A…

java的lambda和stream流操作

Lambda 表达式 ≈ 匿名函数 &#xff08;Lambda接口&#xff09;函数式接口&#xff1a;传入Lambda表达作为函数式接口的参数 函数式接口 只能有一个抽象方法的接口 Lambda 表达式必须赋值给一个函数式接口&#xff0c;比如 Java 8 自带的&#xff1a; 接口名 作用 Functio…

Dify智能体平台源码二次开发笔记(6) - 优化知识库pdf文档的识别

目录 前言 新增PdfNewExtractor类 替换ExtractProcessor类 最终结果 前言 dify的1.1.3版本知识库pdf解析实现使用pypdfium2提取文本&#xff0c;主要存在以下问题&#xff1a; 1. 文本提取能力有限&#xff0c;对表格和图片支持不足 2. 缺乏专门的中文处理优化 3. 没有文档结…

easyExcel单元格合并

环境 java 1.8 easyexcel 3.1.1 实现方式 自定义WriteHandler&#xff0c;实现AbstractMergeStrategy抽象类&#xff0c;实现merge 方法完成自定义的合并操作。 本测试代码&#xff0c;实现了eques方法&#xff0c;用于判断是否需要合并 核心代码 实现AbstractMergeStrate…

Jenkins 简易使用记录

一、Jenkins 核心功能与适用场景 核心功能&#xff1a; 持续集成&#xff08;CI&#xff09;&#xff1a;自动构建代码、运行单元测试。持续交付&#xff08;CD&#xff09;&#xff1a;自动化部署到测试/生产环境。任务调度&#xff1a;定时执行任务&#xff08;如备份、清理&…

【HFP】蓝牙HFP协议音频连接核心技术深度解析

目录 一、音频连接建立的总体要求 1.1 发起主体与时机 1.2 前提条件 1.3 同步连接的建立 1.4 通知机制 二、不同主体发起的音频连接建立流程 2.1 连接建立触发矩阵 2.2 AG 发起的音频连接建立 2.3 HF 发起的音频连接建立 三、编解码器连接建立流程 3.1 发起条件 3.…

【卡洛诗】成为平价市场中的标杆西餐厅

近年来&#xff0c;中国餐饮市场在消费分级趋势下面临结构性调整&#xff0c;消费者对“质价比”的追求催生了新赛道的崛起。在这一背景下&#xff0c;卡洛诗西餐凭借精准的定位与系统性创新&#xff0c;以“中式西餐”为核心理念&#xff0c;成功打破西餐高价壁垒&#xff0c;…

嵌入式设备网络的动态ID分配机制实现

文章目录 前言一、系统设计要点二、核心数据结构2.1 设备唯一标识(DeviceUID)2.2 节点信息(Node)2.3 节点管理器(NodeManager) 三、核心算法实现3.1 初始化与清理3.1.1 初始化节点管理器3.1.2 清理节点管理器 3.2 动态ID分配策略3.2.1 查找最小可用ID3.2.2 ID使用检查 3.3 心跳…

WebSocket 双向通信技术详解

引言 在现代Web应用中&#xff0c;实时通信已经成为不可或缺的一部分。想象一下聊天应用、在线游戏、股票交易平台或协作工具&#xff0c;这些应用都需要服务器能够即时将更新推送给客户端&#xff0c;而不仅仅是等待客户端请求。WebSocket技术应运而生&#xff0c;它提供了一…

kafka菜鸟教程

一、kafka原理 1、kafka是一个高性能的消息队列系统&#xff0c;能够处理大规模的数据流&#xff0c;并提供低延迟的数据传输&#xff0c;它能够以每秒数十万条消息的速度进行读写操作。 二、kafka优点 1、服务解耦 &#xff08;1&#xff09;提高系统的可维护性‌ 通过服务…

SQLMap工具使用

一、SQLMap介绍 SQLMap 是一款强大的开源自动化 SQL 注入工具&#xff0c;用于检测和利用 Web 应用程序中的 SQL 注入漏洞。其工作原理是SQLMap 通过向目标 URL 发送带有特殊构造的 SQL 语句的请求&#xff0c;观察目标应用程序的响应&#xff0c;来判断是否存在 SQL 注入漏洞…