生成式AI是一种能够生成各类内容的技术,包括文本、图像、音频和合成数据。大语言模型(Large Language Model, LLM)经过海量文本数据的训练后,能将这些文本数据以一种黑盒形式压缩在模型参数中。预训练完成后,模型便掌握了大量的人类世界知识。研究者发现,当模型的规模足够大且经过指令微调对齐后,便可通过提示模板,运用零样本(zero-shot)或少样本(few-shot)的提示词来完成许多自然语言理解和自然语言生成任务。但是大模型并不具备在环境不断变化的场景中回答特定问题所需的全面知识。

针对这种问题,一般有三种解决方式:

1.RAG(Retrieval Augmented Generation)

2020年,Facebook在“Retrieval-AugmentedGeneration for Knowledge-Intensive NLP Tasks”一文中首先提出了一种称为检索增强生成(RAG)的框架。该框架可以使模型访问超出其训练数据范围之外的信息,使得模型在每次生成时可以利用检索提供的外部更专业、更准确的知识,从而更好地回答用户问题。

RAG在推理过程中分为两个阶段:检索和内容生成。在检索阶段,通过算法检索与用户问题相关的知识片段。在开放领域中,这些知识片段可以来自互联网上搜索引擎检索到的文档,例如微软Bing AI的模式;在私有领域的企业场景中,通常使用大量的内部文档通过更小的信息源约束来提高模型生成的安全性和可靠性。完成检索之后,可以获取到一些与用户输入相关的可靠外部知识。在内容生成阶段,通过一个结构化的prompt模板约束,将这些外部知识添加到用户的问题中,并传递给语言模型。模型基于知识增强的prompt,通过自己的大量参数计算,就可以生成一个针对该用户问题的更准确的答案。

RAG具体执行时包括三个环节,首先对用户问题进行处理,这个过程通常称为嵌入(embedding),然后从向量库中根据相似度取出跟问题最相关的内容,最后把检索出的内容作为问题的上下文一起发给大模型,通过大模型来生成符合我们习惯的回答。通过向量库的检索,大模型可以掌握原本训练过程中不了解的知识。

2.微调(Fine Tunning)

所谓微调就是对大模型在自己的数据上进行微调。大模型微调的核心是 “保留预训练知识,适配下游任务”,能以较低成本让通用大模型具备场景化能力,是落地大模型应用的关键手段。通过对大模型进行微调,同样可以使大模型具有业务知识,也可以进行知识更新,但是大模型微调需要较高的GPU计算资源,并且较为复杂,训练数据准备也要耗费不少时间。因此,如果对于知识不断变化的场景,会频繁进行微调,成本较高。

3.提示工程(Prompt Engineering)

不同的问题描述方式会导致LLM回答质量的差异。因此,学会如何更好地向LLM描述问题变得非常重要。ChatGPT的爆火推动了prompt工程的兴起,它旨在优化和开发提示词,以便更高效地利用LLM解决各种实际问题。目前,在某些场景下,LLM很难准确理解用户意图,因此我们需要更详细地描述问题才能获得更好的答案。相比RAG和微调,提示工程最简单,因为不需要做额外的工作,但是由于没有加入新的知识,因此大模型所回答的内容依然仅依赖于它原本训练过程中获取到的知识,除非在提示词中把新的知识在上下文中输入到大模型。

这三种技术各有优劣,在不同的场景下可以具体应用。RAG的相关教程现在很多,我这里主要举几个例子,起到抛砖引玉的作用。

要使用RAG,我可以先把需要文档存入到向量库中,这里我们使用FAISS。然后根据相似度查询匹配度最高的内容:

#--------------测试向量库FAISS--------------
from langchain_ollama import OllamaEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.docstore.document import Document
raw_documents = [Document(page_content="葡萄", metadata={"source": "local"}),
Document(page_content="白菜", metadata={"source": "local"}),
Document(page_content="狗", metadata={"source": "local"})]
embeddings = OllamaEmbeddings(model="bge-m3:567m")
db = FAISS.from_documents(raw_documents, embeddings)
query = "动物"
docs = db.similarity_search(query)
print(docs[0].page_content)
# 输出:狗

这里可以看到,我们先把“葡萄”、“白菜”、“狗”作为原始文本,通过embedding模型,对文本进行嵌入操作,然后把embedding后的文本向量存储到向量库中,最后根据查询的问题去寻找相似度最高的文本。

可以看到,构建RAG向量库的基本流程都是如此的方式。

下面我们看一个简单的查询例子,假设我想构建一个动漫知识库,存储一些热门动漫。我这里有个《龙珠》的简单介绍,我想要存储到向量库中,并进行提问。原始文本如下:

