探索 LLM:从基础原理到 RAG 实现的深度解析

一.LLM基础知识

1.1 大语言模型(Large Language Model,LLM)

  1. 他是模型,是 AI 能力的核心。
  2. 他是语言模型,其核心能力在于语言能力。
  3. 他是大语言模型,与传统模型相比,它最大的特点就是“大”。

1.2 AI应用

  1. AI应用,就是以 LLM 为核心的各种应用
  2. 从API的角度理解GPT模型,它最核心的参数就是输入一个或多个字符串,然后,大模型输出一个字符串
  3. 与传统的应用开发不同的是,这个 API 并非是传统应用开发中按照特定预期处理的结果。
  4. 使用传统的 API,我们需要关注的是接口文档,而想要发挥 LLM 的威力,我们需要对大模型有一定的了解

1.3 大模型原理

  1. 一次添加一个词
  2. 下一个词是什么
  3. token
  4. 温度(Temperature):表示随机性强弱的概念
    这个参数越小,表示确定性越强,越大,表示随机性越强,简单理解就是,温度越高越活跃
  5. Embedding :在大模型内部处理的是向量,,Embedding 是一种将高维数据(如文本、图像、视频等)转换为低维向量表示的技术。这种技术在自然语言处理(NLP)、计算机视觉等领域有着广泛的应用。Embedding 的核心思想是将离散数据映射到连续的向量空间,使得相似的数据点在向量空间中的距离较近,而不相似的数据点则距离较远。

1.4 promot工程

  1. 提示词 = 定义角色 + 背景信息 + 任务目标 + 输出要求
  2. 要求:大模型处理复杂任务场景的能力
  3. 原因:Agent背后的技术能让大模型推断下一步行为,利用大模型的推理能力,依赖于promot工程
  4. 起源:Natural Language Processing(NLP):如果给予 AI 适当的引导,它能更准确地理解我们的意图,响应我们的指令
  5. 零样本提示(Zero-Shot Prompting):适合简单的任务。比如,一些简单查询就可以使用零样本提示。我们需要做的就是调整提示词
  6. 少样本提示(Few-Shot Prompting):适合复杂的任务。比如,我们需要让 AI 回答一个问题,我们需要提供一些例子,让 AI 学习这些例子,然后再回答问题。
  7. 思维链提示(Chain-of-Thought Prompting):思维链提示给出的答案则是带有完整的思考过程,是一个“慢下来”的答案,于是得到了一个正确的答案
  8. ReAct 框架(Reasoning + Acting) :推理 + 行动=大模型为了完成一个大目标,需要不断地做一些任务。每个任务都会经历思考(Thought)、行动(Action)、观察(Observation)三个阶段。

二.LLM-Code

2.1 Open AI API

  • Text Generation:生成和处理文本
  • Embeddings:文本转向量
  • Speech to Text:语音转文本
  • Image Generation:生成图像
  • Vision:处理图像输入

2.2 SSE

  • SSE 是服务器发送事件(Server-Sent Event),它是一种服务器推送技术,客户端通过 HTTP 连接接收来自服务器的自动更新
  • 它描述了服务器如何在建立初始客户端连接后向客户端发起数据传输。
  1. 为啥不用WebSocket
  • SSE 的技术特点契合流式应答的需求:客户端与大模型的交互是一次性的,每产生一个 token,服务端就可以给客户端推送一次,当生成内容结束时,断掉连接,无需考虑客户端的存活情况
  • 如果采用 WebSocket 的话,服务端就需要维护连接,像 OpenAI 这样的服务体量,维护连接就会造成很大的服务器压力,而且,在生成内容场景下,也没有向服务端进一步发送内容,WebSocket 的双向通信在这里也是多余的
  • SSE 这项技术而言,它存在已经很长时间了,2004 年就有人提出,大模型才流行起来

2.3 核心的三个抽象

  • ChatModel:整个框架的核心,根据输入的内容生成输出
  • PromptTemplate: 负责处理输入,有效拆分开发者提示词和用户提示词
  • OutputParser:负责处理输出,许多输出解析器里包含了格式指令

