ai学习笔记(十二)
这次主要分享一下prompt工程、自监督学习和rag技术。
1. prompt工程
提示工程(Prompt Engineering)是优化AI模型输出的关键技术,通过精心设计输入指令来引导模型生成更准确、相关的响应。
1.1 核心原则
是否进行了prompt工程处理的关键在于给ai的输入是否具有明确性和结构化输入。
明确性:提示应清晰具体,避免模糊表述。例如,“总结这篇文章“优于“处理这个“。
结构化:使用分步指令或示例(few-shot learning)可显著提升模型表现。实验显示结构化提示能使准确率提升40%。
一个结构清晰的 Prompt 通常包含以下四个组件,它们能显著提升回复的质量:
-
角色(Role):赋予模型一个特定的身份。(例如:“你是一位拥有20年经验的资深架构师”)
-
上下文(Context):提供背景信息、限制条件或数据。(例如:“我们正在为一个初创公司设计高并发系统,预算有限”)
-
任务(Task):清晰、具体的操作指令。(例如:“请对比并评价三种数据库方案的优劣”)
-
输出要求(Output Indicator):规定格式、风格或字数。(例如:“请用对比表格展示,并给出最终建议”)
1.2 进阶技术
a. 零样本提示(Zero-shot)
零样本提示(Zero-shot Prompting)是指直接让语言模型解决问题,不提供任何示例。这种方法依赖模型已有的知识库和推理能力,适用于通用型任务。
problem = """
在一个果园里,第一天采摘了总苹果数的1/5,第二天采摘了剩下苹果数的1/4,
第三天采摘了再剩下苹果数的1/3。采摘完三天后,果园里还剩下360个苹果。
请问,果园里原来一共有多少个苹果?
"""
# --- Demo 1: 零样本提示 (Zero-shot Prompting) ---
# 直接、简单的提问方式
zero_shot_prompt = f"""问题:{problem}
请直接解答,要求:
1. 设未知数
2. 列方程
3. 求解
4. 给出答案
保持简洁。"""
messages = [
{"role": "user", "content": zero_shot_prompt}
]
b. 少样本提示(Few-shot)
少样本提示(Few-shot Prompting)通过提供少量范例(通常3-5个)来引导模型学习特定模式。这种方法能显著提升模型在专业领域的表现,如法律文书生成或医疗问答。
# --- Demo 2: 少样本思维链提示 (Few-shot CoT) ---
# 提供完整的逆向推理范例
few_shot_cot_prompt = f"""
学习以下逆向推理范例:
[范例]
问题:仓库第一天运走总数1/3,第二天运走剩下的1/2,最后剩250吨。原来有多少吨?
解答:逆向推理
- 第二天运走后剩250吨
- 第二天前:250 ÷ (1-1/2) = 500吨
- 第一天前:500 ÷ (1-1/3) = 750吨
答案:750吨
---
请用相同格式解决:
{problem}
"""
messages = [
{"role": "user", "content": few_shot_cot_prompt}
]
c. 思维链提示(Chain of Thought,CoT)
-
逻辑:在 Prompt 中要求模型“一步步思考”。
-
作用:对于逻辑推理、数学题或复杂决策,CoT 能引导模型展示中间步骤,从而减少幻觉(乱说)并提高准确率。
-
常用语:“Let's think step by step”(让我们一步步思考)。
# --- Demo 3: 引导式逆向推理 ---
# 明确指导逆向推理步骤
guided_prompt = f"""
问题:{problem}
逆向推理法(从结果倒推):
1. 最后剩360个苹果
2. 第三天采摘前:360 ÷ (1-1/3) = 360 ÷ (2/3) = ?
3. 第二天采摘前:结果 ÷ (1-1/4) = 结果 ÷ (3/4) = ?
4. 第一天采摘前:结果 ÷ (1-1/5) = 结果 ÷ (4/5) = ?
请计算每步的具体数值并给出最终答案。
"""
messages = [
{"role": "user", "content": guided_prompt}
]
d. 自洽性(Self-Consistency)
自洽性能够让模型对同一个问题进行多次思考,得出不同答案后通过“少数服从多数”的投票机制,选出最可靠的结论。
import collections
'''
问题:小明有 5 个苹果,他买了两箱,每箱有 10 个。
他给了朋友 3 个,后来又吃掉了一半剩下的。最后他还有几个苹果?
'''
def get_consistent_answer(problem):
# 模拟 CoT 引导词
prompt = f"问题:{problem}\n请一步步思考并给出最后答案(格式为:答案是 [数值])"
# 1. 一次性生成多个回复 (n=5),设置较高温度增加多样性
responses = llm.generate(prompt, n=5, temperature=0.7)
results = []
for resp in responses:
# 2. 从每个推理链中提取最终答案 (简单正则示例)
ans = extract_answer(resp)
results.append(ans)
# 3. 少数服从多数 (投票)
most_common = collections.Counter(results).most_common(1)
return most_common[0][0] # 返回出现频率最高的答案
# 调用
final_ans = get_consistent_answer("5个苹果吃掉一半剩几个?")
print(f"最自洽的答案是: {final_ans}")
2. 自监督学习
自监督学习就是让模型自己教自己。
2.1 核心思想
无需人工标注的预测任务
传统的监督学习需要大量的人工标签(比如:给一万张图片手动标注“这是猫”)。而自监督学习直接利用数据本身的信息,人为地制造出某种“缺失”,然后让模型去预测。
2.2 常用损坏策略
- Mask (掩码):用特殊的
[MASK]符号替换掉原来的词。这是最经典的BERT做法。 - Replace spans (替换片段):随机选取一段连续的文本(span),并用随机生成的词或其他词替换它们。
- Drop (丢弃):直接删除文本中的某些词或片段。
3. RAG
RAG (Retrieval-Augmented Generation,检索增强生成)
RAG通过动态检索外部知识库来增强生成模型的输出准确性, 就像是给大模型配了一个“随时可以翻阅的图书馆”。
3.1 为什么需要RAG?
大模型虽然博学,但有三个致命弱点:
-
幻觉问题:模型会一本正经地胡说八道。
-
时效性差:模型的知识停留在预训练结束的那一天(知识过时)。
-
私域数据缺失:模型不知道你公司的内部文档或个人笔记。
对比方案:
-
微调 (Fine-tuning):像让模型把整本书背下来,成本高,更新难。
-
RAG:像让模型参加“开卷考试”,哪里不会查哪里,成本低,准确度高。
3.2 工作流程

