Gemini 与 Elasticsearch 联手打造智能问答系统

1

利用 Gemini API 和 Elasticsearch 构建智能问答系统

本教程将深入探讨如何利用 Google 的 Gemini API 创建强大的自然语言处理(NLP)应用,并结合 Elasticsearch 的全文搜索能力,构建一个高效的智能问答系统。我们将聚焦于如何将 Gemini 连接到 Elasticsearch 中存储的私有数据,并借助 Langchain 框架搭建问答功能,实现企业内部知识的智能检索与应用。

技术准备

在开始之前,确保您已完成以下准备工作:

  1. Elasticsearch 及 Kibana:

    • 安装 Elasticsearch 及 Kibana。建议参考 Elastic Stack 8.x 的安装指南,确保环境配置正确。
  2. Gemini 开发者 Key:

    • 前往 Google AI Studio 获取 Gemini API 密钥。该密钥是访问 Gemini API 的凭证,用于后续的文本嵌入和问答功能。
  3. 设置环境变量:

    • 在终端中设置环境变量,方便在代码中调用。这包括 Elasticsearch 的用户名、密码以及 Gemini API 密钥。
    export ES_USER=elastic
    export ES_PASSWORD=your_elasticsearch_password
    export GOOGLE_API_KEY=your_gemini_api_key
  4. 拷贝 Elasticsearch 证书:

    • 将 Elasticsearch 的证书文件(http_ca.crt)拷贝到当前工作目录,用于安全连接 Elasticsearch 集群。
    cp ~/elastic/elasticsearch-8.12.0/config/certs/http_ca.crt .
  5. 安装 Python 依赖包:

    • 使用 pip 安装所需的 Python 包。这些包包括 google-generativeaielasticsearchlangchainlangchain_google_genai,它们是构建问答系统的基础。
    pip3 install -q -U google-generativeai elasticsearch langchain langchain_google_genai

应用设计与实现

接下来,我们将逐步构建问答系统。

  1. 导入必要的 Python 包

    首先,导入所需的 Python 包。这些包提供了访问 Gemini API、Elasticsearch 和 Langchain 功能的接口。

    import google.generativeai as genai
    import google.ai.generativelanguage as glm
    from elasticsearch import Elasticsearch, helpers
    from langchain.vectorstores import ElasticsearchStore
    from langchain.text_splitter import CharacterTextSplitter
    from langchain_google_genai import GoogleGenerativeAIEmbeddings
    from langchain_google_genai import ChatGoogleGenerativeAI
    from langchain.prompts import ChatPromptTemplate
    from langchain.prompts import PromptTemplate
    from langchain.schema.output_parser import StrOutputParser
    from langchain.schema.runnable import RunnablePassthrough
    from langchain.schema.runnable import RunnableLambda
    from langchain.schema import HumanMessage
    from urllib.request import urlopen
    from dotenv import load_dotenv
    import json, os
  2. 读取环境变量

    使用 dotenv 库读取环境变量,包括 Gemini API 密钥、Elasticsearch 用户名和密码。

    load_dotenv()
    
    GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
    ES_USER = os.getenv("ES_USER")
    ES_PASSWORD = os.getenv("ES_PASSWORD")
    elastic_index_name='gemini-qa'
  3. 加载并处理文档

    • 下载示例数据集: 从 GitHub 仓库下载示例数据集(data.json)。该数据集包含一系列文档,用于构建问答系统的知识库。

      wget https://raw.githubusercontent.com/liu-xiao-guo/semantic_search_es/main/datasets/data.json
    • 加载 JSON 数据: 将下载的 JSON 数据加载到 Python 对象中。

      with open('./datasets/data.json') as f:
         workplace_docs = json.load(f)
      
      print(f"Successfully loaded {len(workplace_docs)} documents")
    • 将文档拆分为段落: 使用 CharacterTextSplitter 将文档拆分为更小的段落,以便更好地进行语义搜索。

      metadata = []
      content = []
      
      for doc in workplace_docs:
        content.append(doc["content"])
        metadata.append({
            "name": doc["name"],
            "summary": doc["summary"],
            "rolePermissions":doc["rolePermissions"]
        })
      
      text_splitter = CharacterTextSplitter(chunk_size=50, chunk_overlap=0)
      docs = text_splitter.create_documents(content, metadatas=metadata)
  4. 使用 Gemini Embeddings 将文档索引到 Elasticsearch

    • 配置 Elasticsearch 连接: 创建 Elasticsearch 客户端,配置连接参数,包括主机地址、用户名、密码和证书。

      url = f"https://{ES_USER}:{ES_PASSWORD}@192.168.0.3:9200"
      
      connection = Elasticsearch(
              hosts=[url], 
              ca_certs = "./http_ca.crt", 
              verify_certs = True
      )
      print(connection.info())
    • 创建 Gemini Embeddings 实例: 创建 GoogleGenerativeAIEmbeddings 实例,指定用于生成文本嵌入的模型。

      embeddings = GoogleGenerativeAIEmbeddings(
          model="models/embedding-001", task_type="retrieval_document"
      )
    • 将文档索引到 Elasticsearch: 使用 ElasticsearchStore 将文档及其嵌入向量索引到 Elasticsearch 中。这使得我们可以使用语义搜索来检索相关文档。

      es = ElasticsearchStore.from_documents( 
                                  docs,
                                  embedding = embeddings, 
                                  es_url = url, 
                                  es_connection = connection,
                                  index_name = elastic_index_name, 
                                  es_user = ES_USER,
                                  es_password = ES_PASSWORD)
  5. 创建 Retriever

    • 创建 Retriever 实例,用于从 Elasticsearch 中检索相关文档。Retriever 使用 Gemini Embeddings 将查询转换为向量,并在 Elasticsearch 中执行相似性搜索。

      embeddings = GoogleGenerativeAIEmbeddings(
          model="models/embedding-001", task_type="retrieval_query"
      )
      
      retriever = es.as_retriever(search_kwargs={"k": 3})
  6. 格式化文档

    • 定义一个函数 format_docs,用于将检索到的文档格式化为字符串,以便在提示模板中使用。

      def format_docs(docs):
          return "\n\n".join(doc.page_content for doc in docs)
  7. 创建问答链

    • 使用 Prompt Template 和 gemini-pro 模型创建一个问答链。该链首先使用 Retriever 检索相关文档,然后使用 Prompt Template 将问题和文档组合成提示,最后使用 gemini-pro 模型生成答案。

      template = """Answer the question based only on the following context:\n
      {context}
      
      Question: {question}
      """
      prompt = ChatPromptTemplate.from_template(template)
      
      
      chain = (
          {"context": retriever | format_docs, "question": RunnablePassthrough()} 
          | prompt 
          | ChatGoogleGenerativeAI(model="gemini-pro", temperature=0.7) 
          | StrOutputParser()
      )
      
      chain.invoke("what is our sales goals?")

总结

本教程演示了如何使用 Gemini API、Elasticsearch 和 Langchain 构建一个智能问答系统。通过将 Gemini 的文本嵌入能力与 Elasticsearch 的全文搜索能力相结合,我们可以构建一个能够理解自然语言问题并从私有数据中检索相关信息的强大工具。该系统可用于企业内部知识管理、客户服务等领域,提高工作效率和决策质量。

通过本文,我们可以看到 Gemini 在语义搜索领域的巨大潜力。结合 Elasticsearch 这样的专业搜索引擎,可以为企业提供更智能化的数据服务。