2.4 编码实现

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate 
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableWithMessageHistory # 设置 API 密钥
api_key = "你的密钥"
# 初始化 ChatOpenAI 实例时传递 API 密钥
chat_model = ChatOpenAI(model="gpt-4o-mini", api_key=api_key)
store = {}
def get_session_history(session_id: str) -> BaseChatMessageHistory:if session_id not in store:store[session_id] = InMemoryChatMessageHistory()return store[session_id]
prompt = ChatPromptTemplate.from_messages([("system","你现在扮演程序员的角色,可以直接生成代码",),MessagesPlaceholder(variable_name="messages"),]
)
with_message_history = RunnableWithMessageHistory(prompt | chat_model,get_session_history
)
config = {"configurable": {"session_id": "chatLLMCode"}}
while True:user_input = input("You:> ")if user_input.lower() == 'exit':breakstream = with_message_history.stream({"messages": [HumanMessage(content=user_input)]},config=config)for chunk in stream:print(chunk.content, end='', flush=True)print()

三.RAG

3.1 检索增强生成(Retrieval Augmented Generation,RAG)

  1. 检索增强生成(Retrieval Augmented Generation,RAG)是一种结合了检索和生成的技术,它可以在生成文本时,利用外部的知识库来增强生成的内容。
  2. 检索增强生成:在本地检索到相关的内容,把它增强到提示词里,然后再去做内容生成
    产生背景:

* 让LLM知道自己的行业知识,有两种方式

  1. 模型微调:使用业务信息对已经训练好的模型进行微调
  2. RAG:在上下文中带有业务信息,让大模型据此进行整合

3.2 Embeddings和VectorStore

  1. Embeddings:Embeddings 是一种将高维数据(如文本、图像、视频等)转换为低维向量表示的技术。这种技术在自然语言处理(NLP)、计算机视觉等领域有着广泛的应用。Embeddings 的核心思想是将离散数据映射到连续的向量空间,使得相似的数据点在向量空间中的距离较近,而不相似的数据点则距离较远。
  2. VectorStore:VectorStore 是一种用于存储和检索向量数据的技术。它可以将高维向量数据存储在一个向量空间中,以便快速查找相似的向量。VectorStore 的核心思想是将高维数据映射到低维向量空间,以便进行高效的相似度搜索。
    3.索引(Indexing):索引是一种用于快速查找数据的技术。它可以将数据存储在一个索引中,以便快速查找数据。索引的核心思想是将数据映射到一个索引空间中,以便进行高效的查找。
  3. 相似度搜索(Similarity Search):相似度搜索是一种用于查找与给定向量最相似的向量的技术。它可以将给定的向量与索引中的向量进行比较,以便找到最相似的向量。相似度搜索的核心思想是将给定的向量映射到索引空间中,以便进行高效的查找。

3.3 索引过程

  1. 首先,我们需要将文本数据转换为向量。这可以通过使用 Embeddings 技术来实现。
  2. 然后,我们需要将向量存储在一个向量空间中。这可以通过使用 VectorStore 技术来实现。
  3. 最后,索引把信息放到向量数据库中,而检索就是把信息提取出来,提取出来的信息与用户提示词合并起来,再到大模型去完成生成

RAG 是为了让大模型知道更多的东西。

3.4 RAG的实现