在进行数据切分之前一定要对你输入的文档进行数据清洗,可以先人工去掉一些无关的内容,比如论文里的作者资料,无关的长链接和图片,再根据程序进一步清洗。
import re
def clean_document(text):
# 1. 剔除页眉页脚示例 (基于正则)
text = re.sub(r"Confidential - Page \d+", "", text)
# 2. 压缩空白符
text = re.sub(r'\s+', ' ', text).strip()
# 3. 删除非法字符
text = re.sub(r'[^\x00-\x7F\u4e00-\u9fa5]+', '', text)
# 4. 修复硬换行 (简单的句子连接逻辑)
text = text.replace('.\n', '.<SEP>').replace('\n', ' ').replace('<SEP>', '.\n')
return text
第一阶段:数据准备(离线)
-
分块 (Chunking):把长文档切成一小段一小段(如 500 字一段)。
-
向量化 (Embedding):用一个模型把文字转成一串数字(向量)。
-
入库 (Vector Database):把这些数字存进向量数据库。
a. 文本切分
文本切分必要性:模型上下文窗口存在限制(如GPT-3最大2048 tokens),切分可解决长文本处理问题。同时,合理切分能提升检索精度,避免信息冗余。
常用切分策略:
- 字符分割:按固定字符数切割,简单但可能破坏语义。
- 递归分割:层级式分割,优先按段落/句子边界切分。(默认使用)
- Markdown分割:保留文档结构(如标题/列表)。
chunk_size控制片段长度(通常512-1024 tokens),chunk_overlap(建议10-20%)防止关键信息断裂。
b. 向量化 Embedding
将文本映射为稠密向量(通常768-1024维),通过余弦相似度计算语义关联。相比one-hot编码,能捕获近义词/上下文关系(如“手机“与“智能手机“向量相近)
中文模型选型:
-
bge-large-zh:1024维向量,适合精度优先场景
-
m3e-base:768维向量,推理速度比bge快40%资源占用对比:bge需4GB显存,m3e仅需2GB
高精度场景:选择bge-large等大模型(3B+参数)实时系统:考虑m3e或蒸馏模型(推理延迟<50ms)移动端:量化后的tiny模型(<100MB内存占用)
c. 向量数据库
定义:向量数据库是专门设计用于存储和检索向量数据的数据库系统,与传统关系型数据库不同,它通过向量相似度进行高效查询。
ANN搜索核心:
近似最近邻(ANN)搜索是向量数据库的核心功能,能够在毫秒级时间内从海量数据中找出最相似的向量,支持AI模型的实时推理。
为什么要ANN?
传统的精确搜索策略能保证100%的准确率,但是计算复杂度是O(N),他需要与数据库中的每一个向量进行计算。当数据量大时,会带来秒级延迟,无法接受。
ANN 是一种“用极小的精度损失,换取指数级速度提升”的搜索策略。它通过预先构建特殊的索引结构,避免了与所有向量进行计算,从而将检索时间从秒级压缩到毫秒级。
ANN 不是一个单一的算法,而是一类算法的总称。不同的算法有不同的索引构建方式和搜索策略,以适应不同的场景,常用的算法有HNSW、IVF、PQ、DiskANN等。
常用向量数据库:
本地轻量级方案:FAISS(Facebook开源的向量搜索库)、ChromaDB(嵌入式向量数据库)。生产级分布式方案:Milvus(云原生向量数据库)、Pinecone(全托管向量服务)、Weaviate(开源搜索引擎)。

