文档检索和LLM集成

本文介绍AnalyticDB PostgreSQL版如何通过Python代码进行文本检索及在LangChain中实现问答系统。

文档检索

本章节以使用纯文本检索为例,示例代码如下:

def query_content(namespace, namespace_password, collection, top_k,
                  content,
                  filter_str: str = None,
                  metrics: str = None,
                  use_full_text_retrieval: bool = None):
      request = gpdb_20160503_models.QueryContentRequest(
          region_id=ADBPG_INSTANCE_REGION,
          dbinstance_id=ADBPG_INSTANCE_ID,
          namespace=namespace,
          namespace_password=namespace_password,
          collection=collection,
          content=content,
          filter=filter_str,
          top_k=top_k,
          metrics=metrics,
          use_full_text_retrieval=use_full_text_retrieval,
      )
      response = get_client().query_content(request)
      print(f"query_content response code: {response.status_code}, body:{response.body}")


if __name__ == '__main__':
    query_content('ns1', 'Ns1password', 'dc1', 10, 'ADBPG是什么?')


# output: body:
# {
#   "Matches": 
#      {
#        "MatchList": 
#          [{
#            "Content": "ADBPG...",
#            "FileName": "test.pdf", 
#            "Id": "9368a9aa-8a26-4200-b84b-cab4e06dbbd4_20"
#            "LoaderMetadata": "\"page\":1.0,\"total_pages\":15.0,\"format\":\"PDF 1.4\",\"title\":\"\",\"author\":\"\",\"subject\":\"\",\"keywords\":\"\",\"creator\":\"Chromium\",\"producer\":\"Skia/PDF m93\",\"creationDate\":\"D:20231213060903+00\\u002700\\u0027\",\"modDate\":\"D:20231213060903+00\\u002700\\u0027\",\"trapped":\"\"}", 
#            "Metadata": {}, 
#            "RetrievalSource": 1, 
#            "Score": 0.7038057130604151
#          },....]
#      }
# }

其中query_content参数说明如下:

  • namespace:文档库所在的Namespace名称。

  • namespace_password:Namespace的密码。

  • collection:文档库名称。

  • top_k:返回相似度最高的检索结果数量。

  • content:要检索的文本内容。

  • filter_str:检索前的过滤语句。

  • metrics:向量距离算法,建议不设置,会按照创建索引时的算法计算。

  • use_full_text_retrieval:是否使用全文检索,取值说明如下:

    • true:使用全文检索。

    • false(默认):不使用全文检索。

返回的检索结果列表包含以下信息:

  • Id:切分后的Chunk对应的UUID。

  • FileName:文档名称。

  • Content:检索的内容,即切分后的一条Chunk。

  • LoaderMetadata:在文档上传时产生的Metadata数据。

  • Metadata:用户自定义的Metadata数据。

  • RetrievalSource:检索来源,取值说明如下:

    • 1:向量检索命中。

    • 2:全文检索命中。

    • 3:向量检索和全文检索双路命中。

  • Score:按照指定的相似度算法得到的相似度分数。

集成LangChain

LangChain是一套基于大语言模型(LLM)构建应用的开源框架,可实现通过一整套接口和工具将模型和外部数据连接。下文将展示如何将AnalyticDB PostgreSQL版的检索能力集成到LangChain中实现一个问答系统。

安装模块

pip install --upgrade langchain openai tiktoken

构建AdbpgRetriever

from langchain_core.retrievers import BaseRetriever
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document


class AdbpgRetriever(BaseRetriever):
    namespace: str = None
    namespace_password: str = None
    collection: str = None
    top_k: int = None
    use_full_text_retrieval: bool = None

    def query_content(self, content) -> List[gpdb_20160503_models.QueryContentResponseBodyMatchesMatchList]:
        request = gpdb_20160503_models.QueryContentRequest(
            region_id=ADBPG_INSTANCE_REGION,
            dbinstance_id=ADBPG_INSTANCE_ID,
            namespace=self.namespace,
            namespace_password=self.namespace_password,
            collection=self.collection,
            content=content,
            top_k=self.top_k,
            use_full_text_retrieval=self.use_full_text_retrieval,
        )
        response = get_client().query_content(request)
        return response.body.matches.match_list

    def _get_relevant_documents(
            self, query: str, *, run_manager: CallbackManagerForRetrieverRun
    ) -> List[Document]:
        match_list = self.query_content(query)
        return [Document(page_content=i.content) for i in match_list]

创建Chain

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

OPENAI_API_KEY = "YOUR_OPENAI_API_KEY"
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

template = """Answer the question based only on the following context:

{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()


def format_docs(docs):
    return "\n\n".join([d.page_content for d in docs])

retriever = AdbpgRetriever(namespace='ns1', namespace_password='Ns1password', collection='dc1', top_k=10, use_full_text_retrieval=True)
chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)

问答

chain.invoke("AnalyticDB PostgreSQL是什么?")

# 回答:
# AnalyticDB PostgreSQL是阿里云提供的一种云原生在线分析处理(OLAP)服务,它基于开源的PostgreSQL数据库扩展,提供了高性能、高容量的数据仓库解决方案。
# 它结合了PostgreSQL的灵活性和兼容性以及用于数据分析和报告的高并发和高速查询能力。
#
# AnalyticDB PostgreSQL特别适合处理大规模数据集,支持实时分析和决策支持,是企业进行数据挖掘、商业智能(BI)、报告和数据可视化的有力工具。
# 作为一种托管服务,它简化了数据仓库的管理和运维,让用户能够专注于数据分析而不是底层基础设施。
# 主要特点包括:
# 
# 高性能分析 - 使用列式存储和大规模并行处理(MPP)架构来快速查询和分析大量数据。
# 易于扩展 - 根据数据量和查询性能要求,容易横向和纵向扩展资源。
# 兼容 PostgreSQL - 支持PostgreSQL SQL语言和生态系统中的大部分工具,便于现有 PostgreSQL 用户迁移和适应。
# 安全和可靠 - 提供数据备份、恢复和加密等功能,确保数据的安全性和可靠性。
# 云原生集成 - 与阿里云的其他服务如数据集成、数据可视化工具等紧密集成。
# 总之,AnalyticDB PostgreSQL是一个高性能、可扩展的云数据仓库服务,允许企业在云环境中进行复杂的数据分析和报告。