首页 > 其他分享 >山东大学项目实训-基于LLM的中文法律文书生成系统(十三)- RAG(2)

山东大学项目实训-基于LLM的中文法律文书生成系统(十三)- RAG(2)

时间:2024-05-31 09:12:33浏览次数:13  
标签:RAG documents text self List 实训 LLM Document split

今天主要讲langchain在上传解析文档时是怎么实现的。

文档解析逻辑,以txt类型的文件解析为例子

step1:寻找上传逻辑入口:local_doc_qa.py ,关注TextLoader(),ChineseTextSplitter()

def load_file(filepath, sentence_size=SENTENCE_SIZE, using_zh_title_enhance=ZH_TITLE_ENHANCE):
    if filepath.lower().endswith(".md"):
        loader = UnstructuredFileLoader(filepath, mode="elements")
        docs = loader.load()
    elif filepath.lower().endswith(".txt"):
        loader = TextLoader(filepath, autodetect_encoding=True)
        textsplitter = ChineseTextSplitter(pdf=False, sentence_size=sentence_size)
        docs = loader.load_and_split(textsplitter)

step2:解析txt/pdf等原始文件,不同类型的文件有不同种类多Loader,比如txt文件有TextLoader,具体load()实现如下:

def load(self) -> List[Document]:
    """Load from file path."""    text = ""    
    try:
        with open(self.file_path, encoding=self.encoding) as f:
            text = f.read()
    except UnicodeDecodeError as e:
        if self.autodetect_encoding:
            detected_encodings = detect_file_encodings(self.file_path)
            for encoding in detected_encodings:
                logger.debug("Trying encoding: ", encoding.encoding)
                try:
                    with open(self.file_path, encoding=encoding.encoding) as f:
                        text = f.read()
                    break                except UnicodeDecodeError:
                    continue        else:
            raise RuntimeError(f"Error loading {self.file_path}") from e
    except Exception as e:
        raise RuntimeError(f"Error loading {self.file_path}") from e

    metadata = {"source": self.file_path}
    return [Document(page_content=text, metadata=metadata)]

此时输入:file_path,输出:List[Document],其中,Document对象如下:

page_content:原生txt读取的所有内容

metadata:文件地址路径,metadata = {"source": self.file_path}

class Document(BaseModel):
    """Interface for interacting with a document."""    
    page_content: str    
    metadata: dict = Field(default_factory=dict)

step3:load_and_split()进行文档切割

输入:Optional[TextSplitter],输出:List[Document]

def load_and_split(self, text_splitter: Optional[TextSplitter] = None) -> List[Document]:
    """Load documents and split into chunks."""    
    if text_splitter is None:
        _text_splitter: TextSplitter = RecursiveCharacterTextSplitter()
    else:
        _text_splitter = text_splitter
    docs = self.load()
    return _text_splitter.split_documents(docs)

然后在split_documents()中分别对documents进行解压缩,最后嵌套调用create_documents()方法,

def split_documents(self, documents: List[Document]) -> List[Document]:
    """Split documents."""    
    texts = [doc.page_content for doc in documents]
    metadatas = [doc.metadata for doc in documents]
    return self.create_documents(texts, metadatas=metadatas)

create_documents()方法将每一篇文档传入split_text(text)进行解析,其中

输入:texts: List[str],输出:List[Document]

def create_documents(
    self, texts: List[str], metadatas: Optional[List[dict]] = None) -> List[Document]:
    """Create documents from a list of texts."""    
    _metadatas = metadatas or [{}] * len(texts)
    documents = []
    for i, text in enumerate(texts):
        for chunk in self.split_text(text):
            new_doc = Document(
                page_content=chunk, metadata=copy.deepcopy(_metadatas[i])
            )
            documents.append(new_doc)
    return documents

可以看到又进行了一个函数嵌套,最后定位到chinese_text_splitter.py的split_text(),其中具体逻辑就不展示了,这一块也是一个方法重载的过程,溯源起来发现ChineseTextSplitter中的split_text()继承了TextSplitter中的split_text()抽象方法然后进行实例化。实例化后的split_text()干了件啥事?就是把一篇文档按要求切成多个chunk,最后放在一个list里。

输入:text: str,输出:List[str]

