Skip to main content
本笔记本介绍如何使用一种特殊的语言解析方法加载源代码文件:代码中每个顶级函数和类将被加载为单独的文档。已加载的函数和类之外的其他顶级代码也将作为单独的文档加载。 这种方法有助于提升源代码问答模型的准确性。 代码解析支持的语言包括:
  • C (*)
  • C++ (*)
  • C# (*)
  • COBOL
  • Elixir
  • Go (*)
  • Java (*)
  • JavaScript(需要 esprima 包)
  • Kotlin (*)
  • Lua (*)
  • Perl (*)
  • Python
  • Ruby (*)
  • Rust (*)
  • Scala (*)
  • TypeScript (*)
标注 (*) 的项需要安装 tree_sittertree_sitter_languages 包。 使用 tree_sitter 添加对其他语言的支持较为直接, 但目前需要修改 LangChain 源码。 可配置用于解析的语言,以及激活基于语法拆分所需的最小行数。 如果未明确指定语言,LanguageParser 将根据文件扩展名(如有)自动推断。
pip install -qU esprima esprima tree_sitter tree_sitter_languages
import warnings

warnings.filterwarnings("ignore")
from pprint import pprint

from langchain_community.document_loaders.generic import GenericLoader
from langchain_community.document_loaders.parsers import LanguageParser
from langchain_text_splitters import Language
loader = GenericLoader.from_filesystem(
    "./example_data/source_code",
    glob="*",
    suffixes=[".py", ".js"],
    parser=LanguageParser(),
)
docs = loader.load()
len(docs)
6
for document in docs:
    pprint(document.metadata)
{'content_type': 'functions_classes',
 'language': <Language.PYTHON: 'python'>,
 'source': 'example_data/source_code/example.py'}
{'content_type': 'functions_classes',
 'language': <Language.PYTHON: 'python'>,
 'source': 'example_data/source_code/example.py'}
{'content_type': 'simplified_code',
 'language': <Language.PYTHON: 'python'>,
 'source': 'example_data/source_code/example.py'}
{'content_type': 'functions_classes',
 'language': <Language.JS: 'js'>,
 'source': 'example_data/source_code/example.js'}
{'content_type': 'functions_classes',
 'language': <Language.JS: 'js'>,
 'source': 'example_data/source_code/example.js'}
{'content_type': 'simplified_code',
 'language': <Language.JS: 'js'>,
 'source': 'example_data/source_code/example.js'}
print("\n\n--8<--\n\n".join([document.page_content for document in docs]))
对于行数较少的小文件,可以禁用解析器。 parser_threshold 参数指定源代码文件使用解析器进行分段所需的最小行数。
loader = GenericLoader.from_filesystem(
    "./example_data/source_code",
    glob="*",
    suffixes=[".py"],
    parser=LanguageParser(language=Language.PYTHON, parser_threshold=1000),
)
docs = loader.load()
len(docs)
1
print(docs[0].page_content)

拆分

对于过大的函数、类或脚本,可能还需要进行额外的拆分。
loader = GenericLoader.from_filesystem(
    "./example_data/source_code",
    glob="*",
    suffixes=[".js"],
    parser=LanguageParser(language=Language.JS),
)
docs = loader.load()
from langchain_text_splitters import (
    Language,
    RecursiveCharacterTextSplitter,
)
js_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.JS, chunk_size=60, chunk_overlap=0
)
result = js_splitter.split_documents(docs)
len(result)
7

使用 tree-sitter 模板添加语言支持

使用 Tree-Sitter 模板扩展语言支持需要以下几个步骤:
  1. 创建新的语言文件
    • 在指定目录(langchain/libs/community/langchain_community/document_loaders/parsers/language)下创建新文件。
    • 参照现有语言文件(如 cpp.py)的结构和解析逻辑。
    • 还需在 langchain 目录(langchain/libs/langchain/langchain/document_loaders/parsers/language)下创建文件。
  2. 解析语言特性
    • 模仿 cpp.py 文件的结构,将其适配到您要添加的语言。
    • 主要改动是调整 chunk query 数组,以适应目标语言的语法和结构。
  3. 测试语言解析器
    • 为充分验证,为新语言生成专项测试文件。在指定目录(langchain/libs/community/tests/unit_tests/document_loaders/parsers/language)下创建 test_language.py
    • 参照 test_cpp.py 为新语言中的已解析元素建立基础测试。
  4. 集成到解析器和文本分割器
    • language_parser.py 文件中加入新语言。确保更新 LANGUAGE_EXTENSIONS 和 LANGUAGE_SEGMENTERS,以及 LanguageParser 的文档字符串,以识别和处理新增语言。
    • 同时确认 text_splitter.py 中的 Language 类也包含了您的语言,以便正确解析。
按照以上步骤操作,并确保完整的测试和集成,您将成功使用 Tree-Sitter 模板扩展语言支持。 祝您顺利!