首页 > 编程语言 >Langchain-ChatGLM源码解读(一)-文档数据上传

Langchain-ChatGLM源码解读(一)-文档数据上传

时间:2024-03-14 20:34:56浏览次数:35  
标签:documents text self List Langchain 源码 split ChatGLM Document

一、简介

Langchain-ChatGLM 相信大家都不陌生,近几周计划出一个源码解读,先解锁langchain的一些基础用法。

文档问答过程大概分为以下5部分,在Langchain中都有体现。

  1. 上传解析文档
  2. 文档向量化、存储
  3. 文档召回
  4. query向量化
  5. 文档问答

今天主要讲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()方法就可以了!

胖友,请不要忘了一键三连点赞哦!

转载请注明出处:QA Weekly

标签:documents,text,self,List,Langchain,源码,split,ChatGLM,Document
From: https://www.cnblogs.com/gongzb/p/18073874

相关文章

  • 基于SpringBoot实现企业技术员工测评考试管理系统演示【附项目源码+论文说明】
    基于SpringBoot实现企业技术员工测评考试管理系统演示摘要社会的发展和科学技术的进步,互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。互联网具有便利性,速度快,效率高,成本低等优点。因此,构建符合自己要求的操作系......
  • 基于springboot实现网页时装购物系统演示【附项目源码+论文说明】
    基于springboot实现网页时装购物系统演示摘要随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,时装购物系统当然也不能排除在外。时装购物系统是以实际运用为开发背景,运用软件工程原理和开发方法,采用springboot......
  • 基于springcloud实现鲜花订购网微服务演示【附项目源码】
    基于springcloud实现鲜花订购网微服务演示JAVA简介Java主要采用CORBA技术和安全模型,可以在互联网应用的数据保护。它还提供了对EJB(EnterpriseJavaBeans)的全面支持,javaservletAPI,JSP(javaserverpages),和XML技术。Java是一种计算机编程语言,具有封装、继承和多态性三个......
  • Langchain-ChatGLM源码解读(二)-文档embedding以及构建faiss过程
    一、简介Langchain-ChatGLM 相信大家都不陌生,近几周计划出一个源码解读,先解锁langchain的一些基础用法。文档问答过程大概分为以下5部分,在Langchain中都有体现。上传解析文档文档向量化、存储文档召回query向量化文档问答今天主要讲langchain在文档embedding以及构建fa......
  • 河北王校长源码之AQS
    AQSAQS可以重写的方法//排他锁protectedbooleantryAcquire(intarg){returnsuper.tryAcquire(arg);}protectedbooleantryRelease(intarg){returnsuper.tryRelease(arg);}//共享锁......
  • 河北王校长源码之HashMap
    HashMap类结构继承AbstractMap<K,V>实现Map<K,V>Map基本方法实现Cloneable浅克隆实现Serializable序列化成员变量//默认初始化容量staticfinalintDEFAULT_INITIAL_CAPACITY=1<<4;//数组最大长度staticfinalintMAXIMUM_CAPAC......
  • 河北王校长源码之ArrayList
    ArrayListy类结构继承AbstractList实现Listlist基本方法实现RandomAccess支持随机访问(下标)for效率高于迭代器(对比LinkedList)实现Cloneable浅克隆实现Serializable序列化成员变量默认容量privatestaticfinalintDEFAULT_CAPACITY=10;空数组......
  • Linux源码安装nginx1.20.2
    下面是关于Linux源码安装nginx1.20.2的操作流程目录前言1,安装准备1.1下载安装包 1.2上传安装包1.3解压  1.4关闭防火墙和selinux2,安装 nginx依赖库以及编译环境2.1安装nginx依赖库 2.2执行configure脚本生成makefile配置文件2.2.1可能出现的错误 3,......
  • PG14:auth_delay 插件源码分析
    auth_delay让服务器在报告身份验证失败前短暂暂停,以增加对数据库密码进行暴力破解的难度。需要注意的是,这对阻止拒绝服务攻击毫无帮助,甚至可能加剧攻击,因为在报告身份验证失败前等待的进程仍会占用连接。要使用这个模块必须要在postgresql.conf中配置参数shared_preload_libr......
  • 容器集群实现多机多卡分布式微调大模型chatglm2-6b(deepseed + LLaMA + NCCL)
    环境信息2台物理机(187.135,187.136),各两张p4显卡,安装好docker=20.10.0,安装好nvidia驱动(driverversion=470.223.02,cudaversion=11.4)构造容器集群(dockerswarm187.136节点作为manager节点,187.135节点作为worker节点)[root@host-136~]#dockerswarminit--advertise-addr......