# 导入 operator 模块中的 itemgetter 函数,用于从字典中获取指定键的值
from operator import itemgetter
# 导入 typing 模块中的 List 类型,用于定义列表类型的变量
from typing import List
# 导入 tiktoken 库,用于计算字符串中的 token 数量
import tiktoken
# 从 langchain_core.messages 模块中导入各种消息类和消息修剪函数
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage, ToolMessage, SystemMessage, trim_messages
# 从 langchain_core.chat_history 模块中导入聊天历史类
from langchain_core.chat_history import BaseChatMessageHistory, InMemoryChatMessageHistory
# 从 langchain_core.prompts 模块中导入提示模板类和消息占位符类
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# 从 langchain_core.runnables 模块中导入可运行传递类
from langchain_core.runnables import RunnablePassthrough
# 从 langchain_core.runnables.history 模块中导入带有消息历史的可运行类
from langchain_core.runnables.history import RunnableWithMessageHistory
# 从 langchain_openai 模块中导入 OpenAIEmbeddings 类,用于生成文本的嵌入向量
from langchain_openai import OpenAIEmbeddings
# 从 langchain_openai.chat_models 模块中导入 ChatOpenAI 类,用于与 OpenAI 的聊天模型进行交互
from langchain_openai.chat_models import ChatOpenAI
# 从 langchain_chroma 模块中导入 Chroma 类,用于与 Chroma 向量数据库进行交互
from langchain_chroma import Chroma# 创建一个 Chroma 向量数据库实例,指定集合名称为 "rag",嵌入函数为 OpenAIEmbeddings(),持久化目录为 "vectordb"
vectorstore = Chroma(collection_name="rag",embedding_function=OpenAIEmbeddings(),persist_directory="vectordb"
)# 将向量数据库转换为检索器,使用相似度搜索类型
retriever = vectorstore.as_retriever(search_type="similarity")# 定义一个函数,用于计算字符串中的 token 数量
def str_token_counter(text: str) -> int:# 获取 "o200k_base" 编码enc = tiktoken.get_encoding("o200k_base")# 返回编码后的字符串长度return len(enc.encode(text))# 定义一个函数,用于计算消息列表中的 token 数量
def tiktoken_counter(messages: List[BaseMessage]) -> int:# 初始化 token 数量为 3num_tokens = 3# 每个消息的 token 数量为 3tokens_per_message = 3# 每个名称的 token 数量为 1tokens_per_name = 1# 遍历消息列表for msg in messages:# 如果消息是人类消息,设置角色为 "user"if isinstance(msg, HumanMessage):role = "user"# 如果消息是 AI 消息,设置角色为 "assistant"elif isinstance(msg, AIMessage):role = "assistant"# 如果消息是工具消息,设置角色为 "tool"elif isinstance(msg, ToolMessage):role = "tool"# 如果消息是系统消息,设置角色为 "system"elif isinstance(msg, SystemMessage):role = "system"# 如果消息类型不支持,抛出异常else:raise ValueError(f"Unsupported messages type {msg.__class__}")# 累加 token 数量num_tokens += (tokens_per_message+ str_token_counter(role)+ str_token_counter(msg.content))# 如果消息有名称,累加名称的 token 数量if msg.name:num_tokens += tokens_per_name + str_token_counter(msg.name)# 返回 token 数量return num_tokens# 创建一个消息修剪器,设置最大 token 数量为 4096,策略为 "last",token 计数器为 tiktoken_counter,包括系统消息
trimmer = trim_messages(max_tokens=4096,strategy="last",token_counter=tiktoken_counter,include_system=True,
)# 创建一个空字典,用于存储会话历史
store = {}# 定义一个函数,用于获取会话历史
def get_session_history(session_id: str) -> BaseChatMessageHistory:# 如果会话 ID 不存在,创建一个新的内存聊天历史实例if session_id not in store:store[session_id] = InMemoryChatMessageHistory()# 返回会话历史实例return store[session_id]# 创建一个 ChatOpenAI 实例,用于与 OpenAI 的聊天模型进行交互
model = ChatOpenAI()# 创建一个聊天提示模板,包含系统消息、历史消息占位符和人类消息
prompt = ChatPromptTemplate.from_messages([("system","""You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.Context: {context}""",),MessagesPlaceholder(variable_name="history"),("human", "{question}"),]
)# 定义一个函数,用于格式化文档列表
def format_docs(docs):# 返回格式化后的文档字符串return "\n\n".join(doc.page_content for doc in docs)# 创建一个上下文获取器,通过检索器获取相关文档,并格式化文档
context = itemgetter("question") | retriever | format_docs
# 创建第一个步骤,将上下文赋值给 "context" 键
first_step = RunnablePassthrough.assign(context=context)
# 创建一个链,将第一个步骤、提示模板、消息修剪器和聊天模型连接起来
chain = first_step | prompt | trimmer | model# 创建一个带有消息历史的可运行实例,将链、会话历史获取器、输入消息键和历史消息键连接起来
with_message_history = RunnableWithMessageHistory(chain,get_session_history=get_session_history,input_messages_key="question",history_messages_key="history",
)# 设置配置,指定会话 ID 为 "dreamhead"
config = {"configurable": {"session_id": "dreamhead"}}# 无限循环
while True:# 获取用户输入user_input = input("You:> ")# 如果用户输入为 "exit",退出循环if user_input.lower() == 'exit':break# 如果用户输入为空,继续循环if user_input.strip() == "":continue# 使用带有消息历史的可运行实例处理用户输入,并获取流式响应stream = with_message_history.stream({"question": user_input}, config=config)# 逐块打印流式响应内容for chunk in stream:print(chunk.content, end='', flush=True)# 打印换行符print()

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

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

