ai学习笔记(十二)

张开发
2026/4/16 3:04:41 15 分钟阅读

分享文章

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 ThoughtCoT逻辑在 Prompt 中要求模型“一步步思考”。作用对于逻辑推理、数学题或复杂决策CoT 能引导模型展示中间步骤从而减少幻觉乱说并提高准确率。常用语“Lets 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. 一次性生成多个回复 (n5)设置较高温度增加多样性 responses llm.generate(prompt, n5, temperature0.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. RAGRAG (Retrieval-Augmented Generation检索增强生成)RAG通过动态检索外部知识库来增强生成模型的输出准确性 就像是给大模型配了一个“随时可以翻阅的图书馆”。3.1 为什么需要RAG大模型虽然博学但有三个致命弱点幻觉问题模型会一本正经地胡说八道。时效性差模型的知识停留在预训练结束的那一天知识过时。私域数据缺失模型不知道你公司的内部文档或个人笔记。对比方案微调 (Fine-tuning)像让模型把整本书背下来成本高更新难。RAG像让模型参加“开卷考试”哪里不会查哪里成本低准确度高。3.2 工作流程在进行数据切分之前一定要对你输入的文档进行数据清洗可以先人工去掉一些无关的内容比如论文里的作者资料无关的长链接和图片再根据程序进一步清洗。import re def clean_document(text): # 1. 剔除页眉页脚示例 (基于正则) text re.sub(rConfidential - 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)把这些数字存进向量数据库。第二阶段查询与生成在线检索 (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_modelshibing624/text2vec-base-chinese): self.db_path db_path print(f加载 Embedding 模型: {embedding_model}...) self.embeddings HuggingFaceEmbeddings( model_nameembedding_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_directoryself.db_path, embedding_functionself.embeddings) else: print(向量数据库不存在请先构建知识库。) return None def build_knowledge_base(self, docs_dir./medical_docs): 读取指定目录下的文档构建向量库 print(开始构建知识库...) #读文件夹里面的pdf文件 #loader DirectoryLoader(docs_dir, glob**/*.pdf, loader_clsTextLoader) loader DirectoryLoader( docs_dir, glob**/*.pdf, # 只加载 PDF 文件 loader_clsPyPDFLoader, # 使用 PDF 加载器 use_multithreadingTrue # 可选加快加载速度 ) documents loader.load() # 切分文档 带语义感知的递归式启发切分 text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50, #重叠度防止丢失上下文 separators[\n\n, \n, 。, , , , 、, ] ) chunks text_splitter.split_documents(documents) # 存入 Chroma self.vectorstore Chroma.from_documents( documentschunks, embeddingself.embeddings, persist_directoryself.db_path ) self.vectorstore.persist() print(f知识库构建完成共 {len(chunks)} 个片段。) def retrieve_context(self, query, top_k3): 根据 query 检索最相关的医疗知识 if not self.vectorstore: return results self.vectorstore.similarity_search_with_score(query, ktop_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)

更多文章