掘金 人工智能 19小时前
基础RAG实现,最佳入门选择(一)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了使用Python和智谱AI构建基础RAG(Retrieval-Augmented Generation)系统的实践方法。通过从PDF文件中提取文本,进行分块处理,生成文本嵌入向量,并利用语义搜索找到相关信息,最终结合智谱AI模型生成回答,实现智能问答功能。该流程清晰展示了RAG技术的核心步骤,为初学者提供了入门参考。

💡 从PDF提取文本:使用`fitz`库从PDF文件中提取文本内容,为后续处理提供原始数据。

🧩 文本分块:将提取的文本分割成多个块,并设置重叠,以便更好地捕捉上下文信息,提高搜索的准确性。

🔍 生成文本嵌入向量:利用智谱AI的API,将文本块转换为嵌入向量,用于语义搜索,方便计算文本之间的相似度。

🔎 语义搜索:通过计算查询语句与文本块的嵌入向量之间的余弦相似度,找到与查询最相关的文本块。

💬 使用大模型生成回答:结合语义搜索结果,使用智谱AI的GLM-4模型生成针对查询的详细回答。

基础RAG实现,最佳入门选择(一)

从 PDF 中提取文本

import fitz  # PyMuPDF库,用于读取和操作PDF文件import os    # 提供操作系统路径和文件操作相关功能import numpy as np  # 提供多维数组与科学计算支持import json         # 用于处理JSON格式数据的序列化与反序列化from openai import OpenAI  # 用于调用OpenAI API(如GPT模型)进行自然语言处理def extract_text_from_pdf(pdf_path):    """    从指定路径的PDF文件中提取全部文本内容。    参数:    pdf_path (str): 需要读取的PDF文件路径    返回:    str: 提取出的所有文本内容    """    # 打开PDF文件    mypdf = fitz.open(pdf_path)    all_text = ""  # 初始化一个空字符串,用于累积存储每页的文本内容    # 循环遍历PDF文档中的所有页面    for page_num in range(mypdf.page_count):        page = mypdf[page_num]  # 获取当前页面对象        text = page.get_text("text")  # 提取当前页面的纯文本内容        all_text += text  # 将当前页的文本添加到总文本字符串中    return all_text  # 返回整个PDF提取后的完整文本内容if __name__ == "__main__":    # 示例:定义需要读取的PDF文件路径(请根据实际情况修改)    pdf_path = "2888年Java程序员找工作最新场景题.pdf"    # 调用函数提取文本    text = extract_text_from_pdf(pdf_path)    # 输出前1000个字符以查看部分结果(避免输出过长)    print(text[:1000])

chunk_text

import fitz  # PyMuPDF库,用于读取和操作PDF文件import os    # 提供操作系统路径和文件操作相关功能import numpy as np  # 提供多维数组与科学计算支持import json         # 用于处理JSON格式数据的序列化与反序列化from openai import OpenAI  # 用于调用OpenAI API(如GPT模型)进行自然语言处理def extract_text_from_pdf(pdf_path):    """    从指定路径的PDF文件中提取全部文本内容。    参数:    pdf_path (str): 需要读取的PDF文件路径    返回:    str: 提取出的所有文本内容    """    # 打开PDF文件    mypdf = fitz.open(pdf_path)    all_text = ""  # 初始化一个空字符串,用于累积存储每页的文本内容    # 循环遍历PDF文档中的所有页面    for page_num in range(mypdf.page_count):        page = mypdf[page_num]  # 获取当前页面对象        text = page.get_text("text")  # 提取当前页面的纯文本内容        all_text += text  # 将当前页的文本添加到总文本字符串中    return all_text  # 返回整个PDF提取后的完整文本内容def chunk_text(text, n, overlap):    """    将给定文本按照指定长度分块,并允许相邻块之间有重叠。    参数:    text (str): 需要分块的文本。    n (int): 每个块包含的字符数。    overlap (int): 相邻块之间的重叠字符数。    返回:    List[str]: 分块后的文本列表。    """    chunks = []  # 初始化一个空列表,用于存储分块结果    # 以步长(n - overlap)遍历文本    for i in range(0, len(text), n - overlap):        # 将从i开始、长度为n的子串加入分块列表        chunks.append(text[i:i + n])    return chunks  # 返回分块后的文本列表if __name__ == "__main__":    # 示例:定义需要读取的PDF文件路径(请根据实际情况修改)    pdf_path = "2888年Java程序员找工作最新场景题.pdf"    # 调用函数提取文本    text = extract_text_from_pdf(pdf_path)    # 设置文本分块的参数    chunk_size = 1000  # 每个块的大小    overlap_size = 200  # 块之间的重叠大小    # 对文本进行分块    text_chunks = chunk_text(text, chunk_size, overlap_size)    # 打印分块结果    print(f"文本被分成了 {len(text_chunks)} 个块")    print("\n第一个文本块的内容:")    print(text_chunks[0])