相关文章

Mac cursor设置jdk、Maven版本

基本配置 – Cursor 使用文档 首先是系统用户级别的设置参数,运行cursor,按下ctrlshiftp,输入Open User Settings(JSON),在弹出的下拉菜单中选中下面这样的: 在打开的json编辑器中追加下面的内容: {"…

ARM64平台Flutter环境搭建

ARM64平台Flutter环境搭建 Flutter简介问题背景搭建步骤1. 安装ARM64 Android Studio2. 安装Oracle的JDK3. 安装 Dart和 Flutter 开发插件4. 安装 Android SDK5. 安装 Flutter SDK6. 同意 Android 条款7. 运行 Flutter 示例项目8. 修正 aapt2 报错9. 修正 CMake 报错10. 修正 N…

基于海思soc的智能产品开发(视频的后续开发)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 前面我们讨论了camera,也讨论了屏幕驱动,这些都是基础的部分。关键是,我们拿到了这些视频数据之后,…

vue3+webOffice合集

1、webOffice 初始化 1)officeType: 文档位置:https://solution.wps.cn/docs/web/quick-start.html#officetype 2)appId: 前端使用appId 后端需要用到AppSecret 3)fileId: 由后端返回,前端无法生成,与上传文…

2025牛客寒假算法营2

A题 知识点&#xff1a;模拟 打卡。检查给定的七个整数是否仅包含 1,2,3,5,6 即可。为了便于书写&#xff0c;我们可以反过来&#xff0c;检查这七个整数是否不为 4 和 7。 时间 O(1)&#xff1b;空间 O(1)。 #include <bits/stdc.h> using namespace std;signed main()…

记录一次k8s起不来的排查过程

我在k8s集群&#xff0c;重启了一个node宿主机&#xff0c;竟然发现kubelet起不来了&#xff01;报错如下 这个报错很模糊&#xff0c;怎么排查呢。这样&#xff0c;开两个界面&#xff0c;一个重启kubelet&#xff0c;一个看系统日志(/var/log/message:centos&#xff0c;/va…

仿 RabbitMQ 的消息队列3(实战项目)

七. 消息存储设计 上一篇博客已经将消息统计文件的读写代码实现了&#xff0c;下一步我们将实现创建队列文件和目录。 实现创建队列文件和目录 初始化 0\t0 这样的初始值. //创建队列对应的文件和目录&#xff1a;public void createQueueFile(String queueName) throws IO…

HTTP 配置与应用(局域网)

想做一个自己学习的有关的csdn账号&#xff0c;努力奋斗......会更新我计算机网络实验课程的所有内容&#xff0c;还有其他的学习知识^_^&#xff0c;为自己巩固一下所学知识&#xff0c;下次更新HTTP 配置与应用&#xff08;不同网段&#xff09;。 我是一个萌新小白&#xf…

大模型应用与部署 技术方案

大模型应用与部署 技术方案 一、引言 人工智能蓬勃发展,Qwen 大模型在自然语言处理领域地位关键,其架构优势尽显,能处理文本创作等多类复杂任务,提供优质交互。Milvus 向量数据库则是向量数据存储检索利器,有高效索引算法(如 IVF_FLAT、HNSWLIB 等)助力大规模数据集相似…

【Prometheus】Prometheus如何监控Haproxy

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Go语言中的值类型和引用类型特点