def split_text(self, text: str) -> List[str]:   ##此处需要进一步优化逻辑
    paas

step4:load_and_split()进行文档切割把切好的chunk和对应的metadata重新组合形成一个Document对象,需要注意的是⚠️,此时Document对象放的是文章的某一个chunk,而不是整篇文章。最后返回一个List

def create_documents(
    self, texts: List[str], metadatas: Optional[List[dict]] = None) -> List[Document]:
    """Create documents from a list of texts."""    
    _metadatas = metadatas or [{}] * len(texts)
    documents = []
    for i, text in enumerate(texts):
        for chunk in self.split_text(text):
            new_doc = Document(
                page_content=chunk, metadata=copy.deepcopy(_metadatas[i])
            )
            documents.append(new_doc)
    return documents

如果想加入自己的文档切割方法该怎么做?可以重写一个类似于ChineseTextSplitter()方法就可以了!

标签:RAG,documents,text,self,List,实训,LLM,Document,split
From: https://www.cnblogs.com/h1s97x/p/18223745

相关文章

  • 山东大学项目实训-基于LLM的中文法律文书生成系统(十五)- RAG(4)
    引入RAGRAG前的工作流程如下:向模型提问->模型从已训练数据中查询数据->组织语言->生成答案。RAG后的工作流程如下:读取文档->分词->嵌入->将嵌入数据存入向量数据库->向模型提问->模型从向量数据库中查询数据->组织语言->生成答案。嵌入在人工智能中,嵌入(Embedding)是将数据向量......
  • Python实训的心路历程——第4天
    时间过得好快,转眼就第四天了,今天还是接着做界面,并往里面添加内容。========================================一天又过去了,但是每天都感觉自己成长了好多呢,哈哈来汇总一下今天的工作和收获今天把界面和一些基础的功能写完了,程序能正常跑了,可以处理实时摄像头、视频、图片三种......
  • 使用 LlamaIndex + Eleasticsearch ,进行 RAG 检索增强生成
    节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学.针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。合集:《大模型面试宝典》(2024版)正式发......
  • 创新实训(五)
    提交记录界面在该界面可以看到提交题目的情况可以查看题目,提交者,结果,用时,内存,使用语言,文件大小,提交时间等信息。点击编号可以查看详细答案和测试用例通过情况右下角可以对该提交记录进行管理......
  • 创新实训(四)
    添加新题功能在题库页面可添加新题点击添加新题按钮并确定后会首先生成一个空白的新题点击标题然后点击管理即可进入题目的管理界面题目部分使用markdown编写,右下角可以设置题目可见性题目管理者者管理页面数据管理页面......
  • 创新实训(二)
    项目测试从项目开发初期开始持续跟进项目功能测试,我主要负责管理员端内容。项目前端概览以下是我们的项目前端的大致框架结构,最上方从左到右依次是我们网站的logo,网站名称,登录注册按钮,再下方是导航栏,可导航到不同的子页面,在最右面是检索框,在下面就是子页面的主体。点击导航栏......
  • Kubernetes 硬盘持久化之 StorageClass
    Kubernetes硬盘持久化之StorageClassStorageClass定义StorageClass为管理员提供了描述存储"类"的方法。不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。这个类的概念在其他存储系统中有时被称为"配置文件"。每个StorageClass......
  • 创新实训(三)
    添加比赛功能仅展示大致框架,后续待功能完善后进行实际比赛的模拟报名选手列表管理页面......
  • 创新实训 (二)
    在对模型进行部署时,可以使用魔搭默认的环境,CPU免费,GPU有使用的时间限制,需要关联阿里云的账号,因为CodeGeeX要用GPU,所以先选择限制使用时长的GPU。在相应的模型库中选择:CodeFuse-CodeGeeX2-6B使用教程中对应的gitclonehttps://www.modelscope.cn/codefuse-ai/CodeFuse-C......
  • 创新实训 (一)
    为了提高在线评测系统的功能性,需要选择和集成一个强大的代码纠错大模型,用于自动分析和纠正用户提交的代码中的错误。这里的大模型我们选择使用清华大学开源的ChatGLM-CodeGeeX2。在该模型的基础上,选用程序设计试题的专门数据,进行Fine-turning的训练(即微调)。为了令CodeGeeX在......