运行得到的结果

E:\AworkNew2025\all-rag-techniques\venv\Scripts\python.exe E:\AworkNew2025\all-rag-techniques\test\RAG01.py 文本被分成了 339 个块第一个文本块的内容:2024 年Java 程序员找工作最新面试攻略这个文档是帮助正在找工作以及准备找工作的同学,在面试之前去复习和突击的一种方式。适合已经在技术领域有一定积累,然后不确定面试切入点,所以可以通过这个面试文档来预热和巩固。想直接通过刷面试文档找到工作的同学也要注意,面试文档的内容是静态的,但是面试过程是动态的,面试官对于某一个领域的考察,通常是通过连环问的方式去问,所以在面试之前,求职者要对Java 相关技术有一个体系化的了解,从而更好地突出自己的综合能力。在科技日新月异的今天,软件开发行业正经历着前所未有的变革。Java,作为企业级应用开发的中流砥柱,其生态系统也在不断进化,从微服务架构的普及到云原生技术的兴起,再到AI 与大数据的深度融合,Java 程序员的角色和技能需求随之迭代升级。面对这样的行业背景,如何在求职路上脱颖而出,成为每位开发者必须深思的问题。随着Java 这个赛道的不断内卷,这两年,Java 程序员的面试,从原来的常规八股文(有标准答案)到现在,以项目、场景问题、技术深度思考为主,逐步转变成没有标准答案,需要大家基于自己的理解和技术底蕴来回答。那针对市场中新的需求,有没有最新的面试攻略呢?其实也是有的,虽然说没有标准答案,但是我们可以针对如今市场的面试变化,来针对性的设计一些面试回答的思路,让大家有一个清晰和明确的方向。这里有什么?1.针对2024 年面试行情的变化设计的面试场景题以及回答思路2.如何快速通过面试的详细攻略3.简历优化技巧1. 知己知彼才能百战百胜,如何做好面试前的准备工作2024 年的行情,和3~4 年前不同,通过海量简历投递和海量面试找工作的时代已经过去了。在如今面试机会较少,并且面试难度较大的情况下。充分做好面试的准备才是快速通过面试最有效的方法!切忌把真实面试当靶场,最后带来的代价是非常巨大的!面试无非就两个部分,投简历、面试!很多人把重心放在投简历上,忽略了准备面试的重要性,最后的结果是获得了面试机会但是在面试过程中被刷下来了。1.1 怎么写简历着手准备的第一步聚焦于简历的打造。简历是他人初步了解你的窗口,其重要性不言而喻,因此精心构思简历至关重要。理想的简历应当围绕你的亲身经历构建,正如某些杰出人士仅凭一句“Unix 的创造者”便足以令人印象深进程已结束,退出代码为 0

智谱AI进行简单的RAG测试