孙悟空是《龙珠》系列的核心主人公,来自贝吉塔行星的赛亚人,以乐观、勇敢和对战斗的热爱贯穿全篇。
### 核心身份与背景
原名卡卡罗特,婴儿时期被送往地球,因头部撞击失去赛亚人侵略本性,被地球人孙悟饭收养长大。
赛亚人天生热爱战斗,拥有越战越强的体质,还有变身超级赛亚人等强大形态的能力。
### 关键性格特质
纯真善良,对世界充满好奇,不谙世事却坚守正义底线。
战斗狂热,遇强则强,始终追求更强的对手和更高的实力境界。
重视亲情与友情,愿意为保护家人、伙伴和地球付出一切,甚至牺牲自己。
### 成长与成就
从懵懂的山野少年起步,历经无数战斗,结识布尔玛、克林、贝吉塔等挚友。
多次拯救地球于毁灭危机,击败弗利萨、沙鲁、布欧等强敌,成为宇宙级的强者。
始终保持谦逊,即便实力顶尖,仍不断修炼突破,从未停止变强的脚步。
### 核心攻击型绝招
龟派气功:最具代表性的招式,双手合十积蓄能量后推出冲击波,可根据实力提升威力,是常用的远程攻击手段。
元气弹:集合周围生物的元气凝聚成巨大能量球,威力极强且只对邪恶目标生效,多次在决战中扭转战局。
龙拳爆发:将能量集中于拳头,打出形似巨龙的冲击,爆发力惊人,常用于近距离重创强敌。
近身与辅助型招式
舞空术:通过控制能量实现飞行,是后期战斗和移动的基础技能。
瞬间移动:从 Yardrat 星习得,能感知对方气息并瞬间转移到指定地点,兼具逃生、支援和突袭功能。
赛亚人变身:不算直接招式但核心能力,从超级赛亚人到超蓝、超本能等形态,变身後全方面提升战斗力,配合招式发挥更强威力。
衍生与组合招式
界王拳:通过倍数提升自身战斗力,初期常用,后期多与变身形态结合使用,但会对身体造成负荷。
分身术:分裂出多个自身分身,用于迷惑对手或同时攻击,实力随本体强度同步。

我们这里先用文档加载器把txt文本加载进来,然后通过RecursiveCharacterTextSplitter类对文档进行分段,分段也是一个影响RAG效果的非常关键步骤,不同的分段策略可能导致RAG的效果有很大的差别。我这里选择每500个字分段,并设定以换行符作为分段标志。分段后的文档再进行embedding操作,存入到向量库。查询的时候,系统会先去向量库中寻找问题相关的内容,再和问题一起提交给大模型,从而得到结果。

from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langchain_ollama import OllamaEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.docstore.document import Document
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 数据加载与文本切块
loader = TextLoader('2.txt', encoding='utf-8') # 定义加载器
documents = loader.load() # 加载文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0, separators=["\n"]) # 定义一个文档切分器
chunks = text_splitter.split_documents(documents) # 切分文档
template = """
你是一位问答助手,你的任务是根据###中间的文本信息回答问题,请准确回答问题,不要健谈,如果提供的文本信息无法回答问题,请直接回复“提供的文本无法回答问题”,
我相信你能做得很好。###\n{context}###\n 问题:{question}
"""
question = "卡卡罗特的绝招有哪些?"
# 写入向量数据库,获取检索器
embeddings = OllamaEmbeddings(model="bge-m3:567m")
db = FAISS.from_documents(chunks, embeddings)
retriever = db.as_retriever(search_kwargs={"k": 2})
# 召回和问题相关的文本
context = retriever.get_relevant_documents(question)
print(context)
context_str = "; ".join([doc.page_content for doc in context])
input_str = template.format_map({"context":context_str, "question":question})
chat = ChatOpenAI(
streaming=True,
model='deepseek-chat',
openai_api_key='<你的API KEY>',
openai_api_base='https://api.deepseek.com',
max_tokens=1024
)
messages = [
SystemMessage(content="你是一位问答助手"),
HumanMessage(content=input_str)
]
response = chat(messages)
print(response.content)

根据控制台的输出,我们可以看到系统找到的分段,并且给出了正确的结果,而且我们这里问的是卡卡罗特,而文档里面一开始说的是孙悟空,说明大模型自动识别了卡卡罗特就是孙悟空。

下面我用streamlit作为前端界面框架,做了一个简单的例子,我们可以针对向量库中的内容进行查询,并可以添加新的文档到向量库中,增加文档的知识。首先构建一个可以操作向量库的工具文件:

