本教程演示如何使用 Gemini API创建 embeddings 并将其存储在 Elasticsearch 中。 我们将学习如何将 Gemini 连接到 Elasticsearch 中存储的私有数据,并使用 Langchian 构建问答功能。
准备
Elasticsearch 及 Kibana
如果你还没有安装好自己的 Elasticsearch 及 Kibana 的话,请参阅如下的文章来进行安装:
在安装的时候,请参照 Elastic Stack 8.x 的文章来进行安装。
Gemini 开发者 key
你可以参考文章 来申请一个免费的 key 供下面的开发。你也可以直接去地址进行申请。
设置环境变量
我们在 termnial 中打入如下的命令来设置环境变量:
ini
1. export ES_USER=elastic
2. export ES_PASSWORD=-M3aD_m3MHCZNYyJi_V2
3. export GOOGLE_API_KEY=YourGoogleAPIkey
拷贝 Elasticsearch 证书
我们把 Elasticsearch 的证书拷贝到当前的目录下:
bash
1. $ pwd
2. /Users/liuxg/python/elser
3. $ cp ~/elastic/elasticsearch-8.12.0/config/certs/http_ca.crt .
安装 Python 依赖包
css
pip3 install -q -U google-generativeai elasticsearch langchain langchain_google_genai
应用设计
我们在当前的工作目录下打入命令:
jupyter notebook
导入包
javascript
1. import google.generativeai as genai
2. import google.ai.generativelanguage as glm
3. from elasticsearch import Elasticsearch, helpers
4. from langchain.vectorstores import ElasticsearchStore
5. from langchain.text_splitter import CharacterTextSplitter
6. from langchain_google_genai import GoogleGenerativeAIEmbeddings
7. from langchain_google_genai import ChatGoogleGenerativeAI
8. from langchain.prompts import ChatPromptTemplate
9. from langchain.prompts import PromptTemplate
10. from langchain.schema.output_parser import StrOutputParser
11. from langchain.schema.runnable import RunnablePassthrough
12. from langchain.schema.runnable import RunnableLambda
13. from langchain.schema import HumanMessage
14. from urllib.request import urlopen
15. from dotenv import load_dotenv
16. import json, os
读取环境变量
ini
1. load_dotenv()
3. GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
4. ES_USER = os.getenv("ES_USER")
5. ES_PASSWORD = os.getenv("ES_PASSWORD")
6. elastic_index_name='gemini-qa'
写入文档
让我们下载示例数据集并反序列化文档
我们首先在地址下载示例数据集:
arduino
wget https://raw.githubusercontent.com/liu-xiao-guo/semantic_search_es/main/datasets/data.json
其中的一个文档的内容如下:
markdown
1. $ pwd
2. /Users/liuxg/python/elser
3. $ ls datasets/
4. data.json
python
1. # Load data into a JSON object
2. with open('./datasets/data.json') as f:
3. workplace_docs = json.load(f)
5. print(f"Successfully loaded {len(workplace_docs)} documents")
将文档拆分为段落
css
1. metadata = []
2. content = []
4. for doc in workplace_docs:
5. content.append(doc["content"])
6. metadata.append({
7. "name": doc["name"],
8. "summary": doc["summary"],
9. "rolePermissions":doc["rolePermissions"]
10. })
12. text_splitter = CharacterTextSplitter(chunk_size=50, chunk_overlap=0)
13. docs = text_splitter.create_documents(content, metadatas=metadata)
使用 Gemini Embeddings 将文档索引到 Elasticsearch
ini
1. url = f"https://{ES_USER}:{ES_PASSWORD}@192.168.0.3:9200"
3. connection = Elasticsearch(
4. hosts=[url],
5. ca_certs = "./http_ca.crt",
6. verify_certs = True
7. )
8. print(connection.info())
10. embeddings = GoogleGenerativeAIEmbeddings(
11. model="models/embedding-001", task_type="retrieval_document"
12. )
14. es = ElasticsearchStore.from_documents(
15. docs,
16. embedding = embeddings,
17. es_url = url,
18. es_connection = connection,
19. index_name = elastic_index_name,
20. es_user = ES_USER,
21. es_password = ES_PASSWORD)
运行完上面的代码后,我们可以去 Kibana 中进行查看:
创建 retriever
更多搜索的方法可以参考 "Elasticsearch:使用 Open AI 和 Langchain 的 RAG - Retrieval Augmented Generation (四)"。
ini
1. embeddings = GoogleGenerativeAIEmbeddings(
2. model="models/embedding-001", task_type="retrieval_query"
3. )
5. retriever = es.as_retriever(search_kwargs={"k": 3})
格式化文档
python
1. def format_docs(docs):
2. return "\n\n".join(doc.page_content for doc in docs)
使用 Prompt Template+gemini-pro 模型创建一条链
ini
1. template = """Answer the question based only on the following context:\n
3. {context}
5. Question: {question}
6. """
7. prompt = ChatPromptTemplate.from_template(template)
10. chain = (
11. {"context": retriever | format_docs, "question": RunnablePassthrough()}
12. | prompt
13. | ChatGoogleGenerativeAI(model="gemini-pro", temperature=0.7)
14. | StrOutputParser()
15. )
17. chain.invoke("what is our sales goals?")
最终的的 notebook 可以在地址找到:github.com/liu-xiao-gu...