文章介绍大模型知识增强三大技术:RAG检索增强生成、微调和提示工程,重点详解RAG技术实现原理与代码实践。通过构建动漫知识库实例,展示如何将外部知识注入大模型解决知识盲区,并提供完整代码实现和Streamlit界面构建方案,帮助程序员实现大模型知识动态更新与应用开发。
生成式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()运行后,界面如下:
可以看到,回答的结果是正确的,下面再看一下,我问文档中不存在的《诛仙》的问题:
系统就无法正确回答了,所以我增加一下《诛仙》的知识进去:
可以看到,当我上传了《诛仙》的相关文档后,系统就可以查询到《诛仙》的相关信息了。
大模型未来如何发展?普通人如何抓住AI大模型的风口?
※领取方式在文末
为什么要学习大模型?——时代浪潮已至
随着AI技术飞速发展,大模型的应用已从理论走向大规模落地,渗透到社会经济的方方面面。
- 技术能力上:其强大的数据处理与模式识别能力,正在重塑自然语言处理、计算机视觉等领域。
- 行业应用上:开源人工智能大模型已走出实验室,广泛落地于医疗、金融、制造等众多行业。尤其在金融、企业服务、制造和法律领域,应用占比已超过30%,正在创造实实在在的价值。
未来大模型行业竞争格局以及市场规模分析预测:
同时,AI大模型技术的爆发,直接催生了产业链上一批高薪新职业,相关岗位需求井喷:
AI浪潮已至,对技术人而言,学习大模型不再是选择,而是避免被淘汰的必然。这关乎你的未来,刻不容缓!
那么,我们如何学习AI大模型呢?
在一线互联网企业工作十余年里,我指导过不少同行后辈,经常会收到一些问题,我是小白,学习大模型该从哪里入手呢?我自学没有方向怎么办?这个地方我不会啊。如果你也有类似的经历,一定要继续看下去!这些问题,也不是三言两语啊就能讲明白的。
所以呢,这份精心整理的AI大模型学习资料,我整理好了,免费分享!只希望它能用在正道上,帮助真正想提升自己的朋友。让我们一起用技术做点酷事!
ps:微信扫描即可获取
加上后我将逐一发送资料
与志同道合者共勉
真诚无偿分享!!!
适学人群
我们的课程体系专为以下三类人群精心设计:
AI领域起航的应届毕业生:提供系统化的学习路径与丰富的实战项目,助你从零开始,牢牢掌握大模型核心技术,为职业生涯奠定坚实基础。
跨界转型的零基础人群:聚焦于AI应用场景,通过低代码工具让你轻松实现“AI+行业”的融合创新,无需深奥的编程基础也能拥抱AI时代。
寻求突破瓶颈的传统开发者(如Java/前端等):将带你深入Transformer架构与LangChain框架,助你成功转型为备受市场青睐的AI全栈工程师,实现职业价值的跃升。
※大模型全套学习资料展示
通过与MoPaaS魔泊云的强强联合,我们的课程实现了质的飞跃。我们持续优化课程架构,并新增了多项贴合产业需求的前沿技术实践,确保你能获得更系统、更实战、更落地的大模型工程化能力,从容应对真实业务挑战。资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的技术人员,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。
01 大模型系统化学习路线
作为学习AI大模型技术的新手,方向至关重要。 正确的学习路线可以为你节省时间,少走弯路;方向不对,努力白费。希望这份最科学最系统的学习成长路线图和学习规划,带你从零基础入门到精通!
👇微信扫描下方二维码即可~
本教程比较珍贵,仅限大家自行学习,不要传播!更严禁商用!
02 大模型学习书籍&文档
新手必备的权威大模型学习PDF书单来了!全是一系列由领域内的顶尖专家撰写的大模型技术的书籍和学习文档(电子版),从基础理论到实战应用,硬核到不行!
※(真免费,真有用,错过这次拍大腿!)
03 AI大模型最新行业报告
2025最新行业报告,针对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。
04 大模型项目实战&配套源码
学以致用,在项目实战中检验和巩固你所学到的知识,同时为你找工作就业和职业发展打下坚实的基础。
05 大模型大厂面试真题
面试不仅是技术的较量,更需要充分的准备。在你已经掌握了大模型技术之后,就需要开始准备面试,我精心整理了一份大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。
06 全套AI大模型应用开发视频教程
(包含提示工程、RAG、LangChain、Agent、模型微调与部署、DeepSeek等技术点)
由于篇幅有限
只展示部分资料
并且还在持续更新中…
ps:微信扫描即可获取
加上后我将逐一发送资料
与志同道合者共勉
真诚无偿分享!!!
最后,祝大家学习顺利,抓住机遇,共创美好未来!