# 例子,动漫RAG
# 存储和获取向量库
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain_ollama import OllamaEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import Docx2txtLoader
def load_word_file(file_path):
loader = Docx2txtLoader(file_path)
data = loader.load()
return data
text_splitter = RecursiveCharacterTextSplitter(
separators=["\n","\n\n"],
chunk_size=500,
chunk_overlap=0,
length_function=len,
is_separator_regex=False
)
def add_word(filename, index_name):
# Word
docs = load_word_file(filename)
documents = text_splitter.split_documents(docs)
embeddings = OllamaEmbeddings(model="bge-m3:567m")
vector = FAISS.load_local("faiss_index_word", embeddings, allow_dangerous_deserialization=True)
vector.add_documents(documents)
vector.save_local("faiss_index_word")
def get(index_name):
embeddings = OllamaEmbeddings(model="bge-m3:567m")
vector = FAISS.load_local(index_name, embeddings, allow_dangerous_deserialization=True)
return vector
def init_db(index_name):
file_path = "D:\\zj\\AI\\corpus\\孙悟空.docx"
docs = load_word_file(file_path)
documents = text_splitter.split_documents(docs)
# -------------------- 2. 向量库构建 --------------------
# 使用 OpenAI 文本嵌入(可替换为其他嵌入模型)
embeddings = OllamaEmbeddings(model="bge-m3:567m")
# 创建 FAISS 向量库
vector_db = FAISS.from_documents(
documents=documents,
embedding=embeddings
)
vector_db.save_local(index_name)

然后用Streamlit作为外部界面,构建一个可以查询和增加文档的小应用,也可以对向量库进行初始化,初始化的时候,系统会自动构建动漫龙珠的向量库,后续可以上传文档并添加新的知识。

import streamlit as st
from langchain_core.output_parsers import StrOutputParser
from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from vector2 import init_db,get,add_word
import asyncio
chat = ChatOpenAI(
streaming=True,
model='deepseek-chat',
openai_api_key='<你的AIP KEY>',
openai_api_base='https://api.deepseek.com',
max_tokens=1024
)
def main():
index_name = "anime_index_word"
st.title("动漫知识库")
question = st.text_input("请输入查询内容:")
uploaded_file = st.sidebar.file_uploader("上传文件", type=["txt", "docx"])
if st.sidebar.button("初始化向量库"):
init_db(index_name)
if uploaded_file is not None:
if st.sidebar.button("添加文件到向量库"):
with open("D:\\temp\\"+uploaded_file.name, "wb") as f:
f.write(uploaded_file.getbuffer())
f.close()
add_word("D:\\temp\\"+uploaded_file.name, index_name)
st.sidebar.success("添加成功")
if st.button("执行查询"):
if question:
template = """
你是一位问答助手,你的任务是根据###中间的文本信息回答问题,请准确回答问题,不要健谈,如果提供的文本信息无法回答问题,请直接回复“提供的文本无法回答问题”,
我相信你能做得很好。###\n{context}###\n 问题:{question}
"""
PROMPT = PromptTemplate(
template=template,
input_variables=["context","question"]
)
db = get(index_name)
retriever = db.as_retriever(search_kwargs={"k": 2})
# 召回和问题相关的文本
context = retriever.get_relevant_documents(question)
print(context)
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| PROMPT
| chat
| StrOutputParser()
)
# 流式返回
stream = chain.stream(question)
st.write_stream(stream)
else:
st.write("查询出错,请检查输入或数据库连接。")
if __name__ == "__main__":
main()

运行后,界面如下:

可以看到,回答的结果是正确的,下面再看一下,我问文档中不存在的《诛仙》的问题:

系统就无法正确回答了,所以我增加一下《诛仙》的知识进去:

如何高效转型Al大模型领域?

作为一名在一线互联网行业奋斗多年的老兵,我深知持续学习和进步的重要性,尤其是在复杂且深入的Al大模型开发领域。为什么精准学习如此关键?

  • 系统的技术路线图:帮助你从入门到精通,明确所需掌握的知识点。
  • 高效有序的学习路径:避免无效学习,节省时间,提升效率。
  • 完整的知识体系:建立系统的知识框架,为职业发展打下坚实基础。

AI大模型从业者的核心竞争力

  • 持续学习能力:Al技术日新月异,保持学习是关键。
  • 跨领域思维:Al大模型需要结合业务场景,具备跨领域思考能力的从业者更受欢迎。
  • 解决问题的能力:AI大模型的应用需要解决实际问题,你的编程经验将大放异彩。

以前总有人问我说:老师能不能帮我预测预测将来的风口在哪里?

现在没什么可说了,一定是Al;我们国家已经提出来:算力即国力!

未来已来,大模型在未来必然走向人类的生活中,无论你是前端,后端还是数据分析,都可以在这个领域上来,我还是那句话,在大语言AI模型时代,只要你有想法,你就有结果!只要你愿意去学习,你就能卷动的过别人!

现在,你需要的只是一份清晰的转型计划和一群志同道合的伙伴。作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

更多推荐