import fitz  # PyMuPDF库,用于处理PDF文件import os  # 提供与操作系统交互的功能import numpy as np  # 用于数值计算和数组操作import json  # 用于处理JSON数据的解析与生成from zhipuai import ZhipuAI  # 智谱AI的API接口def extract_text_from_pdf(pdf_path):    """    从PDF文件中提取文本内容,并打印前`num_chars`个字符(默认未实现参数控制)。    参数:    pdf_path (str): PDF文件的路径。    返回:    str: 从PDF中提取的所有文本内容。    """    # 打开指定路径的PDF文件    mypdf = fitz.open(pdf_path)    all_text = ""  # 初始化一个空字符串,用于存储提取的文本    # 遍历PDF中的每一页    for page_num in range(mypdf.page_count):        page = mypdf[page_num]  # 获取当前页        text = page.get_text("text")  # 从当前页提取文本        all_text += text  # 将提取的文本追加到all_text字符串中    return all_text  # 返回提取的完整文本def chunk_text(text, n, overlap):    """    将文本分割成固定长度的片段,每个片段之间有重叠部分。    参数:    text (str): 需要分割的文本。    n (int): 每个文本片段的字符数。    overlap (int): 相邻片段之间的重叠字符数。    返回:    List[str]: 文本片段列表。    """    chunks = []  # 初始化一个空列表来存储文本片段    # 以(n - overlap)为步长遍历文本    for i in range(0, len(text), n - overlap):        # 将文本从索引i到i+n的部分添加到chunks列表中        chunks.append(text[i:i + n])    return chunks  # 返回文本片段列表def get_embeddings(text_chunks):    """    使用智谱AI API获取文本块的嵌入向量        参数:    text_chunks (List[str]): 文本块列表        返回:    List[List[float]]: 每个文本块对应的嵌入向量列表    """    embeddings = []    for chunk in text_chunks:        try:            response = client.embeddings.create(                model="embedding-2",  # 使用智谱AI的嵌入模型                input=chunk            )            embeddings.append(response.data[0].embedding)        except Exception as e:            print(f"处理文本块时出错: {str(e)}")            raise    return embeddingsdef semantic_search(query, embeddings, text_chunks, top_k=3):    """    使用余弦相似度进行语义搜索        参数:    query (str): 查询文本    embeddings (List[List[float]]): 所有文本块的嵌入向量    text_chunks (List[str]): 原始文本块    top_k (int): 返回最相关的k个结果        返回:    List[str]: 最相关的文本块列表    """    # 获取查询文本的嵌入向量    query_embedding = client.embeddings.create(        model="embedding-2",  # 使用智谱AI的嵌入模型        input=query    ).data[0].embedding        # 计算余弦相似度    similarities = []    for embedding in embeddings:        similarity = np.dot(query_embedding, embedding) / (            np.linalg.norm(query_embedding) * np.linalg.norm(embedding)        )        similarities.append(similarity)        # 获取最相关的文本块    top_indices = np.argsort(similarities)[-top_k:][::-1]    return [text_chunks[i] for i in top_indices]if __name__ == "__main__":    # 初始化智谱AI客户端    client = ZhipuAI(        api_key="87ec5e982d05fc748c957971a2b76443.xxxxxx"    # 替换为你的智谱AI API密钥    )        # 设置PDF文件路径    pdf_path = "2888年Java程序员找工作最新场景题.pdf"        # 从PDF提取文本    print("正在从PDF提取文本...")    extracted_text = extract_text_from_pdf(pdf_path)        # 将文本分块    print("正在将文本分块...")    chunk_size = 1000    # 每个文本块的大小(字符数)    overlap_size = 200   # 重叠部分的大小(字符数)    text_chunks = chunk_text(extracted_text, chunk_size, overlap_size)    print(f"文本被分成了 {len(text_chunks)} 个块")        # 获取文本块的嵌入向量    print("正在生成文本嵌入向量...")    try:        embeddings = get_embeddings(text_chunks)    except Exception as e:        print(f"生成嵌入向量时出错: {str(e)}")        print("请检查API密钥和网络连接是否正确")        exit(1)        # 示例查询    query = "知己知彼才能百战百胜,如何做好面试前的准备?"    print(f"\n执行查询: {query}")        # 进行语义搜索    relevant_chunks = semantic_search(query, embeddings, text_chunks)        # 打印搜索结果    print("\n最相关的文本块:")    for i, chunk in enumerate(relevant_chunks, 1):        print(f"\n块 {i}:")        print(chunk)        # 使用智谱AI生成回答    print("\n正在生成回答...")    prompt = f"""基于以下相关文本块,回答问题:{query}相关文本:{''.join(relevant_chunks)}请提供详细的回答:"""        response = client.chat.completions.create(        model="glm-4",  # 使用智谱AI的GLM-4模型        messages=[            {"role": "system", "content": "你是一个专业的AI助手,擅长基于给定文本回答问题。"},            {"role": "user", "content": prompt}        ]    )        print("\nAI回答:")    print(response.choices[0].message.content)