第二阶段:查询与生成(在线)
-
检索 (Retrieve):用户提问时,系统也把问题转成向量,去数据库里找最相似的几段话。
-
增强 (Augment):把找出来的“参考资料”和“原始问题”拼接在一起。
-
生成 (Generate):把拼接后的长文本发给大模型,让它“根据以上参考资料回答问题”。
3.3 代码示例
import os
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader, TextLoader
#from langchain.text_splitters import RecursiveCharacterTextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
#from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_huggingface import HuggingFaceEmbeddings
class RAGEngine:
def __init__(self, db_path="./chroma_db", embedding_model="shibing624/text2vec-base-chinese"):
self.db_path = db_path
print(f"加载 Embedding 模型: {embedding_model}...")
self.embeddings = HuggingFaceEmbeddings(
model_name=embedding_model,
model_kwargs={'device': 'cpu'} # 为了低配置兼容,如果GPU有空余可改cuda
)
self.vectorstore = self._init_vectorstore()
def _init_vectorstore(self):
if os.path.exists(self.db_path):
print("加载本地向量数据库...")
return Chroma(persist_directory=self.db_path, embedding_function=self.embeddings)
else:
print("向量数据库不存在,请先构建知识库。")
return None
def build_knowledge_base(self, docs_dir="./medical_docs"):
"""读取指定目录下的文档,构建向量库"""
print("开始构建知识库...")
#读文件夹里面的pdf文件
#loader = DirectoryLoader(docs_dir, glob="**/*.pdf", loader_cls=TextLoader)
loader = DirectoryLoader(
docs_dir,
glob="**/*.pdf", # 只加载 PDF 文件
loader_cls=PyPDFLoader, # 使用 PDF 加载器
use_multithreading=True # 可选,加快加载速度
)
documents = loader.load()
# 切分文档 带语义感知的递归式启发切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50, #重叠度,防止丢失上下文
separators=["\n\n", "\n", "。", "!", "?", ",", "、", ""]
)
chunks = text_splitter.split_documents(documents)
# 存入 Chroma
self.vectorstore = Chroma.from_documents(
documents=chunks,
embedding=self.embeddings,
persist_directory=self.db_path
)
self.vectorstore.persist()
print(f"知识库构建完成!共 {len(chunks)} 个片段。")
def retrieve_context(self, query, top_k=3):
"""根据 query 检索最相关的医疗知识"""
if not self.vectorstore:
return ""
results = self.vectorstore.similarity_search_with_score(query, k=top_k)
# 组装上下文
context = ""
for doc, score in results:
# 过滤掉相似度太低的结果 (Chroma 默认是 L2 距离,越小越相似)
if score < 400:
context += doc.page_content + "\n"
return context.strip()
# 测试代码
if __name__ == "__main__":
rag = RAGEngine()
#rag.build_knowledge_base() # 第一次运行需解开注释构建库
context = rag.retrieve_context("高血压患者应该注意什么?")
print("检索到的上下文:\n", context)
3.4 常见问题
1.RAG检索结果不准确怎么办?
-
精细化切分:按段落、标题或句子边界切分文档,并设置适当的重叠长度,避免语义被截断。
-
升级 Embedding 模型:换用领域适应性强或更高维的稠密向量模型,必要时在私有数据上微调。
-
混合检索:同时使用稀疏检索(如 BM25)和稠密向量检索,融合两者结果以提升召回质量。
-
重排序:先用高效方法召回一批候选文档,再用跨编码器模型对它们重新打分,剔除真正不相关的内容。
-
动态 Top‑K 与阈值过滤:不固定返回文档数量,而是根据相似度分数动态调整,并丢弃低于设定阈值的文档。
-
查询改写与扩展:利用大模型生成原始查询的多个同义变体或假设答案,分别检索后再合并去重。
-
元数据过滤:在向量库中存储文档的发布时间、来源等属性,检索时按需过滤,只返回符合条件的文档。
2. 大模型回答质量不高,缺乏可读性。
-
结构化 Prompt:给大模型设定明确的角色、任务分解步骤、输出格式示例,并要求不确定时主动拒答。
-
增强上下文依赖约束:在提示中强调“仅使用给出的文档,禁止引入外部知识”,并对不相关的文档明确忽略。
-
答案验证机制:生成答案后让模型自己检查是否完全被文档支持,或另用一个小型 NLI 模型进行一致性校验。
-
多文档融合摘要:当检索结果中存在矛盾或冗余时,先让模型合并相同信息、对比差异,再输出综合结论。
-
输出风格控制:根据场景调整温度参数、禁用无意义的套话,并预设不同模板(如技术问答要求简洁精确)。
-
可追溯引用:要求每个结论后附上来源文档 ID 及原文片段,方便用户核实真伪。
3.知识库时效性不够
-
实时更新机制:监听数据源的变化(如数据库 CDC、文件系统事件),一旦有更新就触发增量索引。
-
定时脚本与增量爬取:使用定时任务周期性抓取外部数据,仅拉取自上次抓取后发生变更的内容。
-
版本化索引:按时间片建立独立索引,查询时默认使用最新索引,同时允许用户切换到历史版本。
-
主动过时检测:定期扫描知识库,对比外部官方源,将过时的文档标记为失效并触发重新抓取。
-
时间衰减排序:在检索打分时加入基于文档发布时间的衰减因子,使新近文档更容易进入最终结果。
-
外部 API 实时注入:对于无法预存的实时信息(如天气、股价),直接调用外部 API 获取并拼接到上下文。
-
用户反馈驱动更新:收集用户对答案的“有用/无用”标记或主动指出过时的反馈,定向刷新相关内容。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)