一、值类型 值类型的数据直接包含值&#xff0c;当它们被赋值给一个新的变量或者作为参数传递给函数时&#xff0c;实际上是创建了原值的一个副本。这意味着对新变量的修改不会影响原始变量的值。 Go中的值类型包括&#xff1a; 基础类型&#xff1a;int&#xff0c;float64…

GPT 结束语设计 以nanogpt为例

GPT 结束语设计 以nanogpt为例 目录 GPT 结束语设计 以nanogpt为例 1、简述 2、分词设计 3、结束语断点 1、简述 在手搓gpt的时候&#xff0c;可能会遇到一些性能问题&#xff0c;即关于是否需要全部输出或者怎么节约资源。 在输出语句被max_new_tokens 限制&#xff0c…

深入MapReduce——计算模型设计

引入 通过引入篇&#xff0c;我们可以总结&#xff0c;MapReduce针对海量数据计算核心痛点的解法如下&#xff1a; 统一编程模型&#xff0c;降低用户使用门槛分而治之&#xff0c;利用了并行处理提高计算效率移动计算&#xff0c;减少硬件瓶颈的限制 优秀的设计&#xff0c…

macOS安装Gradle环境

文章目录 说明安装JDK安装Gradle 说明 gradle8.5最高支持jdk21&#xff0c;如果使用jdk22建议使用gradle8.8以上版本 安装JDK mac系统安装最新&#xff08;截止2024.9.13&#xff09;Oracle JDK操作记录 安装Gradle 下载Gradle&#xff0c;解压将其存放到资源java/env目录…

五国十五校联合巨献!仿人机器人运动与操控:控制、规划与学习的最新突破与挑战

作者&#xff1a; Zhaoyuan Gu, Junheng Li, Wenlan Shen, Wenhao Yu, Zhaoming Xie, Stephen McCrory, Xianyi Cheng, Abdulaziz Shamsah, Robert Griffin, C. Karen Liu, Abderrahmane Kheddar, Xue Bin Peng, Yuke Zhu, Guanya Shi, Quan Nguyen, Gordon Cheng, Huijun Gao,…

【BQ3568HM开发板】如何在OpenHarmony上通过校园网的上网认证

引言 前面已经对BQ3568HM开发板进行了初步测试&#xff0c;后面我要实现MQTT的工作&#xff0c;但是遇到一个问题&#xff0c;就是开发板无法通过校园网的认证操作。未认证的话会&#xff0c;学校使用的深澜软件系统会屏蔽所有除了认证用的流量。好在我们学校使用的认证系统和…

(Java版本)基于JAVA的网络通讯系统设计与实现-毕业设计

源码 论文 下载地址&#xff1a; ​​​​c​​​​​​c基于JAVA的网络通讯系统设计与实现(源码系统论文&#xff09;https://download.csdn.net/download/weixin_39682092/90299782https://download.csdn.net/download/weixin_39682092/90299782 第1章 绪论 1.1 课题选择的…

SpringCloud微服务Gateway网关简单集成Sentinel

Sentinel是阿里巴巴开源的一款面向分布式服务架构的轻量级流量控制、熔断降级组件。Sentinel以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度来帮助保护服务的稳定性。 官方文档&#xff1a;https://sentinelguard.io/zh-cn/docs/introduction.html …

vscode环境中用仓颉语言开发时调出覆盖率的方法

在vscode中仓颉语言想得到在idea中利用junit和jacoco的覆盖率&#xff0c;需要如下几个步骤&#xff1a; 1.在vscode中搭建仓颉语言开发环境&#xff1b; 2.在源代码中右键运行[cangjie]coverage. 思路1&#xff1a;编写了测试代码的情况&#xff08;包管理工具&#xff09; …

pikachu靶场-敏感信息泄露概述

敏感信息泄露概述 由于后台人员的疏忽或者不当的设计&#xff0c;导致不应该被前端用户看到的数据被轻易的访问到。 比如&#xff1a; ---通过访问url下的目录&#xff0c;可以直接列出目录下的文件列表; ---输入错误的url参数后报错信息里面包含操作系统、中间件、开发语言的版…