运行结果展示

文本效果展示

E:\AworkNew2025\all-rag-techniques\venv\Scripts\python.exe E:\AworkNew2025\all-rag-techniques\test\01_simple_rag.ipynb.py 正在从PDF提取文本...正在将文本分块...文本被分成了 339 个块正在生成文本嵌入向量...执行查询: 知己知彼才能百战百胜,如何做好面试前的准备?最相关的文本块:块 1:带来的代价是非常巨大的!面试无非就两个部分,投简历、面试!很多人把重心放在投简历上,忽略了准备面试的重要性,最后的结果是获得了面试机会但是在面试过程中被刷下来了。1.1 怎么写简历着手准备的第一步聚焦于简历的打造。简历是他人初步了解你的窗口,其重要性不言而喻,因此精心构思简历至关重要。理想的简历应当围绕你的亲身经历构建,正如某些杰出人士仅凭一句“Unix 的创造者”便足以令人印象深刻。尽管并非所有人都拥有如此耀眼的成就,但这一例证强调了个人经历在简历中的核心地位。因此,选择那些能丰富你简历含金量的职位,从事能让你简历熠熠生辉的项目,乃是简历撰写的黄金法则——让经历说话,而非仅仅堆砌文字。然而,简历的文字表达同样不可小觑,尤其是当我们缺乏显赫背景时。简历应当精炼,避免冗余信息导致焦点模糊,着重突出你的优势与技能。一般而言,简历应涵盖以下核心部分:个人简介:用不超过200 字简明扼要地概括自己,例如:“拥有超十年软件开发经验,带领团队逾四年,专长于构建高可用性、高性能的分布式系统,背景横跨互联网与金融业,目前担任XXX 公司XX 职位,负责XXX 平台。”联系信息:推荐使用专业的电子邮件地址(如Gmail),避免使用过于休闲的邮箱服务。若拥有个人网站、博客、GitHub 或Stack Overflow 账号,务必附上,尤其是个性化域名更能彰显主动性和审美品味,且确保页面内容组织得当,真诚无伪。技术作品与展示:展示你的成果,尤其是对于前端开发者更为直接。后端开发者则可通过GitHub 展示项目。专业证书或奖项同样值得提及,如微软或Oracle 认证。技能概览:技术栈:明确列出掌握的编程语言、框架、技术工具及设计理念,如Java、SpringBoot、Redis、分布式系统架构等。专业领域:涵盖前端、算法、机器学习、分布式系统、数据库管理等。行业经验:涉及的行业如金融、电子商务,及特定业务如客户关系管理、支付系统等。软实力与经验:团队管理规模、项目管理经验、个人特质等,简洁明了即可。确保简历内容与目标职位的技能要求对齐,以便快速建立匹配印象。工作与教育背景需精挑细选,强调关键项目、挑战、责任及所获成就,同时,这些内容应紧密支撑你的技能陈述,避免离题。简历长度以不超过两页A4 块 2:深度。如声称掌握面向对象设计,熟悉《设计模式》中的经典23 种模式将是基本要求。对于分布式架构的宣称,则需对CAP 原则、微服务架构、弹性设计以及SpringCloud、Cloud Native 等相关技术框架有深刻理解。关于网络编程的技能,理解TCP/IP 协议的三次握手、四次挥手过程,Socket 编程基础,以及select、poll、epoll 等I/O 多路复用技术,都是必不可少的知识点。综上所述,你简历上的每一项技术标注,都应当基于你对该技术核心知识点的掌握之上。这好比备考期末考试,你需要全面回顾教材,确保掌握大多数关键知识点,即使不必面面俱到,但对于80%以上的重点内容,你都应做到心中有数。这样的准备不仅是为了应对面试,更是对自己技术深度和广度的负责态度体现。1.3 项目准备(非常重要)在面试过程中,分享个人项目经历或解决过的挑战几乎是每个面试官必问的环节,但令人诧异的是,许多候选人并未对此做好充分准备。以下四个经典问题频繁出现于面试之中:1.分享一个你最为自豪或最近完成的项目。2.讲述一次你攻克的最复杂或技术含量最高的难题。3.描述一个你经历过的最具挑战性或最艰难的项目。4.谈谈你曾犯下的最大技术失误或引发的技术故障。这些问题背后,面试官的意图各异:第一个问题旨在探查你的成就顶峰、兴趣所在;第二、三题侧重于你的问题解决能力和面对逆境时的心态韧性;而第四题则关注你对待错误的态度,以及是否具备反思与成长的能力。值得注意的是,面试官会通过连续追问细节来验证信息的真实性,因为虚构的情节难以在严密的追问下自圆其说。为有效应对这类问题,以下建议或许能帮助你更好地准备:构建故事框架:运用STAR 法则(情境Situation、任务Task、行动Action、结果Result)来组织你的叙述,确保内容条理清晰,避免冗长繁杂。添加细节:丰富的技术细节是说服力的关键,它能让故事显得更加真实可信。注入情感:真挚的情感表达能传递你的热情、自豪与坚持,确保情感源自真实的体验。融入反思:在叙述中穿插你的思考、教训总结及后续的改进措施,展现你的成长和成熟。达到这样的叙述水平并非易事,需要持续的练习与积累。日常工作中,培养即时总结的习惯,对经历进行记录与反思,是避免临阵磨块 3:、机器学习、分布式系统、数据库管理等。行业经验:涉及的行业如金融、电子商务,及特定业务如客户关系管理、支付系统等。软实力与经验:团队管理规模、项目管理经验、个人特质等,简洁明了即可。确保简历内容与目标职位的技能要求对齐,以便快速建立匹配印象。工作与教育背景需精挑细选,强调关键项目、挑战、责任及所获成就,同时,这些内容应紧密支撑你的技能陈述,避免离题。简历长度以不超过两页A4 纸为宜,采用PDF 格式以保证格式一致性。可借鉴LinkedIn 或Microsoft Office 模板美化外观,力求内容精炼,重点突出。记住,简历的目标是凸显你的独特之处,哪怕仅展示两三个亮点,也足以引起注意。最后,简历是打开机遇之门的第一步,尤其在竞争激烈的就业市场中,除了实质性的技能和经验,别出心裁的简历设计与正面积极的自我评价亦能增加脱颖而出的机会。即便初始条件有限,展现出积极的态度、持续的学习意愿和解决问题的能力,同样能传达出你是一个值得投资的潜力股。1.2 技术知识储备在准备简历时,切记实事求是,你所列出的每一项技能都可能成为面试对话的起点。"精通"、"熟悉"、"了解"需准确区分,以免自相矛盾。对于提及的每项技术,务必把握其基础及核心概念,因为面试过程中,面试官往往会逐步深入探讨,以此评估你的实际水平。因此,系统性复习相关书籍和资料是不可或缺的步骤,以备不时之需。例如:如你标明熟练掌握Java,那么不仅限于基础语法,还应涵盖并发编程、NIO、JVM等进阶知识,同时对Spring、Netty 等流行框架的基本原理有所认识。提及Go 语言,意味着你应至少阅读过官方的《Effective Go》,理解其核心理念。当列举Redis 时,对其数据结构、性能调优策略、高可用部署方式及分布式锁机制等,通过官方文档的研读应达到一定的理解深度。如声称掌握面向对象设计,熟悉《设计模式》中的经典23 种模式将是基本要求。对于分布式架构的宣称,则需对CAP 原则、微服务架构、弹性设计以及SpringCloud、Cloud Native 等相关技术框架有深刻理解。关于网络编程的技能,理解TCP/IP 协议的三次握手、四次挥手过程,Socket 编程基础,以及select、poll、epoll 等I/O 多路复用技术,正在生成回答...

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

RAG PDF 语义搜索 智谱AI Python
相关文章