利用 Gemini API 和 Elasticsearch 构建智能问答系统
本教程将深入探讨如何利用 Google 的 Gemini API 创建强大的自然语言处理(NLP)应用,并结合 Elasticsearch 的全文搜索能力,构建一个高效的智能问答系统。我们将聚焦于如何将 Gemini 连接到 Elasticsearch 中存储的私有数据,并借助 Langchain 框架搭建问答功能,实现企业内部知识的智能检索与应用。
技术准备
在开始之前,确保您已完成以下准备工作:
Elasticsearch 及 Kibana:
- 安装 Elasticsearch 及 Kibana。建议参考 Elastic Stack 8.x 的安装指南,确保环境配置正确。
Gemini 开发者 Key:
- 前往 Google AI Studio 获取 Gemini API 密钥。该密钥是访问 Gemini API 的凭证,用于后续的文本嵌入和问答功能。
设置环境变量:
- 在终端中设置环境变量,方便在代码中调用。这包括 Elasticsearch 的用户名、密码以及 Gemini API 密钥。
export ES_USER=elastic export ES_PASSWORD=your_elasticsearch_password export GOOGLE_API_KEY=your_gemini_api_key
拷贝 Elasticsearch 证书:
- 将 Elasticsearch 的证书文件(
http_ca.crt
)拷贝到当前工作目录,用于安全连接 Elasticsearch 集群。
cp ~/elastic/elasticsearch-8.12.0/config/certs/http_ca.crt .
- 将 Elasticsearch 的证书文件(
安装 Python 依赖包:
- 使用 pip 安装所需的 Python 包。这些包包括
google-generativeai
、elasticsearch
、langchain
和langchain_google_genai
,它们是构建问答系统的基础。
pip3 install -q -U google-generativeai elasticsearch langchain langchain_google_genai
- 使用 pip 安装所需的 Python 包。这些包包括
应用设计与实现
接下来,我们将逐步构建问答系统。
导入必要的 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
读取环境变量
使用
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'
加载并处理文档
下载示例数据集: 从 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)
使用 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)
创建 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})
格式化文档
定义一个函数
format_docs
,用于将检索到的文档格式化为字符串,以便在提示模板中使用。def format_docs(docs): return "\n\n".join(doc.page_content for doc in docs)
创建问答链
使用 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 这样的专业搜索引擎,可以为企业提供更智能化的数据服务。