开始使用 Semantic Kernel Python 集成
注意
本教程使用 Semantic Kernel Python 库。有关使用 C# 库的教程,请参阅语义内核 C# 集成入门。
您可以将 Atlas Vector Search 与 Microsoft Semantic Kernel 集成 构建 AI 应用程序并实施检索增强生成 (RAG)。本教程演示如何开始使用带有语义内核的Atlas Vector Search ,对数据执行语义Atlas Search并构建 RAG实施。 具体来说,您执行以下操作:
设置环境。
在 Atlas 上存储自定义数据。
在您的数据上创建一个 Atlas Vector Search 索引。
对您的数据运行语义搜索查询。
使用 Atlas Vector Search 来回答有关数据的问题,从而实现 RAG。
背景
Semantic Kernel 是一个开源 SDK,可让您将各种 AI 服务和插件与您的应用程序相结合。 您可以将语义内核用于各种 AI 使用案例,包括RAG 。
通过将 Atlas Vector Search 与语义内核集成,您可以将 Atlas 用作矢量数据库,并使用 Atlas Vector Search 通过从数据中检索语义相似的文档来实现 RAG。要了解有关 RAG 的更多信息,请参阅使用 Atlas Vector Search 进行检索增强生成 (RAG)。
先决条件
如要完成本教程,您必须具备以下条件:
设置环境
为此教程设置环境。通过保存扩展名为 .ipynb
的文件来创建交互式Python笔记本。此 Notebook 允许您单独运行Python代码片段,并且您将使用它来运行本教程中的代码。
要设立笔记本环境,请执行以下操作:
安装并导入依赖项。
在笔记本中运行以下命令,在您的环境中安装语义内核。
pip install --quiet --upgrade semantic-kernel openai motor 运行以下代码,导入所需包:
import getpass, openai import semantic_kernel as sk from semantic_kernel.connectors.ai.open_ai import (OpenAIChatCompletion, OpenAITextEmbedding) from semantic_kernel.connectors.memory.mongodb_atlas import MongoDBAtlasMemoryStore from semantic_kernel.core_plugins.text_memory_plugin import TextMemoryPlugin from semantic_kernel.memory.semantic_text_memory import SemanticTextMemory from semantic_kernel.prompt_template.input_variable import InputVariable from semantic_kernel.prompt_template.prompt_template_config import PromptTemplateConfig from pymongo import MongoClient from pymongo.operations import SearchIndexModel
定义环境变量。
运行以下代码并在出现提示时提供以下内容:
您的 OpenAI API 密钥。
您的Atlas集群的SRV连接string 。
OPENAI_API_KEY = getpass.getpass("OpenAI API Key:") ATLAS_CONNECTION_STRING = getpass.getpass("MongoDB Atlas SRV Connection String:")
注意
连接字符串应使用以下格式:
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net
在 Atlas 中存储自定义数据。
在本部分中,您将初始化内核,它是用于管理应用程序的服务和插件的主接口。通过内核,您可以配置 AI 服务,将 Atlas 实例化为向量数据库(也称为内存存储),并将自定义数据加载到 Atlas 集群。
要将自定义数据存储在 Atlas 中,请在笔记本中粘贴并运行以下代码片段:
将 AI 服务添加到内核。
运行以下代码以配置本教程中使用的 OpenAI 嵌入模型和聊天模型,并将这些服务添加到内核中。 此代码指定以下内容:
OpenAI 的
text-embedding-ada-002
作为嵌入模型,用于将文本转换为向量嵌入。OpenAI 的
gpt-3.5-turbo
作为聊天模型,用于生成响应。
chat_service = OpenAIChatCompletion( service_id="chat", ai_model_id="gpt-3.5-turbo", api_key=OPENAI_API_KEY ) embedding_service = OpenAITextEmbedding( ai_model_id="text-embedding-ada-002", api_key=OPENAI_API_KEY ) kernel.add_service(chat_service) kernel.add_service(embedding_service)
将 Atlas 实例化为内存存储。
运行以下代码,将 Atlas 实例化为内存存储,并将其添加到内核中。 此代码建立与 Atlas 集群的连接并指定以下内容:
semantic_kernel_db
作为用于存储文档的 Atlas 数据库。vector_index
作为用于运行语义Atlas Search查询的索引。
它还导入一个名为TextMemoryPlugin
的插件,其中提供了一群组原生函数来帮助您在内存中存储和检索文本。
mongodb_atlas_memory_store = MongoDBAtlasMemoryStore( connection_string=ATLAS_CONNECTION_STRING, database_name="semantic_kernel_db", index_name="vector_index" ) memory = SemanticTextMemory( storage=mongodb_atlas_memory_store, embeddings_generator=embedding_service ) kernel.add_plugin(TextMemoryPlugin(memory), "TextMemoryPlugin")
在 Atlas 集群上加载样本数据。
此代码将定义并运行一个函数,以使用某些示例文档填充 semantic_kernel_db.test
集合。这些文档包含 LLM 最初无法访问的个性化数据。
async def populate_memory(kernel: sk.Kernel) -> None: await memory.save_information( collection="test", id="1", text="I am a developer" ) await memory.save_information( collection="test", id="2", text="I started using MongoDB two years ago" ) await memory.save_information( collection="test", id="3", text="I'm using MongoDB Vector Search with Semantic Kernel to implement RAG" ) await memory.save_information( collection="test", id="4", text="I like coffee" ) print("Populating memory...") await populate_memory(kernel) print(kernel)
Populating memory... plugins=KernelPluginCollection(plugins={'TextMemoryPlugin': KernelPlugin(name='TextMemoryPlugin', description=None, functions={'recall': KernelFunctionFromMethod(metadata=KernelFunctionMetadata(name='recall', plugin_name='TextMemoryPlugin', description='Recall a fact from the long term memory', parameters=[KernelParameterMetadata(name='ask', description='The information to retrieve', default_value=None, type_='str', is_required=True, type_object=<class 'str'>), KernelParameterMetadata(name='collection', description='The collection to search for information.', default_value='generic', type_='str', is_required=False, type_object=<class 'str'>), KernelParameterMetadata(name='relevance', description='The relevance score, from 0.0 to 1.0; 1.0 means perfect match', default_value=0.75, type_='float', is_required=False, type_object=<class 'float'>), KernelParameterMetadata(name='limit', description='The maximum number of relevant memories to recall.', default_value=1, type_='int', is_required=False, type_object=<class 'int'>)], is_prompt=False, is_asynchronous=True, return_parameter=KernelParameterMetadata(name='return', description='', default_value=None, type_='str', is_required=True, type_object=None)), method=<bound method TextMemoryPlugin.recall of TextMemoryPlugin(memory=SemanticTextMemory())>, stream_method=None), 'save': KernelFunctionFromMethod(metadata=KernelFunctionMetadata(name='save', plugin_name='TextMemoryPlugin', description='Save information to semantic memory', parameters=[KernelParameterMetadata(name='text', description='The information to save.', default_value=None, type_='str', is_required=True, type_object=<class 'str'>), KernelParameterMetadata(name='key', description='The unique key to associate with the information.', default_value=None, type_='str', is_required=True, type_object=<class 'str'>), KernelParameterMetadata(name='collection', description='The collection to save the information.', default_value='generic', type_='str', is_required=False, type_object=<class 'str'>)], is_prompt=False, is_asynchronous=True, return_parameter=KernelParameterMetadata(name='return', description='', default_value=None, type_='', is_required=True, type_object=None)), method=<bound method TextMemoryPlugin.save of TextMemoryPlugin(memory=SemanticTextMemory())>, stream_method=None)})}) services={'chat': OpenAIChatCompletion(ai_model_id='gpt-3.5-turbo', service_id='chat', client=<openai.AsyncOpenAI object at 0x7999971c8fa0>, ai_model_type=<OpenAIModelTypes.CHAT: 'chat'>, prompt_tokens=0, completion_tokens=0, total_tokens=0), 'text-embedding-ada-002': OpenAITextEmbedding(ai_model_id='text-embedding-ada-002', service_id='text-embedding-ada-002', client=<openai.AsyncOpenAI object at 0x7999971c8fd0>, ai_model_type=<OpenAIModelTypes.EMBEDDING: 'embedding'>, prompt_tokens=32, completion_tokens=0, total_tokens=32)} ai_service_selector=<semantic_kernel.services.ai_service_selector.AIServiceSelector object at 0x7999971cad70> retry_mechanism=PassThroughWithoutRetry() function_invoking_handlers={} function_invoked_handlers={}
提示
运行示例代码后,您可以导航到您的集群中的semantic_kernel_db.test
collection,在 Atlas 用户界面中查看向量嵌入。
创建 Atlas Vector Search 索引
注意
要创建 Atlas Vector Search 索引,您必须对 Atlas 项目具有Project Data Access Admin
或更高访问权限。
要在向量存储上启用向量搜索查询,请在semantic_kernel_db.test
集合上创建 Atlas Vector Search 索引。
在笔记本中,运行以下代码以连接您的 Atlas 集群并创建 VectorSearch 类型的索引。此索引定义指定对以下字段进行索引:
embedding
字段作为向量类型。embedding
字段包含使用 OpenAI 的text-embedding-ada-002
嵌入模型创建的嵌入。 索引定义指定了1536
向量维度,并使用cosine
来衡量相似性。
# Connect to your Atlas cluster and specify the collection client = MongoClient(ATLAS_CONNECTION_STRING) collection = client["semantic_kernel_db"]["test"] # Create your index model, then create the search index search_index_model = SearchIndexModel( definition={ "fields": [ { "type": "vector", "path": "embedding", "numDimensions": 1536, "similarity": "cosine" } ] }, name="vector_index", type="vectorSearch" ) collection.create_search_index(model=search_index_model)
构建索引大约需要一分钟时间。在建立索引时,索引处于初始同步状态。 构建完成后,您可以开始查询集合中的数据。
运行向量搜索查询
Atlas构建索引后,您可以对数据运行向量Atlas Search查询。
在 notebook 中,运行以下代码,对字符串 What is my job title?
执行基本语义搜索。它打印最相关的文档以及介于 0
和 1
之间的相关性分数。
result = await memory.search("test", "What is my job title?") print(f"Retrieved document: {result[0].text}, {result[0].relevance}")
Retrieved document: I am a developer, 0.8991971015930176
回答有关数据的问题
本部分展示使用 Atlas Vector Search 和语义内核的RAG实施示例。 现在您已经使用Atlas Vector Search检索语义相似的文档,运行以下代码示例以提示LLM回答基于这些文档的问题。
以下代码定义了一个 提示符 LLM指示 使用检索到的文档作为查询的上下文。在此示例中,您使用样本查询 When did I start using MongoDB?
提示LLM 。 由于您使用自定义数据扩展了LLM的知识库,因此聊天模型能够生成更准确、上下文感知的响应。
service_id = "chat" settings = kernel.get_service(service_id).instantiate_prompt_execution_settings( service_id=service_id ) prompt_template = """ Answer the following question based on the given context. Question: {{$input}} Context: {{$context}} """ chat_prompt_template_config = PromptTemplateConfig( execution_settings=settings, input_variables=[ InputVariable(name="input"), InputVariable(name="context") ], template=prompt_template ) prompt = kernel.add_function( function_name="RAG", plugin_name="TextMemoryPlugin", prompt_template_config=chat_prompt_template_config, ) question = "When did I start using MongoDB?" results = await memory.search("test", question) retrieved_document = results[0].text answer = await prompt.invoke( kernel=kernel, input=question, context=retrieved_document ) print(answer)
You started using MongoDB two years ago.
后续步骤
MongoDB 还提供以下开发者资源: