Docs 菜单
Docs 主页
/ /

开始使用 Semantic Kernel Python 集成

注意

本教程使用语义内核 Python库。有关使用C#库的教程,请参阅 语义内核C#集成入门。

您可以将 MongoDB Vector Search 与 Microsoft 语义内核 集成,以构建 AI 应用程序并实现检索增强生成 (RAG)。本教程演示如何开始使用带有语义内核的MongoDB Vector Search 对数据执行语义搜索并构建RAG实施。具体来说,您执行以下操作:

  1. 设置环境。

  2. 在MongoDB中存储自定义数据。

  3. 对数据创建MongoDB Vector Search索引。

  4. 对您的数据运行语义搜索查询。

  5. 使用MongoDB Vector Search 来回答有关数据的问题,从而实施 RAG。

使用本教程的可运行版本以作为 Python 笔记本。

Semantic Kernel 是一个开源 SDK,可让您将各种 AI 服务和插件与您的应用程序相结合。 您可以将语义内核用于各种 AI 使用案例,包括RAG

通过将MongoDB Vector Search 与语义内核集成,您可以将MongoDB用作向量数据库,并使用MongoDB Vector Search 从数据中检索语义相似的文档来实现RAG。要学习;了解有关RAG的更多信息,请参阅使用MongoDB进行检索增强生成 (RAG)

如要完成本教程,您必须具备以下条件:

  • 以下MongoDB 集群类型之一:

  • OpenAI API密钥。您必须拥有一个具有可用于API请求的积分的 OpenAI 帐户。要学习;了解有关注册 OpenAI 帐户的更多信息,请参阅 OpenAI API网站。

  • 运行交互式Python笔记本(例如 Colab)的环境。

为此教程设置环境。 通过保存具有 .ipynb 扩展名的文件来创建交互式Python笔记本。 此 Notebook 允许您单独运行Python代码片段,并且您将使用它来运行本教程中的代码。

要设立笔记本环境,请执行以下操作:

1
  1. 在笔记本中运行以下命令,在您的环境中安装语义内核。

    pip install --quiet --upgrade semantic-kernel openai motor
  2. 运行以下代码,导入所需包:

    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
2

运行以下代码,将占位符替换为以下值:

  • 您的 OpenAI API 密钥。

  • MongoDB集群的连接字符串。

注意

<connection-string> 替换为您的 Atlas 集群或本地部署的连接字符串。

连接字符串应使用以下格式:

mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net

要学习;了解更多信息,请参阅通过驱动程序连接到集群。

连接字符串应使用以下格式:

mongodb://localhost:<port-number>/?directConnection=true

要学习;了解更多信息,请参阅连接字符串。

在本部分中,您将初始化内核,它是用于管理应用程序的服务和插件的主接口。通过内核,您可以配置AI服务,将MongoDB实例化为向量数据库(也称为内存存储),并将自定义数据加载到MongoDB 集群。

要将自定义数据存储在MongoDB中,请在笔记本中粘贴并运行以下代码片段:

1

运行以下代码以初始化内核。

kernel = sk.Kernel()
2

运行以下代码以配置本教程中使用的 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)
3

运行以下代码,将 Atlas 实例化为内存存储,并将其添加到内核中。 此代码建立与 Atlas 集群的连接并指定以下内容:

  • semantic_kernel_db 作为用于存储文档的 Atlas 数据库。

  • vector_index 作为用于运行语义Atlas Search查询的索引。

它还导入一个名为TextMemoryPlugin插件,其中提供了一群组原生函数来帮助您在内存中存储和检索文本。

mongodb_atlas_memory_store = MongoDBAtlasMemoryStore(
connection_string=MONGODB_URI,
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")
4

此代码将定义并运行一个函数,以使用某些示例文档填充 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={}

提示

运行示例代码后,如果您使用的是Atlas ,则可以导航到Atlas 用户界面中的 semantic_kernel_db.test命名空间来验证向量嵌入。

要在向量存储上启用向量搜索查询,请在笔记本中运行以下代码,在 semantic_kernel_db.test集合上创建MongoDB Vector Search索引。

# Connect to your MongoDB cluster and specify the collection
client = MongoClient(MONGODB_URI)
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)

索引定义将 embedding 字段索引为向量类型。embedding 字段包含使用 OpenAI 的 text-embedding-ada-002 嵌入式模型创建的嵌入。此索引定义指定了 1536 个向量维度,并使用 cosine 来衡量相似性。

MongoDB构建索引后,您可以对数据运行向量搜索查询。

在 notebook 中,运行以下代码,对字符串 What is my job title? 执行基本语义搜索。它打印最相关的文档以及介于 01 之间的相关性分数

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

本部分展示使用 MongoDB Vector Search 和语义内核实施RAG 的示例。现在您已经使用MongoDB Vector Search检索语义相似的文档,运行以下代码示例以提示法学硕士回答基于这些文档的问题。

以下代码定义了一个提示,以指示 LLM 使用检索到的文档作为查询的上下文。在此示例中,您使用示例查询When did I start using MongoDB? 提示法学硕士。 由于您使用自定义数据扩展了法学硕士的知识库,因此聊天模型能够生成更准确、上下文感知的响应。

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 还提供以下开发者资源:

后退

LlamaIndex

在此页面上