mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
Merge branch 'main' into update-modelid
This commit is contained in:
@@ -121,6 +121,14 @@ You can also run all the tests together under the [tests](tests/) folder.
|
||||
|
||||
## Tools and scripts
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
### Asynchronous programming
|
||||
|
||||
It's important to note that most of this library is written with asynchronous in mind. The
|
||||
developer should always assume everything is asynchronous. One can use the function signature
|
||||
with either `async def` or `def` to understand if something is asynchronous or not.
|
||||
|
||||
## Pydantic and Serialization
|
||||
|
||||
[Pydantic Documentation](https://docs.pydantic.dev/1.10/)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": null,
|
||||
"id": "11e59885",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -41,7 +41,7 @@
|
||||
"\n",
|
||||
"kernel = sk.Kernel()\n",
|
||||
"\n",
|
||||
"useAzureOpenAI = False\n",
|
||||
"useAzureOpenAI = True\n",
|
||||
"\n",
|
||||
"# Configure AI backend used by the kernel\n",
|
||||
"if useAzureOpenAI:\n",
|
||||
@@ -68,7 +68,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": null,
|
||||
"id": "93bc6103",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -92,7 +92,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": null,
|
||||
"id": "ca0e7604",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -131,7 +131,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": null,
|
||||
"id": "20d35ed0",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -143,12 +143,12 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": null,
|
||||
"id": "d5697c09",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"basic_plan = await planner.create_plan_async(ask, kernel)"
|
||||
"basic_plan = await planner.create_plan(ask, kernel)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -220,7 +220,7 @@
|
||||
"She likes Shakespeare so write using his style. She speaks French so write it in French.\n",
|
||||
"Convert the text to uppercase.\"\"\"\n",
|
||||
"\n",
|
||||
"new_plan = await planner.create_plan_async(ask, kernel)"
|
||||
"new_plan = await planner.create_plan(ask, kernel)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -256,7 +256,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"results = await planner.execute_plan_async(new_plan, kernel)"
|
||||
"results = await planner.execute_plan(new_plan, kernel)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -322,7 +322,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sequential_plan = await planner.create_plan_async(goal=ask)"
|
||||
"sequential_plan = await planner.create_plan(goal=ask)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -445,7 +445,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"plan = await planner.create_plan_async(goal=ask)"
|
||||
"plan = await planner.create_plan(goal=ask)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -537,9 +537,9 @@
|
||||
" name=\"query\",\n",
|
||||
" description=\"The search query\",\n",
|
||||
" )\n",
|
||||
" async def search_async(self, query: str, context: KernelContext) -> str:\n",
|
||||
" async def search(self, query: str, context: KernelContext) -> str:\n",
|
||||
" query = query or context.variables.get(\"query\")[1]\n",
|
||||
" result = await self._connector.search_async(query, num_results=5, offset=0)\n",
|
||||
" result = await self._connector.search(query, num_results=5, offset=0)\n",
|
||||
" return str(result)"
|
||||
]
|
||||
},
|
||||
@@ -669,7 +669,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
"version": "3.9.13"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,171 +1,171 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "68e1c158",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Using Hugging Face With Plugins\n",
|
||||
"\n",
|
||||
"In this notebook, we demonstrate using Hugging Face models for Plugins using both SemanticMemory and text completions. \n",
|
||||
"\n",
|
||||
"SK supports downloading models from the Hugging Face that can perform the following tasks: text-generation, text2text-generation, summarization, and sentence-similarity. You can search for models by task at https://huggingface.co/models."
|
||||
]
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "68e1c158",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Using Hugging Face With Plugins\n",
|
||||
"\n",
|
||||
"In this notebook, we demonstrate using Hugging Face models for Plugins using both SemanticMemory and text completions. \n",
|
||||
"\n",
|
||||
"SK supports downloading models from the Hugging Face that can perform the following tasks: text-generation, text2text-generation, summarization, and sentence-similarity. You can search for models by task at https://huggingface.co/models."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a77bdf89",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0\n",
|
||||
"\n",
|
||||
"# Note that additional dependencies are required for the Hugging Face connectors:\n",
|
||||
"!python -m pip install torch==2.0.0\n",
|
||||
"!python -m pip install transformers==^4.28.1\n",
|
||||
"!python -m pip install sentence-transformers==^2.2.2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "508ad44f",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import semantic_kernel as sk\n",
|
||||
"import semantic_kernel.connectors.ai.hugging_face as sk_hf"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "d8ddffc1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, we will create a kernel and add both text completion and embedding services. \n",
|
||||
"\n",
|
||||
"For text completion, we are choosing GPT2. This is a text-generation model. (Note: text-generation will repeat the input in the output, text2text-generation will not.)\n",
|
||||
"For embeddings, we are using sentence-transformers/all-MiniLM-L6-v2. Vectors generated for this model are of length 384 (compared to a length of 1536 from OpenAI ADA).\n",
|
||||
"\n",
|
||||
"The following step may take a few minutes when run for the first time as the models will be downloaded to your local machine."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "8f8dcbc6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"kernel = sk.Kernel()\n",
|
||||
"\n",
|
||||
"# Configure LLM service\n",
|
||||
"kernel.add_text_completion_service(\n",
|
||||
" service_id=\"gpt2\",\n",
|
||||
" service=sk_hf.HuggingFaceTextCompletion(ai_model_id=\"gpt2\", task=\"text-generation\"),\n",
|
||||
")\n",
|
||||
"kernel.add_text_embedding_generation_service(\n",
|
||||
" service_id=\"sentence-transformers/all-MiniLM-L6-v2\",\n",
|
||||
" service=sk_hf.HuggingFaceTextEmbedding(ai_model_id=\"sentence-transformers/all-MiniLM-L6-v2\"),\n",
|
||||
")\n",
|
||||
"kernel.register_memory_store(memory_store=sk.memory.VolatileMemoryStore())\n",
|
||||
"kernel.import_plugin(sk.core_plugins.TextMemoryPlugin())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "2a7e7ca4",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Add Memories and Define a plugin to use them\n",
|
||||
"\n",
|
||||
"Most models available on huggingface.co are not as powerful as OpenAI GPT-3+. Your plugins will likely need to be simpler to accommodate this."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d096504c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await kernel.memory.save_information(collection=\"animal-facts\", id=\"info1\", text=\"Sharks are fish.\")\n",
|
||||
"await kernel.memory.save_information(collection=\"animal-facts\", id=\"info2\", text=\"Whales are mammals.\")\n",
|
||||
"await kernel.memory.save_information(collection=\"animal-facts\", id=\"info3\", text=\"Penguins are birds.\")\n",
|
||||
"await kernel.memory.save_information(collection=\"animal-facts\", id=\"info4\", text=\"Dolphins are mammals.\")\n",
|
||||
"await kernel.memory.save_information(collection=\"animal-facts\", id=\"info5\", text=\"Flies are insects.\")\n",
|
||||
"\n",
|
||||
"# Define semantic function using SK prompt template language\n",
|
||||
"my_prompt = \"\"\"I know these animal facts: {{recall $query1}} {{recall $query2}} {{recall $query3}} and \"\"\"\n",
|
||||
"\n",
|
||||
"# Create the semantic function\n",
|
||||
"my_function = kernel.create_semantic_function(prompt_template=my_prompt, max_tokens=45, temperature=0.5, top_p=0.5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "2calf857",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's now see what the completion looks like! Remember, \"gpt2\" is nowhere near as large as ChatGPT, so expect a much simpler answer."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "628c843e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"context = kernel.create_new_context()\n",
|
||||
"context[sk.core_plugins.TextMemoryPlugin.COLLECTION_PARAM] = \"animal-facts\"\n",
|
||||
"context[sk.core_plugins.TextMemoryPlugin.RELEVANCE_PARAM] = \"0.3\"\n",
|
||||
"\n",
|
||||
"context[\"query1\"] = \"animal that swims\"\n",
|
||||
"context[\"query2\"] = \"animal that flies\"\n",
|
||||
"context[\"query3\"] = \"penguins are?\"\n",
|
||||
"output = await kernel.run(my_function, input_vars=context.variables)\n",
|
||||
"\n",
|
||||
"output = str(output).strip()\n",
|
||||
"\n",
|
||||
"query_result1 = await kernel.memory.search(\n",
|
||||
" collection=\"animal-facts\", query=context[\"query1\"], limit=1, min_relevance_score=0.3\n",
|
||||
")\n",
|
||||
"query_result2 = await kernel.memory.search(\n",
|
||||
" collection=\"animal-facts\", query=context[\"query2\"], limit=1, min_relevance_score=0.3\n",
|
||||
")\n",
|
||||
"query_result3 = await kernel.memory.search(\n",
|
||||
" collection=\"animal-facts\", query=context[\"query3\"], limit=1, min_relevance_score=0.3\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(f\"gpt2 completed prompt with: '{output}'\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a77bdf89",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0\n",
|
||||
"\n",
|
||||
"# Note that additional dependencies are required for the Hugging Face connectors:\n",
|
||||
"!python -m pip install torch==2.0.0\n",
|
||||
"!python -m pip install transformers==^4.28.1\n",
|
||||
"!python -m pip install sentence-transformers==^2.2.2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "508ad44f",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import semantic_kernel as sk\n",
|
||||
"import semantic_kernel.connectors.ai.hugging_face as sk_hf"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "d8ddffc1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, we will create a kernel and add both text completion and embedding services. \n",
|
||||
"\n",
|
||||
"For text completion, we are choosing GPT2. This is a text-generation model. (Note: text-generation will repeat the input in the output, text2text-generation will not.)\n",
|
||||
"For embeddings, we are using sentence-transformers/all-MiniLM-L6-v2. Vectors generated for this model are of length 384 (compared to a length of 1536 from OpenAI ADA).\n",
|
||||
"\n",
|
||||
"The following step may take a few minutes when run for the first time as the models will be downloaded to your local machine."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "8f8dcbc6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"kernel = sk.Kernel()\n",
|
||||
"\n",
|
||||
"# Configure LLM service\n",
|
||||
"kernel.add_text_completion_service(\n",
|
||||
" service_id=\"gpt2\",\n",
|
||||
" service=sk_hf.HuggingFaceTextCompletion(ai_model_id=\"gpt2\", task=\"text-generation\"),\n",
|
||||
")\n",
|
||||
"kernel.add_text_embedding_generation_service(\n",
|
||||
" service_id=\"sentence-transformers/all-MiniLM-L6-v2\",\n",
|
||||
" service=sk_hf.HuggingFaceTextEmbedding(ai_model_id=\"sentence-transformers/all-MiniLM-L6-v2\"),\n",
|
||||
")\n",
|
||||
"kernel.register_memory_store(memory_store=sk.memory.VolatileMemoryStore())\n",
|
||||
"kernel.import_plugin(sk.core_plugins.TextMemoryPlugin())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "2a7e7ca4",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Add Memories and Define a plugin to use them\n",
|
||||
"\n",
|
||||
"Most models available on huggingface.co are not as powerful as OpenAI GPT-3+. Your plugins will likely need to be simpler to accommodate this."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d096504c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await kernel.memory.save_information_async(collection=\"animal-facts\", id=\"info1\", text=\"Sharks are fish.\")\n",
|
||||
"await kernel.memory.save_information_async(collection=\"animal-facts\", id=\"info2\", text=\"Whales are mammals.\")\n",
|
||||
"await kernel.memory.save_information_async(collection=\"animal-facts\", id=\"info3\", text=\"Penguins are birds.\")\n",
|
||||
"await kernel.memory.save_information_async(collection=\"animal-facts\", id=\"info4\", text=\"Dolphins are mammals.\")\n",
|
||||
"await kernel.memory.save_information_async(collection=\"animal-facts\", id=\"info5\", text=\"Flies are insects.\")\n",
|
||||
"\n",
|
||||
"# Define semantic function using SK prompt template language\n",
|
||||
"my_prompt = \"\"\"I know these animal facts: {{recall $query1}} {{recall $query2}} {{recall $query3}} and \"\"\"\n",
|
||||
"\n",
|
||||
"# Create the semantic function\n",
|
||||
"my_function = kernel.create_semantic_function(prompt_template=my_prompt, max_tokens=45, temperature=0.5, top_p=0.5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "2calf857",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's now see what the completion looks like! Remember, \"gpt2\" is nowhere near as large as ChatGPT, so expect a much simpler answer."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "628c843e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"context = kernel.create_new_context()\n",
|
||||
"context[sk.core_plugins.TextMemoryPlugin.COLLECTION_PARAM] = \"animal-facts\"\n",
|
||||
"context[sk.core_plugins.TextMemoryPlugin.RELEVANCE_PARAM] = \"0.3\"\n",
|
||||
"\n",
|
||||
"context[\"query1\"] = \"animal that swims\"\n",
|
||||
"context[\"query2\"] = \"animal that flies\"\n",
|
||||
"context[\"query3\"] = \"penguins are?\"\n",
|
||||
"output = await kernel.run_async(my_function, input_vars=context.variables)\n",
|
||||
"\n",
|
||||
"output = str(output).strip()\n",
|
||||
"\n",
|
||||
"query_result1 = await kernel.memory.search_async(\n",
|
||||
" collection=\"animal-facts\", query=context[\"query1\"], limit=1, min_relevance_score=0.3\n",
|
||||
")\n",
|
||||
"query_result2 = await kernel.memory.search_async(\n",
|
||||
" collection=\"animal-facts\", query=context[\"query2\"], limit=1, min_relevance_score=0.3\n",
|
||||
")\n",
|
||||
"query_result3 = await kernel.memory.search_async(\n",
|
||||
" collection=\"animal-facts\", query=context[\"query3\"], limit=1, min_relevance_score=0.3\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(f\"gpt2 completed prompt with: '{output}'\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"id": "68e1c158",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Multiple Results"
|
||||
"# Multiple Results\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -15,7 +15,7 @@
|
||||
"id": "fb81bacd",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"In this notebook we show how you can in a single request, have the LLM model return multiple results per prompt. This is useful for running experiments where you want to evaluate the robustness of your prompt and the parameters of your config against a particular large language model."
|
||||
"In this notebook we show how you can in a single request, have the LLM model return multiple results per prompt. This is useful for running experiments where you want to evaluate the robustness of your prompt and the parameters of your config against a particular large language model.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -25,7 +25,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -74,7 +74,7 @@
|
||||
"id": "d8ddffc1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, we will set up the text and chat services we will be submitting prompts to."
|
||||
"First, we will set up the text and chat services we will be submitting prompts to.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -113,7 +113,7 @@
|
||||
"id": "50561d82",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Next, we'll set up the completion request settings for text completion services."
|
||||
"Next, we'll set up the completion request settings for text completion services.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -141,7 +141,7 @@
|
||||
"id": "857a9c89",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Multiple Open AI Text Completions"
|
||||
"## Multiple Open AI Text Completions\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -153,7 +153,7 @@
|
||||
"source": [
|
||||
"if selectedService == Service.OpenAI:\n",
|
||||
" prompt = \"what is the purpose of a rubber duck?\"\n",
|
||||
" results = await oai_text_service.complete_async(prompt=prompt, settings=oai_text_request_settings)\n",
|
||||
" results = await oai_text_service.complete(prompt=prompt, settings=oai_text_request_settings)\n",
|
||||
" i = 1\n",
|
||||
" for result in results:\n",
|
||||
" print(f\"Result {i}: {result}\")\n",
|
||||
@@ -166,7 +166,7 @@
|
||||
"id": "4288d09f",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Multiple Azure Open AI Text Completions"
|
||||
"## Multiple Azure Open AI Text Completions\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -178,7 +178,7 @@
|
||||
"source": [
|
||||
"if selectedService == Service.AzureOpenAI:\n",
|
||||
" prompt = \"provide me a list of possible meanings for the acronym 'ORLD'\"\n",
|
||||
" results = await azure_text_service.complete_async(prompt=prompt, settings=oai_text_request_settings)\n",
|
||||
" results = await azure_text_service.complete(prompt=prompt, settings=oai_text_request_settings)\n",
|
||||
" i = 1\n",
|
||||
" for result in results:\n",
|
||||
" print(f\"Result {i}: {result}\")\n",
|
||||
@@ -191,7 +191,7 @@
|
||||
"id": "eb548f9c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Multiple Hugging Face Text Completions"
|
||||
"## Multiple Hugging Face Text Completions\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -220,7 +220,7 @@
|
||||
"source": [
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" prompt = \"The purpose of a rubber duck is\"\n",
|
||||
" results = await hf_text_service.complete_async(prompt=prompt, request_settings=hf_request_settings)\n",
|
||||
" results = await hf_text_service.complete(prompt=prompt, request_settings=hf_request_settings)\n",
|
||||
" print(\"\".join(results))"
|
||||
]
|
||||
},
|
||||
@@ -230,7 +230,7 @@
|
||||
"id": "da632e12",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Here, we're setting up the settings for Chat completions."
|
||||
"Here, we're setting up the settings for Chat completions.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -256,7 +256,7 @@
|
||||
"id": "d6bf238e",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Multiple OpenAI Chat Completions"
|
||||
"## Multiple OpenAI Chat Completions\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -272,7 +272,7 @@
|
||||
" \"It's a beautiful day outside, birds are singing, flowers are blooming. On days like these, kids like you...\"\n",
|
||||
" )\n",
|
||||
" message = {\"role\": role, \"content\": content}\n",
|
||||
" results = await oai_chat_service.complete_chat_async(messages=[message], settings=oai_chat_request_settings)\n",
|
||||
" results = await oai_chat_service.complete_chat(messages=[message], settings=oai_chat_request_settings)\n",
|
||||
" i = 0\n",
|
||||
" for result in results:\n",
|
||||
" print(f\"Result {i}: {result[0]}\")\n",
|
||||
@@ -285,7 +285,7 @@
|
||||
"id": "cdb8f740",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Multiple Azure OpenAI Chat Completions"
|
||||
"## Multiple Azure OpenAI Chat Completions\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -316,7 +316,7 @@
|
||||
" role = \"user\"\n",
|
||||
" content = \"Tomorow is going to be a great day, I can feel it. I'm going to wake up early, go for a run, and then...\"\n",
|
||||
" message = {\"role\": role, \"content\": content}\n",
|
||||
" results = await azure_chat_service.complete_chat_async(messages=[message], settings=az_oai_request_settings)\n",
|
||||
" results = await azure_chat_service.complete_chat(messages=[message], settings=az_oai_request_settings)\n",
|
||||
" i = 0\n",
|
||||
" for result in results:\n",
|
||||
" print(f\"Result {i}: {result[0]}\")\n",
|
||||
@@ -331,7 +331,7 @@
|
||||
"source": [
|
||||
"## Streaming Multiple Results\n",
|
||||
"\n",
|
||||
"Here is an example pattern if you want to stream your multiple results. Note that this is not supported for Hugging Face text completions at this time."
|
||||
"Here is an example pattern if you want to stream your multiple results. Note that this is not supported for Hugging Face text completions at this time.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -350,7 +350,7 @@
|
||||
" clear_command = \"cls\" if os.name == \"nt\" else \"clear\"\n",
|
||||
"\n",
|
||||
" prompt = \"what is the purpose of a rubber duck?\"\n",
|
||||
" stream = oai_text_service.complete_stream_async(prompt=prompt, settings=oai_text_request_settings)\n",
|
||||
" stream = oai_text_service.complete_stream(prompt=prompt, settings=oai_text_request_settings)\n",
|
||||
" number_of_responses = oai_text_request_settings.number_of_responses\n",
|
||||
" texts = [\"\"] * number_of_responses\n",
|
||||
"\n",
|
||||
|
||||
@@ -1,330 +1,331 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "68e1c158",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Streaming Results\n",
|
||||
"Here is an example pattern if you want to stream your multiple results. Note that this is not supported for Hugging Face text completions at this time."
|
||||
]
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "68e1c158",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Streaming Results\n",
|
||||
"\n",
|
||||
"Here is an example pattern if you want to stream your multiple results. Note that this is not supported for Hugging Face text completions at this time.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a77bdf89",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.7.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from services import Service\n",
|
||||
"\n",
|
||||
"# Select a service to use for this notebook (available services: OpenAI, AzureOpenAI, HuggingFace)\n",
|
||||
"selectedService = Service.AzureOpenAI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "508ad44f",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import semantic_kernel as sk\n",
|
||||
"\n",
|
||||
"if selectedService == Service.OpenAI or selectedService == Service.AzureOpenAI:\n",
|
||||
" from semantic_kernel.connectors.ai.open_ai.request_settings.open_ai_request_settings import (\n",
|
||||
" OpenAITextRequestSettings,\n",
|
||||
" OpenAIChatRequestSettings,\n",
|
||||
" )\n",
|
||||
" from semantic_kernel.connectors.ai.open_ai.request_settings.azure_chat_request_settings import (\n",
|
||||
" AzureChatRequestSettings,\n",
|
||||
" )\n",
|
||||
" from semantic_kernel.connectors.ai.open_ai import (\n",
|
||||
" AzureTextCompletion,\n",
|
||||
" AzureChatCompletion,\n",
|
||||
" OpenAITextCompletion,\n",
|
||||
" OpenAIChatCompletion,\n",
|
||||
" )\n",
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" from semantic_kernel.connectors.ai.hugging_face import HuggingFaceTextCompletion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "d8ddffc1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, we will set up the text and chat services we will be submitting prompts to.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "8f8dcbc6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"kernel = sk.Kernel()\n",
|
||||
"\n",
|
||||
"# Configure Azure LLM service\n",
|
||||
"if selectedService == Service.AzureOpenAI:\n",
|
||||
" deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
|
||||
" azure_text_service = AzureTextCompletion(\n",
|
||||
" deployment_name=\"text-davinci-003\", endpoint=endpoint, api_key=api_key\n",
|
||||
" ) # set the deployment name to the value of your text model (e.g. gpt-35-turbo-instruct or text-davinci-003)\n",
|
||||
" azure_chat_service = AzureChatCompletion(\n",
|
||||
" deployment_name=\"gpt-35-turbo\", endpoint=endpoint, api_key=api_key\n",
|
||||
" ) # set the deployment name to the value of your chat model\n",
|
||||
"\n",
|
||||
"# Configure OpenAI service\n",
|
||||
"if selectedService == Service.OpenAI:\n",
|
||||
" api_key, org_id = sk.openai_settings_from_dot_env()\n",
|
||||
" oai_text_service = OpenAITextCompletion(ai_model_id=\"gpt-3.5-turbo-instruct\", api_key=api_key, org_id=org_id)\n",
|
||||
" oai_chat_service = OpenAIChatCompletion(ai_model_id=\"gpt-3.5-turbo\", api_key=api_key, org_id=org_id)\n",
|
||||
"\n",
|
||||
"# Configure Hugging Face service\n",
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" hf_text_service = HuggingFaceTextCompletion(ai_model_id=\"distilgpt2\", task=\"text-generation\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "50561d82",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Next, we'll set up the completion request settings for text completion services.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "628c843e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"oai_request_settings = OpenAITextRequestSettings(\n",
|
||||
" max_tokens=150,\n",
|
||||
" temperature=0.7,\n",
|
||||
" top_p=1,\n",
|
||||
" frequency_penalty=0.5,\n",
|
||||
" presence_penalty=0.5,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "857a9c89",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming Open AI Text Completion\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e2979db8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.OpenAI:\n",
|
||||
" prompt = \"what is the purpose of a rubber duck?\"\n",
|
||||
" stream = oai_text_service.complete_stream(prompt=prompt, settings=oai_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "4288d09f",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming Azure Open AI Text Completion\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "5319f14d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.AzureOpenAI:\n",
|
||||
" prompt = \"provide me a list of possible meanings for the acronym 'ORLD'\"\n",
|
||||
" stream = azure_text_service.complete_stream(prompt=prompt, settings=oai_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "eb548f9c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming Hugging Face Text Completion\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "be7b1c2e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" from semantic_kernel.connectors.ai.hugging_face.hf_request_settings import (\n",
|
||||
" HuggingFaceRequestSettings,\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" hf_request_settings = HuggingFaceRequestSettings(\n",
|
||||
" extension_data={\n",
|
||||
" \"max_new_tokens\": 80,\n",
|
||||
" \"top_p\": 1,\n",
|
||||
" \"eos_token_id\": 11,\n",
|
||||
" \"pad_token_id\": 0,\n",
|
||||
" }\n",
|
||||
" )"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "9525e4f3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" prompt = \"The purpose of a rubber duck is\"\n",
|
||||
" stream = hf_text_service.complete_stream(prompt=prompt, request_settings=hf_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "da632e12",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Here, we're setting up the settings for Chat completions.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e5f11e46",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"oai_chat_request_settings = OpenAIChatRequestSettings(\n",
|
||||
" max_tokens=150,\n",
|
||||
" temperature=0.7,\n",
|
||||
" top_p=1,\n",
|
||||
" frequency_penalty=0.5,\n",
|
||||
" presence_penalty=0.5,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "d6bf238e",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming OpenAI Chat Completion\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "dabc6a4c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.OpenAI:\n",
|
||||
" role = \"system\"\n",
|
||||
" content = \"You are an AI assistant that helps people find information.\"\n",
|
||||
" message = {\"role\": role, \"content\": content}\n",
|
||||
" stream = oai_chat_service.complete_chat_stream(messages=[message], settings=oai_chat_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "cdb8f740",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming Azure OpenAI Chat Completion\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "da1e9f59",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"az_oai_chat_request_settings = AzureChatRequestSettings(\n",
|
||||
" max_tokens=150,\n",
|
||||
" temperature=0.7,\n",
|
||||
" top_p=1,\n",
|
||||
" frequency_penalty=0.5,\n",
|
||||
" presence_penalty=0.5,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b74a64a9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.AzureOpenAI:\n",
|
||||
" role = \"system\"\n",
|
||||
" content = \"You are an AI assistant that helps people find information.\"\n",
|
||||
" message = {\"role\": role, \"content\": content}\n",
|
||||
" stream = azure_chat_service.complete_chat_stream(messages=[message], settings=az_oai_chat_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a77bdf89",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!python -m pip install semantic-kernel==0.4.6.dev0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from services import Service\n",
|
||||
"\n",
|
||||
"# Select a service to use for this notebook (available services: OpenAI, AzureOpenAI, HuggingFace)\n",
|
||||
"selectedService = Service.AzureOpenAI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "508ad44f",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import semantic_kernel as sk\n",
|
||||
"\n",
|
||||
"if selectedService == Service.OpenAI or selectedService == Service.AzureOpenAI:\n",
|
||||
" from semantic_kernel.connectors.ai.open_ai.request_settings.open_ai_request_settings import (\n",
|
||||
" OpenAITextRequestSettings,\n",
|
||||
" OpenAIChatRequestSettings,\n",
|
||||
" )\n",
|
||||
" from semantic_kernel.connectors.ai.open_ai.request_settings.azure_chat_request_settings import (\n",
|
||||
" AzureChatRequestSettings,\n",
|
||||
" )\n",
|
||||
" from semantic_kernel.connectors.ai.open_ai import (\n",
|
||||
" AzureTextCompletion,\n",
|
||||
" AzureChatCompletion,\n",
|
||||
" OpenAITextCompletion,\n",
|
||||
" OpenAIChatCompletion,\n",
|
||||
" )\n",
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" from semantic_kernel.connectors.ai.hugging_face import HuggingFaceTextCompletion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "d8ddffc1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, we will set up the text and chat services we will be submitting prompts to."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "8f8dcbc6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"kernel = sk.Kernel()\n",
|
||||
"\n",
|
||||
"# Configure Azure LLM service\n",
|
||||
"if selectedService == Service.AzureOpenAI:\n",
|
||||
" deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
|
||||
" azure_text_service = AzureTextCompletion(\n",
|
||||
" deployment_name=\"text-davinci-003\", endpoint=endpoint, api_key=api_key\n",
|
||||
" ) # set the deployment name to the value of your text model (e.g. gpt-35-turbo-instruct or text-davinci-003)\n",
|
||||
" azure_chat_service = AzureChatCompletion(\n",
|
||||
" deployment_name=\"gpt-35-turbo\", endpoint=endpoint, api_key=api_key\n",
|
||||
" ) # set the deployment name to the value of your chat model\n",
|
||||
"\n",
|
||||
"# Configure OpenAI service\n",
|
||||
"if selectedService == Service.OpenAI:\n",
|
||||
" api_key, org_id = sk.openai_settings_from_dot_env()\n",
|
||||
" oai_text_service = OpenAITextCompletion(ai_model_id=\"gpt-3.5-turbo-instruct\", api_key=api_key, org_id=org_id)\n",
|
||||
" oai_chat_service = OpenAIChatCompletion(ai_model_id=\"gpt-3.5-turbo\", api_key=api_key, org_id=org_id)\n",
|
||||
"\n",
|
||||
"# Configure Hugging Face service\n",
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" hf_text_service = HuggingFaceTextCompletion(ai_model_id=\"distilgpt2\", task=\"text-generation\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "50561d82",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Next, we'll set up the completion request settings for text completion services."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "628c843e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"oai_request_settings = OpenAITextRequestSettings(\n",
|
||||
" max_tokens=150,\n",
|
||||
" temperature=0.7,\n",
|
||||
" top_p=1,\n",
|
||||
" frequency_penalty=0.5,\n",
|
||||
" presence_penalty=0.5,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "857a9c89",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming Open AI Text Completion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e2979db8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.OpenAI:\n",
|
||||
" prompt = \"what is the purpose of a rubber duck?\"\n",
|
||||
" stream = oai_text_service.complete_stream_async(prompt=prompt, settings=oai_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "4288d09f",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming Azure Open AI Text Completion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "5319f14d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.AzureOpenAI:\n",
|
||||
" prompt = \"provide me a list of possible meanings for the acronym 'ORLD'\"\n",
|
||||
" stream = azure_text_service.complete_stream_async(prompt=prompt, settings=oai_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "eb548f9c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming Hugging Face Text Completion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "be7b1c2e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" from semantic_kernel.connectors.ai.hugging_face.hf_request_settings import (\n",
|
||||
" HuggingFaceRequestSettings,\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" hf_request_settings = HuggingFaceRequestSettings(\n",
|
||||
" extension_data={\n",
|
||||
" \"max_new_tokens\": 80,\n",
|
||||
" \"top_p\": 1,\n",
|
||||
" \"eos_token_id\": 11,\n",
|
||||
" \"pad_token_id\": 0,\n",
|
||||
" }\n",
|
||||
" )"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "9525e4f3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.HuggingFace:\n",
|
||||
" prompt = \"The purpose of a rubber duck is\"\n",
|
||||
" stream = hf_text_service.complete_stream_async(prompt=prompt, request_settings=hf_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "da632e12",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Here, we're setting up the settings for Chat completions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e5f11e46",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"oai_chat_request_settings = OpenAIChatRequestSettings(\n",
|
||||
" max_tokens=150,\n",
|
||||
" temperature=0.7,\n",
|
||||
" top_p=1,\n",
|
||||
" frequency_penalty=0.5,\n",
|
||||
" presence_penalty=0.5,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "d6bf238e",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming OpenAI Chat Completion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "dabc6a4c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.OpenAI:\n",
|
||||
" role = \"system\"\n",
|
||||
" content = \"You are an AI assistant that helps people find information.\"\n",
|
||||
" message = {\"role\": role, \"content\": content}\n",
|
||||
" stream = oai_chat_service.complete_chat_stream_async(messages=[message], settings=oai_chat_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"id": "cdb8f740",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Streaming Azure OpenAI Chat Completion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "da1e9f59",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"az_oai_chat_request_settings = AzureChatRequestSettings(\n",
|
||||
" max_tokens=150,\n",
|
||||
" temperature=0.7,\n",
|
||||
" top_p=1,\n",
|
||||
" frequency_penalty=0.5,\n",
|
||||
" presence_penalty=0.5,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b74a64a9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if selectedService == Service.AzureOpenAI:\n",
|
||||
" role = \"system\"\n",
|
||||
" content = \"You are an AI assistant that helps people find information.\"\n",
|
||||
" message = {\"role\": role, \"content\": content}\n",
|
||||
" stream = azure_chat_service.complete_chat_stream_async(messages=[message], settings=az_oai_chat_request_settings)\n",
|
||||
" async for text in stream:\n",
|
||||
" print(text, end=\"\") # end = \"\" to avoid newlines"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
+509
-509
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "semantic-kernel"
|
||||
version = "0.4.6.dev"
|
||||
version = "0.4.7.dev"
|
||||
description = "Semantic Kernel Python SDK"
|
||||
authors = ["Microsoft <[email protected]>"]
|
||||
readme = "pip/README.md"
|
||||
|
||||
@@ -30,7 +30,7 @@ async def main():
|
||||
ask = "What is the sum of 110 and 990?"
|
||||
|
||||
# ask the action planner to identify a suitable function from the list of functions available.
|
||||
plan = await planner.create_plan_async(goal=ask)
|
||||
plan = await planner.create_plan(goal=ask)
|
||||
|
||||
# ask the action planner to execute the identified function.
|
||||
result = await plan.invoke_async()
|
||||
|
||||
@@ -77,13 +77,13 @@ async def chat() -> bool:
|
||||
|
||||
stream = True
|
||||
if stream:
|
||||
answer = kernel.run_stream_async(chat_function, input_vars=context_vars)
|
||||
answer = kernel.run_stream(chat_function, input_vars=context_vars)
|
||||
print("Mosscap:> ", end="")
|
||||
async for message in answer:
|
||||
print(message, end="")
|
||||
print("\n")
|
||||
return True
|
||||
answer = await kernel.run_async(chat_function, input_vars=context_vars)
|
||||
answer = await kernel.run(chat_function, input_vars=context_vars)
|
||||
print(f"Mosscap:> {answer}")
|
||||
return True
|
||||
|
||||
|
||||
@@ -78,10 +78,10 @@ async def chat() -> bool:
|
||||
return False
|
||||
|
||||
# Non streaming
|
||||
# answer = await kernel.run_async(chat_function, input_vars=context_vars)
|
||||
# answer = await kernel.run(chat_function, input_vars=context_vars)
|
||||
# print(f"Assistant:> {answer}")
|
||||
|
||||
answer = kernel.run_stream_async(chat_function, input_vars=context_vars, input_context=context)
|
||||
answer = kernel.run_stream(chat_function, input_vars=context_vars, input_context=context)
|
||||
print("Assistant:> ", end="")
|
||||
async for message in answer:
|
||||
print(message, end="")
|
||||
|
||||
@@ -76,10 +76,10 @@ async def chat() -> bool:
|
||||
return False
|
||||
|
||||
# Non streaming
|
||||
# answer = await kernel.run_async(chat_function, input_vars=context_vars)
|
||||
# answer = await kernel.run(chat_function, input_vars=context_vars)
|
||||
# print(f"Assistant:> {answer}")
|
||||
|
||||
answer = kernel.run_stream_async(chat_function, input_vars=context_vars)
|
||||
answer = kernel.run_stream(chat_function, input_vars=context_vars)
|
||||
print("Assistant:> ", end="")
|
||||
async for message in answer:
|
||||
print(message, end="")
|
||||
|
||||
@@ -84,10 +84,10 @@ async def chat() -> bool:
|
||||
return False
|
||||
|
||||
# Non streaming
|
||||
# answer = await kernel.run_async(chat_function, input_vars=context_vars)
|
||||
# answer = await kernel.run(chat_function, input_vars=context_vars)
|
||||
# print(f"Assistant:> {answer}")
|
||||
|
||||
answer = kernel.run_stream_async(chat_function, input_vars=context_vars, input_context=context)
|
||||
answer = kernel.run_stream(chat_function, input_vars=context_vars, input_context=context)
|
||||
print("Assistant:> ", end="")
|
||||
async for message in answer:
|
||||
print(message, end="")
|
||||
|
||||
@@ -18,17 +18,15 @@ COLLECTION_NAME = "acs-index-sample"
|
||||
|
||||
async def populate_memory(kernel: sk.Kernel) -> None:
|
||||
# Add some documents to the ACS semantic memory
|
||||
await kernel.memory.save_information_async(COLLECTION_NAME, id="info1", text="My name is Andrea")
|
||||
await kernel.memory.save_information_async(COLLECTION_NAME, id="info2", text="I currently work as a tour guide")
|
||||
await kernel.memory.save_information_async(
|
||||
COLLECTION_NAME, id="info3", text="I've been living in Seattle since 2005"
|
||||
)
|
||||
await kernel.memory.save_information_async(
|
||||
await kernel.memory.save_information(COLLECTION_NAME, id="info1", text="My name is Andrea")
|
||||
await kernel.memory.save_information(COLLECTION_NAME, id="info2", text="I currently work as a tour guide")
|
||||
await kernel.memory.save_information(COLLECTION_NAME, id="info3", text="I've been living in Seattle since 2005")
|
||||
await kernel.memory.save_information(
|
||||
COLLECTION_NAME,
|
||||
id="info4",
|
||||
text="I visited France and Italy five times since 2015",
|
||||
)
|
||||
await kernel.memory.save_information_async(COLLECTION_NAME, id="info5", text="My family is from New York")
|
||||
await kernel.memory.save_information(COLLECTION_NAME, id="info5", text="My family is from New York")
|
||||
|
||||
|
||||
async def search_acs_memory_questions(kernel: sk.Kernel) -> None:
|
||||
@@ -42,7 +40,7 @@ async def search_acs_memory_questions(kernel: sk.Kernel) -> None:
|
||||
|
||||
for question in questions:
|
||||
print(f"Question: {question}")
|
||||
result = await kernel.memory.search_async(COLLECTION_NAME, question)
|
||||
result = await kernel.memory.search(COLLECTION_NAME, question)
|
||||
print(f"Answer: {result[0].text}\n")
|
||||
|
||||
|
||||
@@ -88,7 +86,7 @@ async def main() -> None:
|
||||
print("Asking questions... (manually)")
|
||||
await search_acs_memory_questions(kernel)
|
||||
|
||||
await connector.close_async()
|
||||
await connector.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -26,8 +26,8 @@ async def main():
|
||||
web_plugin = kernel.import_plugin(WebSearchEnginePlugin(connector), "WebSearch")
|
||||
|
||||
prompt = "Who is Leonardo DiCaprio's current girlfriend?"
|
||||
search_async = web_plugin["searchAsync"]
|
||||
result = await search_async.invoke_async(prompt)
|
||||
search = web_plugin["searchAsync"]
|
||||
result = await search.invoke_async(prompt)
|
||||
print(result)
|
||||
|
||||
"""
|
||||
|
||||
@@ -43,7 +43,7 @@ async def chat(context_vars: sk.ContextVariables) -> bool:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
|
||||
answer = await kernel.run_async(chat_function, input_vars=context_vars)
|
||||
answer = await kernel.run(chat_function, input_vars=context_vars)
|
||||
context_vars["chat_history"] += f"\nUser:> {user_input}\nChatBot:> {answer}\n"
|
||||
|
||||
print(f"ChatBot:> {answer}")
|
||||
|
||||
@@ -48,7 +48,7 @@ async def chat() -> bool:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
|
||||
answer = await kernel.run_async(chat_function, input_vars=context_vars)
|
||||
answer = await kernel.run(chat_function, input_vars=context_vars)
|
||||
print(f"Mosscap:> {answer}")
|
||||
return True
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ async def chat_request_example(api_key):
|
||||
chat_messages = list()
|
||||
user_mssg = "I'm planning a vacation. Which are some must-visit places in Europe?"
|
||||
chat_messages.append(("user", user_mssg))
|
||||
answer = await palm_chat_completion.complete_chat_async(chat_messages, settings)
|
||||
answer = await palm_chat_completion.complete_chat(chat_messages, settings)
|
||||
chat_messages.append(("assistant", str(answer)))
|
||||
user_mssg = "Where should I go in France?"
|
||||
chat_messages.append(("user", user_mssg))
|
||||
answer = await palm_chat_completion.complete_chat_async(chat_messages, settings)
|
||||
answer = await palm_chat_completion.complete_chat(chat_messages, settings)
|
||||
chat_messages.append(("assistant", str(answer)))
|
||||
|
||||
context_vars = sk.ContextVariables()
|
||||
|
||||
@@ -18,11 +18,11 @@ kernel.import_plugin(sk.core_plugins.TextMemoryPlugin())
|
||||
|
||||
async def populate_memory(kernel: sk.Kernel) -> None:
|
||||
# Add some documents to the semantic memory
|
||||
await kernel.memory.save_information_async("aboutMe", id="info1", text="My name is Andrea")
|
||||
await kernel.memory.save_information_async("aboutMe", id="info2", text="I currently work as a tour guide")
|
||||
await kernel.memory.save_information_async("aboutMe", id="info3", text="My favorite hobby is hiking")
|
||||
await kernel.memory.save_information_async("aboutMe", id="info4", text="I visitied Iceland last year.")
|
||||
await kernel.memory.save_information_async("aboutMe", id="info5", text="My family is from New York")
|
||||
await kernel.memory.save_information("aboutMe", id="info1", text="My name is Andrea")
|
||||
await kernel.memory.save_information("aboutMe", id="info2", text="I currently work as a tour guide")
|
||||
await kernel.memory.save_information("aboutMe", id="info3", text="My favorite hobby is hiking")
|
||||
await kernel.memory.save_information("aboutMe", id="info4", text="I visitied Iceland last year.")
|
||||
await kernel.memory.save_information("aboutMe", id="info5", text="My family is from New York")
|
||||
|
||||
|
||||
async def search_memory_examples(kernel: sk.Kernel) -> None:
|
||||
@@ -36,7 +36,7 @@ async def search_memory_examples(kernel: sk.Kernel) -> None:
|
||||
|
||||
for question in questions:
|
||||
print(f"Question: {question}")
|
||||
result = await kernel.memory.search_async("aboutMe", question)
|
||||
result = await kernel.memory.search("aboutMe", question)
|
||||
print(f"Answer: {result}\n")
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ async def chat(kernel: sk.Kernel, chat_func: sk.KernelFunctionBase, context: sk.
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
|
||||
answer = await kernel.run_async(chat_func, input_vars=context.variables)
|
||||
answer = await kernel.run(chat_func, input_vars=context.variables)
|
||||
context["chat_history"] += f"\nUser:> {user_input}\nChatBot:> {answer}\n"
|
||||
|
||||
print(f"ChatBot:> {answer}")
|
||||
|
||||
@@ -56,7 +56,7 @@ async def chat() -> bool:
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
|
||||
answer = await kernel.run_async(chat_function, input_vars=context_vars)
|
||||
answer = await kernel.run(chat_function, input_vars=context_vars)
|
||||
print(f"Blackbeard:> {answer}")
|
||||
return True
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ from semantic_kernel.connectors.ai.google_palm.gp_request_settings import (
|
||||
)
|
||||
|
||||
|
||||
async def text_completion_example_complete_async(kernel, api_key, user_mssg, settings):
|
||||
async def text_completion_example_complete(kernel, api_key, user_mssg, settings):
|
||||
"""
|
||||
Complete a text prompt using the Google PaLM model and print the results.
|
||||
"""
|
||||
palm_text_completion = sk_gp.GooglePalmTextCompletion("models/text-bison-001", api_key)
|
||||
kernel.add_text_completion_service("models/text-bison-001", palm_text_completion)
|
||||
answer = await palm_text_completion.complete_async(user_mssg, settings)
|
||||
answer = await palm_text_completion.complete(user_mssg, settings)
|
||||
return answer
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ async def main() -> None:
|
||||
"boxes have 98 coins in total. How many coins are there in each box? "
|
||||
"Think about it step by step, and show your work."
|
||||
)
|
||||
response = await text_completion_example_complete_async(kernel, apikey, user_mssg1, settings)
|
||||
response = await text_completion_example_complete(kernel, apikey, user_mssg1, settings)
|
||||
print(f"User:> {user_mssg1}\n\nChatBot:> {response}\n")
|
||||
# Use temperature to influence the variance of the responses
|
||||
settings.number_of_responses = 3
|
||||
settings.temperature = 1
|
||||
user_mssg2 = "I need a concise answer. A common method for traversing a binary tree is"
|
||||
response = await text_completion_example_complete_async(kernel, apikey, user_mssg2, settings)
|
||||
response = await text_completion_example_complete(kernel, apikey, user_mssg2, settings)
|
||||
print(f"User:> {user_mssg2}\n\nChatBot:> {response}")
|
||||
return
|
||||
|
||||
|
||||
@@ -38,10 +38,10 @@ async def main():
|
||||
|
||||
# The search query
|
||||
prompt = "Who is Leonardo DiCaprio's current girlfriend?"
|
||||
search_async = web_plugin["searchAsync"]
|
||||
search = web_plugin["searchAsync"]
|
||||
|
||||
# By default, only one search result is provided
|
||||
result = await search_async.invoke_async(prompt)
|
||||
result = await search.invoke_async(prompt)
|
||||
print(result)
|
||||
|
||||
"""
|
||||
|
||||
@@ -9,13 +9,11 @@ import semantic_kernel.connectors.ai.open_ai as sk_oai
|
||||
|
||||
async def populate_memory(kernel: sk.Kernel) -> None:
|
||||
# Add some documents to the semantic memory
|
||||
await kernel.memory.save_information_async("aboutMe", id="info1", text="My name is Andrea")
|
||||
await kernel.memory.save_information_async("aboutMe", id="info2", text="I currently work as a tour guide")
|
||||
await kernel.memory.save_information_async("aboutMe", id="info3", text="I've been living in Seattle since 2005")
|
||||
await kernel.memory.save_information_async(
|
||||
"aboutMe", id="info4", text="I visited France and Italy five times since 2015"
|
||||
)
|
||||
await kernel.memory.save_information_async("aboutMe", id="info5", text="My family is from New York")
|
||||
await kernel.memory.save_information("aboutMe", id="info1", text="My name is Andrea")
|
||||
await kernel.memory.save_information("aboutMe", id="info2", text="I currently work as a tour guide")
|
||||
await kernel.memory.save_information("aboutMe", id="info3", text="I've been living in Seattle since 2005")
|
||||
await kernel.memory.save_information("aboutMe", id="info4", text="I visited France and Italy five times since 2015")
|
||||
await kernel.memory.save_information("aboutMe", id="info5", text="My family is from New York")
|
||||
|
||||
|
||||
async def search_memory_examples(kernel: sk.Kernel) -> None:
|
||||
@@ -29,7 +27,7 @@ async def search_memory_examples(kernel: sk.Kernel) -> None:
|
||||
|
||||
for question in questions:
|
||||
print(f"Question: {question}")
|
||||
result = await kernel.memory.search_async("aboutMe", question)
|
||||
result = await kernel.memory.search("aboutMe", question)
|
||||
print(f"Answer: {result[0].text}\n")
|
||||
|
||||
|
||||
@@ -85,7 +83,7 @@ async def chat(kernel: sk.Kernel, chat_func: sk.KernelFunctionBase, context: sk.
|
||||
print("\n\nExiting chat...")
|
||||
return False
|
||||
|
||||
answer = await kernel.run_async(chat_func, input_vars=context.variables)
|
||||
answer = await kernel.run(chat_func, input_vars=context.variables)
|
||||
context["chat_history"] += f"\nUser:> {user_input}\nChatBot:> {answer}\n"
|
||||
|
||||
print(f"ChatBot:> {answer}")
|
||||
|
||||
@@ -82,13 +82,13 @@ async def chat_request_example(kernel, api_key, org_id):
|
||||
messages = [{"role": "user", "content": user_mssg}]
|
||||
|
||||
chat_messages.append(("user", user_mssg))
|
||||
answer = await openai_chat_completion.complete_chat_async(messages=messages, settings=settings)
|
||||
answer = await openai_chat_completion.complete_chat(messages=messages, settings=settings)
|
||||
chat_messages.append(("assistant", str(answer[0])))
|
||||
|
||||
user_mssg = "What are his best all-time stats?"
|
||||
messages = [{"role": "user", "content": user_mssg}]
|
||||
chat_messages.append(("user", user_mssg))
|
||||
answer = await openai_chat_completion.complete_chat_async(messages=messages, settings=settings)
|
||||
answer = await openai_chat_completion.complete_chat(messages=messages, settings=settings)
|
||||
chat_messages.append(("assistant", str(answer[0])))
|
||||
|
||||
context_vars = sk.ContextVariables()
|
||||
@@ -154,7 +154,7 @@ async def text_complete_request_example(kernel, api_key, org_id):
|
||||
settings = _config_ban_tokens(settings, keys)
|
||||
|
||||
user_mssg = "The best pie flavor to have in autumn is"
|
||||
answer = await openai_text_completion.complete_async(user_mssg, settings)
|
||||
answer = await openai_text_completion.complete(user_mssg, settings)
|
||||
|
||||
context_vars = sk.ContextVariables()
|
||||
context_vars["chat_history"] = f"User:> {user_mssg}\nChatBot:> {answer}\n"
|
||||
|
||||
@@ -30,5 +30,5 @@ else:
|
||||
plugins_directory = os.path.join(__file__, "../../../../samples/plugins")
|
||||
plugin = kernel.import_semantic_plugin_from_directory(plugins_directory, "FunPlugin")
|
||||
|
||||
result = asyncio.run(kernel.run_async(plugin["Joke"], input_str="time travel to dinosaur age"))
|
||||
result = asyncio.run(kernel.run(plugin["Joke"], input_str="time travel to dinosaur age"))
|
||||
print(result)
|
||||
|
||||
@@ -20,17 +20,15 @@ COLLECTION_NAME = "generic"
|
||||
|
||||
async def populate_memory(kernel: sk.Kernel) -> None:
|
||||
# Add some documents to the ACS semantic memory
|
||||
await kernel.memory.save_information_async(COLLECTION_NAME, id="info1", text="My name is Andrea")
|
||||
await kernel.memory.save_information_async(COLLECTION_NAME, id="info2", text="I currently work as a tour guide")
|
||||
await kernel.memory.save_information_async(
|
||||
COLLECTION_NAME, id="info3", text="I've been living in Seattle since 2005"
|
||||
)
|
||||
await kernel.memory.save_information_async(
|
||||
await kernel.memory.save_information(COLLECTION_NAME, id="info1", text="My name is Andrea")
|
||||
await kernel.memory.save_information(COLLECTION_NAME, id="info2", text="I currently work as a tour guide")
|
||||
await kernel.memory.save_information(COLLECTION_NAME, id="info3", text="I've been living in Seattle since 2005")
|
||||
await kernel.memory.save_information(
|
||||
COLLECTION_NAME,
|
||||
id="info4",
|
||||
text="I visited France and Italy five times since 2015",
|
||||
)
|
||||
await kernel.memory.save_information_async(COLLECTION_NAME, id="info5", text="My family is from New York")
|
||||
await kernel.memory.save_information(COLLECTION_NAME, id="info5", text="My family is from New York")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
@@ -99,7 +97,7 @@ Remember, just answer Grounded or Ungrounded or Unclear: """.strip()
|
||||
chat_func = kernel.create_semantic_function(sk_prompt_rag, max_tokens=1000, temperature=0.5)
|
||||
self_critique_func = kernel.create_semantic_function(sk_prompt_rag_sc, max_tokens=4, temperature=0.0)
|
||||
|
||||
answer = await kernel.run_async(
|
||||
answer = await kernel.run(
|
||||
chat_func,
|
||||
input_vars=ContextVariables(
|
||||
variables={
|
||||
@@ -110,24 +108,24 @@ Remember, just answer Grounded or Ungrounded or Unclear: """.strip()
|
||||
),
|
||||
)
|
||||
print(f"Answer: {str(answer).strip()}")
|
||||
check = await kernel.run_async(self_critique_func, input_context=answer)
|
||||
check = await kernel.run(self_critique_func, input_context=answer)
|
||||
print(f"The answer was {str(check).strip()}")
|
||||
|
||||
print("-" * 50)
|
||||
print(" Let's pretend the answer was wrong...")
|
||||
answer.variables.variables["input"] = "Yes, you live in New York City."
|
||||
print(f"Answer: {str(answer).strip()}")
|
||||
check = await kernel.run_async(self_critique_func, input_context=answer)
|
||||
check = await kernel.run(self_critique_func, input_context=answer)
|
||||
print(f"The answer was {str(check).strip()}")
|
||||
|
||||
print("-" * 50)
|
||||
print(" Let's pretend the answer is not related...")
|
||||
answer.variables.variables["input"] = "Yes, the earth is not flat."
|
||||
print(f"Answer: {str(answer).strip()}")
|
||||
check = await kernel.run_async(self_critique_func, input_context=answer)
|
||||
check = await kernel.run(self_critique_func, input_context=answer)
|
||||
print(f"The answer was {str(check).strip()}")
|
||||
|
||||
await connector.close_async()
|
||||
await connector.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -28,7 +28,7 @@ async def main():
|
||||
ask = "What day of the week is today, all uppercase?"
|
||||
|
||||
# ask the sequential planner to identify a suitable function from the list of functions available.
|
||||
plan = await planner.create_plan_async(goal=ask)
|
||||
plan = await planner.create_plan(goal=ask)
|
||||
|
||||
# ask the sequential planner to execute the identified function.
|
||||
result = await plan.invoke_async()
|
||||
|
||||
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
|
||||
|
||||
class ChatCompletionClientBase(ABC):
|
||||
@abstractmethod
|
||||
async def complete_chat_async(
|
||||
async def complete_chat(
|
||||
self,
|
||||
messages: List["ChatMessage"],
|
||||
settings: "AIRequestSettings",
|
||||
@@ -31,7 +31,7 @@ class ChatCompletionClientBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def complete_chat_stream_async(
|
||||
async def complete_chat_stream(
|
||||
self,
|
||||
messages: List["ChatMessage"],
|
||||
settings: "AIRequestSettings",
|
||||
|
||||
@@ -9,5 +9,5 @@ if TYPE_CHECKING:
|
||||
|
||||
class EmbeddingGeneratorBase(ABC):
|
||||
@abstractmethod
|
||||
async def generate_embeddings_async(self, texts: List[str]) -> "ndarray":
|
||||
async def generate_embeddings(self, texts: List[str]) -> "ndarray":
|
||||
pass
|
||||
|
||||
@@ -60,7 +60,7 @@ class GooglePalmChatCompletion(ChatCompletionClientBase, TextCompletionClientBas
|
||||
logger.warning("The `log` parameter is deprecated. Please use the `logging` module instead.")
|
||||
self._message_history = message_history
|
||||
|
||||
async def complete_chat_async(
|
||||
async def complete_chat(
|
||||
self,
|
||||
messages: List[Tuple[str, str]],
|
||||
settings: GooglePalmRequestSettings,
|
||||
@@ -79,14 +79,14 @@ class GooglePalmChatCompletion(ChatCompletionClientBase, TextCompletionClientBas
|
||||
return "I don't know." # PaLM returns None if it doesn't know
|
||||
return response.last
|
||||
|
||||
async def complete_chat_stream_async(
|
||||
async def complete_chat_stream(
|
||||
self,
|
||||
messages: List[Tuple[str, str]],
|
||||
settings: GooglePalmRequestSettings,
|
||||
):
|
||||
raise NotImplementedError("Google Palm API does not currently support streaming")
|
||||
|
||||
async def complete_async(
|
||||
async def complete(
|
||||
self,
|
||||
prompt: str,
|
||||
settings: GooglePalmRequestSettings,
|
||||
@@ -108,7 +108,7 @@ class GooglePalmChatCompletion(ChatCompletionClientBase, TextCompletionClientBas
|
||||
return "I don't know." # PaLM returns None if it doesn't know
|
||||
return response.last
|
||||
|
||||
async def complete_stream_async(
|
||||
async def complete_stream(
|
||||
self,
|
||||
prompt: str,
|
||||
settings: GooglePalmRequestSettings,
|
||||
|
||||
@@ -42,7 +42,7 @@ class GooglePalmTextCompletion(TextCompletionClientBase, AIServiceClientBase):
|
||||
if log:
|
||||
logger.warning("The `log` parameter is deprecated. Please use the `logging` module instead.")
|
||||
|
||||
async def complete_async(
|
||||
async def complete(
|
||||
self,
|
||||
prompt: str,
|
||||
request_settings: GooglePalmTextRequestSettings,
|
||||
@@ -70,7 +70,7 @@ class GooglePalmTextCompletion(TextCompletionClientBase, AIServiceClientBase):
|
||||
return [candidate["output"] for candidate in response.candidates]
|
||||
return response.result
|
||||
|
||||
async def complete_stream_async(
|
||||
async def complete_stream(
|
||||
self,
|
||||
prompt: str,
|
||||
request_settings: GooglePalmTextRequestSettings,
|
||||
|
||||
@@ -34,7 +34,7 @@ class GooglePalmTextEmbedding(EmbeddingGeneratorBase, AIServiceClientBase):
|
||||
"""
|
||||
super().__init__(ai_model_id=ai_model_id, api_key=api_key)
|
||||
|
||||
async def generate_embeddings_async(self, texts: List[str]) -> ndarray:
|
||||
async def generate_embeddings(self, texts: List[str]) -> ndarray:
|
||||
"""
|
||||
Generates embeddings for a list of texts.
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class HuggingFaceTextCompletion(TextCompletionClientBase, AIServiceClientBase):
|
||||
if log:
|
||||
logger.warning("The `log` parameter is deprecated. Please use the `logging` module instead.")
|
||||
|
||||
async def complete_async(
|
||||
async def complete(
|
||||
self,
|
||||
prompt: str,
|
||||
request_settings: HuggingFaceRequestSettings,
|
||||
@@ -90,7 +90,7 @@ class HuggingFaceTextCompletion(TextCompletionClientBase, AIServiceClientBase):
|
||||
except Exception as e:
|
||||
raise AIException("Hugging Face completion failed", e)
|
||||
|
||||
async def complete_stream_async(
|
||||
async def complete_stream(
|
||||
self,
|
||||
prompt: str,
|
||||
request_settings: HuggingFaceRequestSettings,
|
||||
@@ -113,7 +113,7 @@ class HuggingFaceTextCompletion(TextCompletionClientBase, AIServiceClientBase):
|
||||
raise AIException(
|
||||
AIException.ErrorCodes.InvalidConfiguration,
|
||||
"HuggingFace TextIteratorStreamer does not stream multiple responses in a parseable format. \
|
||||
If you need multiple responses, please use the complete_async method.",
|
||||
If you need multiple responses, please use the complete method.",
|
||||
)
|
||||
try:
|
||||
tokenizer = transformers.AutoTokenizer.from_pretrained(self.ai_model_id)
|
||||
|
||||
@@ -46,7 +46,7 @@ class HuggingFaceTextEmbedding(EmbeddingGeneratorBase, AIServiceClientBase):
|
||||
generator=sentence_transformers.SentenceTransformer(model_name_or_path=ai_model_id, device=resolved_device),
|
||||
)
|
||||
|
||||
async def generate_embeddings_async(self, texts: List[str]) -> ndarray:
|
||||
async def generate_embeddings(self, texts: List[str]) -> ndarray:
|
||||
"""
|
||||
Generates embeddings for a list of texts.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class OllamaChatCompletion(TextCompletionClientBase, ChatCompletionClientBase, A
|
||||
url: HttpUrl = "http://localhost:11434/api/chat"
|
||||
session: Optional[aiohttp.ClientSession] = None
|
||||
|
||||
async def complete_chat_async(
|
||||
async def complete_chat(
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
request_settings: OllamaChatRequestSettings,
|
||||
@@ -64,7 +64,7 @@ class OllamaChatCompletion(TextCompletionClientBase, ChatCompletionClientBase, A
|
||||
response_object = await response.json()
|
||||
return response_object.get("message", {"content": None}).get("content", None)
|
||||
|
||||
async def complete_chat_stream_async(
|
||||
async def complete_chat_stream(
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
settings: OllamaChatRequestSettings,
|
||||
@@ -93,7 +93,7 @@ class OllamaChatCompletion(TextCompletionClientBase, ChatCompletionClientBase, A
|
||||
if body.get("done"):
|
||||
break
|
||||
|
||||
async def complete_async(
|
||||
async def complete(
|
||||
self,
|
||||
prompt: str,
|
||||
request_settings: OllamaChatRequestSettings,
|
||||
@@ -110,9 +110,9 @@ class OllamaChatCompletion(TextCompletionClientBase, ChatCompletionClientBase, A
|
||||
Returns:
|
||||
Union[str, List[str]] -- A string or list of strings representing the response(s) from the LLM.
|
||||
"""
|
||||
return await self.complete_chat_async([{"role": "user", "content": prompt}], request_settings, **kwargs)
|
||||
return await self.complete_chat([{"role": "user", "content": prompt}], request_settings, **kwargs)
|
||||
|
||||
async def complete_stream_async(
|
||||
async def complete_stream(
|
||||
self,
|
||||
prompt: str,
|
||||
request_settings: OllamaChatRequestSettings,
|
||||
@@ -129,7 +129,7 @@ class OllamaChatCompletion(TextCompletionClientBase, ChatCompletionClientBase, A
|
||||
Yields:
|
||||
str -- Completion result.
|
||||
"""
|
||||
response = self.complete_chat_stream_async([{"role": "user", "content": prompt}], request_settings, **kwargs)
|
||||
response = self.complete_chat_stream([{"role": "user", "content": prompt}], request_settings, **kwargs)
|
||||
async for line in response:
|
||||
yield line
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class OllamaTextCompletion(TextCompletionClientBase, AIServiceClientBase):
|
||||
url: HttpUrl = "http://localhost:11434/api/generate"
|
||||
session: Optional[aiohttp.ClientSession] = None
|
||||
|
||||
async def complete_async(
|
||||
async def complete(
|
||||
self,
|
||||
prompt: str,
|
||||
request_settings: OllamaTextRequestSettings,
|
||||
@@ -58,7 +58,7 @@ class OllamaTextCompletion(TextCompletionClientBase, AIServiceClientBase):
|
||||
response.raise_for_status()
|
||||
return await response.text()
|
||||
|
||||
async def complete_stream_async(
|
||||
async def complete_stream(
|
||||
self,
|
||||
prompt: str,
|
||||
request_settings: OllamaTextRequestSettings,
|
||||
|
||||
@@ -30,7 +30,7 @@ class OllamaTextEmbedding(EmbeddingGeneratorBase, AIServiceClientBase):
|
||||
url: HttpUrl = "http://localhost:11434/api/embeddings"
|
||||
session: Optional[aiohttp.ClientSession] = None
|
||||
|
||||
async def generate_embeddings_async(self, texts: List[str], **kwargs) -> ndarray:
|
||||
async def generate_embeddings(self, texts: List[str], **kwargs) -> ndarray:
|
||||
"""
|
||||
Generates embeddings for a list of texts.
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ class AzureChatCompletion(AzureOpenAIConfigBase, ChatCompletionClientBase, OpenA
|
||||
default_headers=settings.get("default_headers"),
|
||||
)
|
||||
|
||||
async def complete_chat_async(
|
||||
async def complete_chat(
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
settings: AzureChatRequestSettings,
|
||||
@@ -311,7 +311,7 @@ class AzureChatCompletion(AzureOpenAIConfigBase, ChatCompletionClientBase, OpenA
|
||||
for choice in response.choices
|
||||
]
|
||||
|
||||
async def complete_chat_stream_async(
|
||||
async def complete_chat_stream(
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
settings: AzureChatRequestSettings,
|
||||
|
||||
@@ -156,7 +156,7 @@ class OpenAIChatCompletion(OpenAIConfigBase, ChatCompletionClientBase, OpenAITex
|
||||
default_headers=settings.get("default_headers"),
|
||||
)
|
||||
|
||||
async def complete_chat_async(
|
||||
async def complete_chat(
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
settings: OpenAIRequestSettings,
|
||||
@@ -183,7 +183,7 @@ class OpenAIChatCompletion(OpenAIConfigBase, ChatCompletionClientBase, OpenAITex
|
||||
else:
|
||||
return [_parse_message(choice.message) for choice in response.choices]
|
||||
|
||||
async def complete_chat_stream_async(
|
||||
async def complete_chat_stream(
|
||||
self,
|
||||
messages: List[Dict[str, str]],
|
||||
settings: OpenAIRequestSettings,
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ logger: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OpenAITextCompletionBase(TextCompletionClientBase, OpenAIHandler):
|
||||
async def complete_async(
|
||||
async def complete(
|
||||
self,
|
||||
prompt: str,
|
||||
settings: "OpenAIRequestSettings",
|
||||
@@ -54,7 +54,7 @@ class OpenAITextCompletionBase(TextCompletionClientBase, OpenAIHandler):
|
||||
return response.choices[0].message.content
|
||||
return [choice.message.content for choice in response.choices]
|
||||
|
||||
async def complete_stream_async(
|
||||
async def complete_stream(
|
||||
self,
|
||||
prompt: str,
|
||||
settings: "OpenAIRequestSettings",
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ from semantic_kernel.connectors.ai.open_ai.services.open_ai_handler import (
|
||||
|
||||
|
||||
class OpenAITextEmbeddingBase(OpenAIHandler, EmbeddingGeneratorBase):
|
||||
async def generate_embeddings_async(
|
||||
async def generate_embeddings(
|
||||
self, texts: List[str], batch_size: Optional[int] = None, **kwargs: Dict[str, Any]
|
||||
) -> ndarray:
|
||||
"""Generates embeddings for the given texts.
|
||||
|
||||
@@ -95,7 +95,7 @@ def get_function_calling_object(kernel: Kernel, filter: Dict[str, List[str]]) ->
|
||||
async def execute_function_call(kernel: Kernel, function_call: FunctionCall, log: Optional[Any] = None) -> str:
|
||||
if log:
|
||||
logger.warning("The `log` parameter is deprecated. Please use the `logging` module instead.")
|
||||
result = await kernel.run_async(
|
||||
result = await kernel.run(
|
||||
kernel.func(**function_call.split_name_dict()),
|
||||
input_vars=function_call.to_context_variables(),
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ class TextCompletionClientBase(ABC):
|
||||
"""Base class for text completion AI services."""
|
||||
|
||||
@abstractmethod
|
||||
async def complete_async(
|
||||
async def complete(
|
||||
self,
|
||||
prompt: str,
|
||||
settings: "AIRequestSettings",
|
||||
@@ -31,7 +31,7 @@ class TextCompletionClientBase(ABC):
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
async def complete_stream_async(
|
||||
async def complete_stream(
|
||||
self,
|
||||
prompt: str,
|
||||
settings: "AIRequestSettings",
|
||||
|
||||
+17
-17
@@ -74,12 +74,12 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
search_endpoint, admin_key, azure_credentials, token_credentials
|
||||
)
|
||||
|
||||
async def close_async(self):
|
||||
async def close(self):
|
||||
"""Async close connection, invoked by MemoryStoreBase.__aexit__()"""
|
||||
if self._search_index_client is not None:
|
||||
await self._search_index_client.close()
|
||||
|
||||
async def create_collection_async(
|
||||
async def create_collection(
|
||||
self,
|
||||
collection_name: str,
|
||||
vector_config: Optional[HnswVectorSearchAlgorithmConfiguration] = None,
|
||||
@@ -140,7 +140,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
await self._search_index_client.create_index(index)
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""Gets the list of collections.
|
||||
|
||||
Returns:
|
||||
@@ -159,7 +159,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
return results_list
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection.
|
||||
|
||||
Arguments:
|
||||
@@ -170,7 +170,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
await self._search_index_client.delete_index(index=collection_name.lower())
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Checks if a collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -190,7 +190,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
except ResourceNotFoundError:
|
||||
return False
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upsert a record.
|
||||
|
||||
Arguments:
|
||||
@@ -201,12 +201,12 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
str -- The unique record id of the record.
|
||||
"""
|
||||
|
||||
result = await self.upsert_batch_async(collection_name, [record])
|
||||
result = await self.upsert_batch(collection_name, [record])
|
||||
if result:
|
||||
return result[0]
|
||||
return None
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""Upsert a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -243,7 +243,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
return None
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
"""Gets a record.
|
||||
|
||||
Arguments:
|
||||
@@ -271,7 +271,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
# Create Memory record from document
|
||||
return dict_to_memory_record(search_result, with_embedding)
|
||||
|
||||
async def get_batch_async(
|
||||
async def get_batch(
|
||||
self, collection_name: str, keys: List[str], with_embeddings: bool = False
|
||||
) -> List[MemoryRecord]:
|
||||
"""Gets a batch of records.
|
||||
@@ -288,7 +288,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
search_results = []
|
||||
|
||||
for key in keys:
|
||||
search_result = await self.get_async(
|
||||
search_result = await self.get(
|
||||
collection_name=collection_name.lower(),
|
||||
key=key,
|
||||
with_embedding=with_embeddings,
|
||||
@@ -297,7 +297,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
return search_results
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Removes a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -309,9 +309,9 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
|
||||
for record_id in keys:
|
||||
await self.remove_async(collection_name=collection_name.lower(), key=encode_id(record_id))
|
||||
await self.remove(collection_name=collection_name.lower(), key=encode_id(record_id))
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Removes a record.
|
||||
|
||||
Arguments:
|
||||
@@ -329,7 +329,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
await search_client.delete_documents(documents=[docs_to_delete])
|
||||
await search_client.close()
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -348,7 +348,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
Tuple[MemoryRecord, float] -- The record and the relevance score.
|
||||
"""
|
||||
|
||||
memory_records = await self.get_nearest_matches_async(
|
||||
memory_records = await self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
min_relevance_score=min_relevance_score,
|
||||
@@ -361,7 +361,7 @@ class AzureCognitiveSearchMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
return None
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
|
||||
+14
-14
@@ -92,10 +92,10 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
num_lists,
|
||||
similarity,
|
||||
)
|
||||
await store.create_collection_async(collection_name)
|
||||
await store.create_collection(collection_name)
|
||||
return store
|
||||
|
||||
async def create_collection_async(self, collection_name: str) -> None:
|
||||
async def create_collection(self, collection_name: str) -> None:
|
||||
"""Creates a new collection in the data store.
|
||||
|
||||
Arguments:
|
||||
@@ -106,15 +106,15 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.create_collection(collection_name)
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""Gets the list of collections.
|
||||
|
||||
Returns:
|
||||
List[str] -- The list of collections.
|
||||
"""
|
||||
return await self.cosmosStore.get_collections_async()
|
||||
return await self.cosmosStore.get_collections()
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection.
|
||||
|
||||
Arguments:
|
||||
@@ -125,7 +125,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.delete_collection(str())
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Checks if a collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -136,7 +136,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.does_collection_exist(str())
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upsert a record.
|
||||
|
||||
Arguments:
|
||||
@@ -148,7 +148,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.upsert(str(), record)
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""Upsert a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -160,7 +160,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.upsert_batch(str(), records)
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
"""Gets a record.
|
||||
|
||||
Arguments:
|
||||
@@ -173,7 +173,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.get(str(), key, with_embedding)
|
||||
|
||||
async def get_batch_async(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
async def get_batch(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
"""Gets a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -186,7 +186,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.get_batch(str(), keys, with_embeddings)
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Removes a record.
|
||||
|
||||
Arguments:
|
||||
@@ -198,7 +198,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.remove(str(), key)
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Removes a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -210,7 +210,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.remove_batch(str(), keys)
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -232,7 +232,7 @@ class AzureCosmosDBMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.cosmosStore.get_nearest_matches(str(), embedding, limit, min_relevance_score, with_embeddings)
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
|
||||
@@ -77,7 +77,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
|
||||
self._default_embedding_function = "DisableChromaEmbeddingFunction"
|
||||
|
||||
async def create_collection_async(self, collection_name: str) -> None:
|
||||
async def create_collection(self, collection_name: str) -> None:
|
||||
"""Creates a new collection in Chroma if it does not exist.
|
||||
To prevent downloading model file from embedding_function,
|
||||
embedding_function is set to "DoNotUseChromaEmbeddingFunction".
|
||||
@@ -96,7 +96,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
embedding_function=self._default_embedding_function,
|
||||
)
|
||||
|
||||
async def get_collection_async(self, collection_name: str) -> Optional["Collection"]:
|
||||
async def get_collection(self, collection_name: str) -> Optional["Collection"]:
|
||||
try:
|
||||
# Current version of ChromeDB rejects camel case collection names.
|
||||
return self._client.get_collection(
|
||||
@@ -106,7 +106,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""Gets the list of collections.
|
||||
|
||||
Returns:
|
||||
@@ -114,7 +114,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return [collection.name for collection in self._client.list_collections()]
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection.
|
||||
|
||||
Arguments:
|
||||
@@ -126,7 +126,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
# Current version of ChromeDB reject camel case collection names.
|
||||
self._client.delete_collection(name=camel_to_snake(collection_name))
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Checks if a collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -135,12 +135,12 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
bool -- True if the collection exists; otherwise, False.
|
||||
"""
|
||||
if await self.get_collection_async(collection_name) is None:
|
||||
if await self.get_collection(collection_name) is None:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upserts a single MemoryRecord.
|
||||
|
||||
Arguments:
|
||||
@@ -150,7 +150,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
List[str] -- The unique database key of the record.
|
||||
"""
|
||||
collection = await self.get_collection_async(collection_name)
|
||||
collection = await self.get_collection(collection_name)
|
||||
if collection is None:
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
|
||||
@@ -173,7 +173,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
)
|
||||
return record._key
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""Upserts a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -183,10 +183,10 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
List[str] -- The unique database keys of the records. In Pinecone, these are the record IDs.
|
||||
"""
|
||||
# upsert_async is checking collection existence
|
||||
return [await self.upsert_async(collection_name, record) for record in records]
|
||||
# upsert is checking collection existence
|
||||
return [await self.upsert(collection_name, record) for record in records]
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
"""Gets a record.
|
||||
|
||||
Arguments:
|
||||
@@ -197,13 +197,13 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
MemoryRecord -- The record.
|
||||
"""
|
||||
records = await self.get_batch_async(collection_name, [key], with_embedding)
|
||||
records = await self.get_batch(collection_name, [key], with_embedding)
|
||||
try:
|
||||
return records[0]
|
||||
except IndexError:
|
||||
raise Exception(f"Record with key '{key}' does not exist in collection '{collection_name}'")
|
||||
|
||||
async def get_batch_async(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
async def get_batch(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
"""Gets a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -214,7 +214,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
List[MemoryRecord] -- The records.
|
||||
"""
|
||||
collection = await self.get_collection_async(collection_name)
|
||||
collection = await self.get_collection(collection_name)
|
||||
if collection is None:
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
|
||||
@@ -224,7 +224,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
record = query_results_to_records(value, with_embeddings)
|
||||
return record
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Removes a record.
|
||||
|
||||
Arguments:
|
||||
@@ -234,9 +234,9 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
await self.remove_batch_async(collection_name, [key])
|
||||
await self.remove_batch(collection_name, [key])
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Removes a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -246,11 +246,11 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
collection = await self.get_collection_async(collection_name=collection_name)
|
||||
collection = await self.get_collection(collection_name=collection_name)
|
||||
if collection is not None:
|
||||
collection.delete(ids=keys)
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -275,7 +275,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
"Chroma returns distance score not cosine similarity score.\
|
||||
So embeddings are automatically queried from database for calculation."
|
||||
)
|
||||
collection = await self.get_collection_async(collection_name)
|
||||
collection = await self.get_collection(collection_name)
|
||||
if collection is None:
|
||||
return []
|
||||
|
||||
@@ -318,7 +318,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
|
||||
return top_results
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -336,7 +336,7 @@ class ChromaMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
Tuple[MemoryRecord, float] -- The record and the relevance score.
|
||||
"""
|
||||
results = await self.get_nearest_matches_async(
|
||||
results = await self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
limit=1,
|
||||
@@ -371,11 +371,11 @@ if __name__ == "__main__":
|
||||
timestamp="timestamp",
|
||||
)
|
||||
|
||||
asyncio.run(memory.create_collection_async("test_collection"))
|
||||
collection = asyncio.run(memory.get_collection_async("test_collection"))
|
||||
asyncio.run(memory.create_collection("test_collection"))
|
||||
collection = asyncio.run(memory.get_collection("test_collection"))
|
||||
|
||||
asyncio.run(memory.upsert_batch_async(collection.name, [memory_record1, memory_record2]))
|
||||
asyncio.run(memory.upsert_batch(collection.name, [memory_record1, memory_record2]))
|
||||
|
||||
result = asyncio.run(memory.get_async(collection.name, "test_id1", True))
|
||||
results = asyncio.run(memory.get_nearest_match_async("test_collection", np.array([0.5, 0.5])))
|
||||
result = asyncio.run(memory.get(collection.name, "test_id1", True))
|
||||
results = asyncio.run(memory.get_nearest_match("test_collection", np.array([0.5, 0.5])))
|
||||
print(results)
|
||||
|
||||
@@ -91,7 +91,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
)
|
||||
self._metric_cache = {}
|
||||
|
||||
async def create_collection_async(
|
||||
async def create_collection(
|
||||
self,
|
||||
collection_name: str,
|
||||
dimension_num: Optional[int] = 1536,
|
||||
@@ -139,7 +139,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
consistency_level=consistency,
|
||||
)
|
||||
|
||||
async def get_collections_async(
|
||||
async def get_collections(
|
||||
self,
|
||||
) -> List[str]:
|
||||
"""Return a list of present collections.
|
||||
@@ -149,7 +149,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return self._client.list_collections()
|
||||
|
||||
async def delete_collection_async(self, collection_name: str = "", all: bool = False) -> None:
|
||||
async def delete_collection(self, collection_name: str = "", all: bool = False) -> None:
|
||||
"""Delete the specified collection.
|
||||
|
||||
If all is True, all collections in the cluster will be removed.
|
||||
@@ -165,7 +165,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
elif collection_name in cols:
|
||||
self._client.drop_collection(collection_name)
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Return if the collection exists in the cluster.
|
||||
|
||||
Args:
|
||||
@@ -176,7 +176,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return True if collection_name in self._client.list_collections() else False
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upsert a single MemoryRecord into the collection.
|
||||
|
||||
Args:
|
||||
@@ -187,14 +187,14 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
str: The ID of the inserted record.
|
||||
"""
|
||||
# Use the batch insert with a total batch
|
||||
res = await self.upsert_batch_async(
|
||||
res = await self.upsert_batch(
|
||||
collection_name=collection_name,
|
||||
records=[record],
|
||||
batch_size=0,
|
||||
)
|
||||
return res[0]
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord], batch_size=100) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord], batch_size=100) -> List[str]:
|
||||
"""_summary_
|
||||
|
||||
Args:
|
||||
@@ -226,7 +226,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
logger.debug(f"Upsert failed due to: {e}")
|
||||
raise e
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
"""Get the MemoryRecord corresponding to the key.
|
||||
|
||||
Args:
|
||||
@@ -237,10 +237,10 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
MemoryRecord: The MemoryRecord for the key.
|
||||
"""
|
||||
res = await self.get_batch_async(collection_name=collection_name, keys=[key], with_embeddings=with_embedding)
|
||||
res = await self.get_batch(collection_name=collection_name, keys=[key], with_embeddings=with_embedding)
|
||||
return res[0]
|
||||
|
||||
async def get_batch_async(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
async def get_batch(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
"""Get the MemoryRecords corresponding to the keys
|
||||
|
||||
Args:
|
||||
@@ -270,16 +270,16 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
logger.debug(f"Get failed due to: {e}")
|
||||
raise e
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Remove the specified record based on key.
|
||||
|
||||
Args:
|
||||
collection_name (str): Collection to remove from.
|
||||
key (str): The key to remove.
|
||||
"""
|
||||
await self.remove_batch_async(collection_name=collection_name, keys=[key])
|
||||
await self.remove_batch(collection_name=collection_name, keys=[key])
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Remove multiple records based on keys.
|
||||
|
||||
Args:
|
||||
@@ -336,7 +336,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
logger.debug(f"Search failed with L2: {e}")
|
||||
raise e
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -411,7 +411,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
|
||||
return results
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -429,7 +429,7 @@ class MilvusMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
Tuple[MemoryRecord, float]: A tuple of record and distance.
|
||||
"""
|
||||
m = await self.get_nearest_matches_async(
|
||||
m = await self.get_nearest_matches(
|
||||
collection_name,
|
||||
embedding,
|
||||
1,
|
||||
|
||||
+18
-18
@@ -66,13 +66,13 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
def num_candidates(self) -> int:
|
||||
return self.__num_candidates
|
||||
|
||||
async def close_async(self):
|
||||
async def close(self):
|
||||
"""Async close connection, invoked by MemoryStoreBase.__aexit__()"""
|
||||
if self._mongo_client:
|
||||
self._mongo_client.close()
|
||||
self._mongo_client = None
|
||||
|
||||
async def create_collection_async(self, collection_name: str) -> None:
|
||||
async def create_collection(self, collection_name: str) -> None:
|
||||
"""Creates a new collection in the data store.
|
||||
|
||||
Arguments:
|
||||
@@ -81,10 +81,10 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
if not await self.does_collection_exist_async(collection_name):
|
||||
if not await self.does_collection_exist(collection_name):
|
||||
await self.database.create_collection(collection_name)
|
||||
|
||||
async def get_collections_async(
|
||||
async def get_collections(
|
||||
self,
|
||||
) -> List[str]:
|
||||
"""Gets all collection names in the data store.
|
||||
@@ -94,7 +94,7 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return await self.database.list_collection_names()
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection from the data store.
|
||||
|
||||
Arguments:
|
||||
@@ -105,7 +105,7 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
await self.database[collection_name].drop()
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Determines if a collection exists in the data store.
|
||||
|
||||
Arguments:
|
||||
@@ -114,9 +114,9 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
bool -- True if given collection exists, False if not.
|
||||
"""
|
||||
return collection_name in (await self.get_collections_async())
|
||||
return collection_name in (await self.get_collections())
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upserts a memory record into the data store. Does not guarantee that the collection exists.
|
||||
If the record already exists, it will be updated.
|
||||
If the record does not exist, it will be created.
|
||||
@@ -138,7 +138,7 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
assert update_result.acknowledged
|
||||
return record._id
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""Upserts a group of memory records into the data store. Does not guarantee that the collection exists.
|
||||
If the record already exists, it will be updated.
|
||||
If the record does not exist, it will be created.
|
||||
@@ -168,7 +168,7 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
assert bulk_update_result.matched_count + bulk_update_result.upserted_count == len(records)
|
||||
return [record._id for record in records]
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
"""Gets a memory record from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -183,7 +183,7 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
|
||||
return document_to_memory_record(document, with_embedding) if document else None
|
||||
|
||||
async def get_batch_async(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
async def get_batch(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
"""Gets a batch of memory records from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -200,7 +200,7 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
document_to_memory_record(result, with_embeddings) for result in await results.to_list(length=len(keys))
|
||||
]
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Removes a memory record from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -210,11 +210,11 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
if not await self.does_collection_exist_async(collection_name):
|
||||
if not await self.does_collection_exist(collection_name):
|
||||
raise Exception(f"collection {collection_name} not found")
|
||||
await self.database[collection_name].delete_one({MONGODB_FIELD_ID: key})
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Removes a batch of memory records from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -224,13 +224,13 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
if not await self.does_collection_exist_async(collection_name):
|
||||
if not await self.does_collection_exist(collection_name):
|
||||
raise Exception(f"collection {collection_name} not found")
|
||||
deletes: List[DeleteOne] = [DeleteOne({MONGODB_FIELD_ID: key}) for key in keys]
|
||||
bulk_write_result = await self.database[collection_name].bulk_write(deletes, ordered=False)
|
||||
logger.debug("%s entries deleted", bulk_write_result.deleted_count)
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -278,7 +278,7 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
for doc in await cursor.to_list(length=limit)
|
||||
]
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -296,7 +296,7 @@ class MongoDBAtlasMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
Tuple[MemoryRecord, float] -- A tuple consisting of the MemoryRecord and the similarity score as a float.
|
||||
"""
|
||||
matches: List[Tuple[MemoryRecord, float]] = await self.get_nearest_matches_async(
|
||||
matches: List[Tuple[MemoryRecord, float]] = await self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
limit=1,
|
||||
|
||||
@@ -59,10 +59,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
|
||||
pinecone.init(api_key=self._pinecone_api_key, environment=self._pinecone_environment)
|
||||
|
||||
def get_collections(self) -> List[str]:
|
||||
return pinecone.list_indexes()
|
||||
|
||||
async def create_collection_async(
|
||||
async def create_collection(
|
||||
self,
|
||||
collection_name: str,
|
||||
dimension_num: Optional[int] = None,
|
||||
@@ -103,7 +100,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
metadata_config=metadata_config,
|
||||
)
|
||||
|
||||
async def describe_collection_async(self, collection_name: str) -> Optional[IndexDescription]:
|
||||
async def describe_collection(self, collection_name: str) -> Optional[IndexDescription]:
|
||||
"""Gets the description of the index.
|
||||
Arguments:
|
||||
collection_name {str} -- The name of the index to get.
|
||||
@@ -114,7 +111,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
return pinecone.describe_index(collection_name)
|
||||
return None
|
||||
|
||||
async def get_collections_async(
|
||||
async def get_collections(
|
||||
self,
|
||||
) -> List[str]:
|
||||
"""Gets the list of collections.
|
||||
@@ -124,7 +121,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return list(pinecone.list_indexes())
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection.
|
||||
|
||||
Arguments:
|
||||
@@ -136,7 +133,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
if collection_name in pinecone.list_indexes():
|
||||
pinecone.delete_index(collection_name)
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Checks if a collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -147,7 +144,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return collection_name in pinecone.list_indexes()
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upserts a record.
|
||||
|
||||
Arguments:
|
||||
@@ -172,7 +169,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
|
||||
return record._id
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""Upserts a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -203,7 +200,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
return [record._id for record in records]
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
"""Gets a record.
|
||||
|
||||
Arguments:
|
||||
@@ -225,7 +222,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
|
||||
return parse_payload(fetch_response.vectors[key], with_embedding)
|
||||
|
||||
async def get_batch_async(
|
||||
async def get_batch(
|
||||
self, collection_name: str, keys: List[str], with_embeddings: bool = False
|
||||
) -> List[MemoryRecord]:
|
||||
"""Gets a batch of records.
|
||||
@@ -241,10 +238,10 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
if collection_name not in pinecone.list_indexes():
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
|
||||
fetch_response = await self.__get_batch_async(collection_name, keys, with_embeddings)
|
||||
fetch_response = await self.__get_batch(collection_name, keys, with_embeddings)
|
||||
return [parse_payload(fetch_response.vectors[key], with_embeddings) for key in fetch_response.vectors.keys()]
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Removes a record.
|
||||
|
||||
Arguments:
|
||||
@@ -260,7 +257,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
collection = pinecone.Index(collection_name)
|
||||
collection.delete([key])
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Removes a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -278,7 +275,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
collection.delete(keys[i : i + MAX_DELETE_BATCH_SIZE])
|
||||
collection.delete(keys)
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -296,7 +293,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
Tuple[MemoryRecord, float] -- The record and the relevance score.
|
||||
"""
|
||||
matches = await self.get_nearest_matches_async(
|
||||
matches = await self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
limit=1,
|
||||
@@ -305,7 +302,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
)
|
||||
return matches[0]
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -340,7 +337,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
include_metadata=False,
|
||||
)
|
||||
keys = [match.id for match in query_response.matches]
|
||||
fetch_response = await self.__get_batch_async(collection_name, keys, with_embeddings)
|
||||
fetch_response = await self.__get_batch(collection_name, keys, with_embeddings)
|
||||
vectors = fetch_response.vectors
|
||||
for match in query_response.matches:
|
||||
vectors[match.id].update(match)
|
||||
@@ -367,7 +364,7 @@ class PineconeMemoryStore(MemoryStoreBase):
|
||||
else []
|
||||
)
|
||||
|
||||
async def __get_batch_async(
|
||||
async def __get_batch(
|
||||
self, collection_name: str, keys: List[str], with_embeddings: bool = False
|
||||
) -> "FetchResponse":
|
||||
index = pinecone.Index(collection_name)
|
||||
|
||||
@@ -59,7 +59,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
self._schema = schema
|
||||
atexit.register(self._connection_pool.close)
|
||||
|
||||
async def create_collection_async(
|
||||
async def create_collection(
|
||||
self,
|
||||
collection_name: str,
|
||||
dimension_num: Optional[int] = None,
|
||||
@@ -98,7 +98,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
(),
|
||||
)
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""Gets the list of collections.
|
||||
|
||||
Returns:
|
||||
@@ -106,9 +106,9 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
return await self.__get_collections_async(cur)
|
||||
return await self.__get_collections(cur)
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection.
|
||||
|
||||
Arguments:
|
||||
@@ -125,7 +125,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
),
|
||||
)
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Checks if a collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -136,9 +136,9 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
return await self.__does_collection_exist_async(cur, collection_name)
|
||||
return await self.__does_collection_exist(cur, collection_name)
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upserts a record.
|
||||
|
||||
Arguments:
|
||||
@@ -150,7 +150,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
if not await self.__does_collection_exist_async(cur, collection_name):
|
||||
if not await self.__does_collection_exist(cur, collection_name):
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
cur.execute(
|
||||
SQL(
|
||||
@@ -179,7 +179,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
raise Exception("Upsert failed")
|
||||
return result[0]
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""Upserts a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -191,7 +191,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
if not await self.__does_collection_exist_async(cur, collection_name):
|
||||
if not await self.__does_collection_exist(cur, collection_name):
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
cur.nextset()
|
||||
cur.executemany(
|
||||
@@ -229,7 +229,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
raise Exception("Upsert failed")
|
||||
return [result[0] for result in results if result is not None]
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
"""Gets a record.
|
||||
|
||||
Arguments:
|
||||
@@ -242,7 +242,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
if not await self.__does_collection_exist_async(cur, collection_name):
|
||||
if not await self.__does_collection_exist(cur, collection_name):
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
cur.execute(
|
||||
SQL(
|
||||
@@ -271,7 +271,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
timestamp=result[3],
|
||||
)
|
||||
|
||||
async def get_batch_async(
|
||||
async def get_batch(
|
||||
self, collection_name: str, keys: List[str], with_embeddings: bool = False
|
||||
) -> List[MemoryRecord]:
|
||||
"""Gets a batch of records.
|
||||
@@ -286,7 +286,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
if not await self.__does_collection_exist_async(cur, collection_name):
|
||||
if not await self.__does_collection_exist(cur, collection_name):
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
cur.execute(
|
||||
SQL(
|
||||
@@ -316,7 +316,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
for result in results
|
||||
]
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Removes a record.
|
||||
|
||||
Arguments:
|
||||
@@ -328,7 +328,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
if not await self.__does_collection_exist_async(cur, collection_name):
|
||||
if not await self.__does_collection_exist(cur, collection_name):
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
cur.execute(
|
||||
SQL(
|
||||
@@ -340,7 +340,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
(key,),
|
||||
)
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Removes a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -352,7 +352,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
if not await self.__does_collection_exist_async(cur, collection_name):
|
||||
if not await self.__does_collection_exist(cur, collection_name):
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
cur.execute(
|
||||
SQL(
|
||||
@@ -364,7 +364,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
(list(keys),),
|
||||
)
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -386,7 +386,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
with self._connection_pool.connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
if not await self.__does_collection_exist_async(cur, collection_name):
|
||||
if not await self.__does_collection_exist(cur, collection_name):
|
||||
raise Exception(f"Collection '{collection_name}' does not exist")
|
||||
cur.execute(
|
||||
SQL(
|
||||
@@ -432,7 +432,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
for result in results
|
||||
]
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -451,7 +451,7 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
Tuple[MemoryRecord, float] -- The record and the relevance score.
|
||||
"""
|
||||
|
||||
results = await self.get_nearest_matches_async(
|
||||
results = await self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
limit=1,
|
||||
@@ -462,11 +462,11 @@ class PostgresMemoryStore(MemoryStoreBase):
|
||||
raise Exception("No match found")
|
||||
return results[0]
|
||||
|
||||
async def __does_collection_exist_async(self, cur: Cursor, collection_name: str) -> bool:
|
||||
results = await self.__get_collections_async(cur)
|
||||
async def __does_collection_exist(self, cur: Cursor, collection_name: str) -> bool:
|
||||
results = await self.__get_collections(cur)
|
||||
return collection_name in results
|
||||
|
||||
async def __get_collections_async(self, cur: Cursor) -> List[str]:
|
||||
async def __get_collections(self, cur: Cursor) -> List[str]:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT table_name
|
||||
|
||||
@@ -43,7 +43,7 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
|
||||
self._default_vector_size = vector_size
|
||||
|
||||
async def create_collection_async(self, collection_name: str) -> None:
|
||||
async def create_collection(self, collection_name: str) -> None:
|
||||
"""Creates a new collection if it does not exist.
|
||||
|
||||
Arguments:
|
||||
@@ -60,7 +60,7 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
),
|
||||
)
|
||||
|
||||
async def get_collections_async(
|
||||
async def get_collections(
|
||||
self,
|
||||
) -> List[str]:
|
||||
"""Gets the list of collections.
|
||||
@@ -71,7 +71,7 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
collection_info = self._qdrantclient.get_collections()
|
||||
return [collection.name for collection in collection_info.collections]
|
||||
|
||||
async def get_collection_async(self, collection_name: str) -> qdrant_models.CollectionInfo:
|
||||
async def get_collection(self, collection_name: str) -> qdrant_models.CollectionInfo:
|
||||
"""Gets the a collections based upon collection name.
|
||||
|
||||
Returns:
|
||||
@@ -80,7 +80,7 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
collection_info = self._qdrantclient.get_collection(collection_name=collection_name)
|
||||
return collection_info
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection.
|
||||
|
||||
Arguments:
|
||||
@@ -92,7 +92,7 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
|
||||
self._qdrantclient.delete_collection(collection_name=collection_name)
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Checks if a collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -102,12 +102,12 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
bool -- True if the collection exists; otherwise, False.
|
||||
"""
|
||||
try:
|
||||
result = await self.get_collection_async(collection_name=collection_name)
|
||||
result = await self.get_collection(collection_name=collection_name)
|
||||
return result.status == qdrant_models.CollectionStatus.GREEN
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upserts a record.
|
||||
|
||||
Arguments:
|
||||
@@ -117,7 +117,7 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
str -- The unique database key of the record.
|
||||
"""
|
||||
data_to_upsert = await self._convert_from_memory_record_async(
|
||||
data_to_upsert = await self._convert_from_memory_record(
|
||||
collection_name=collection_name,
|
||||
record=record,
|
||||
)
|
||||
@@ -132,11 +132,11 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
raise Exception("Upsert failed")
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
tasks = []
|
||||
for record in records:
|
||||
tasks.append(
|
||||
self._convert_from_memory_record_async(
|
||||
self._convert_from_memory_record(
|
||||
collection_name=collection_name,
|
||||
record=record,
|
||||
)
|
||||
@@ -154,8 +154,8 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
raise Exception("Batch upsert failed")
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool = False) -> Optional[MemoryRecord]:
|
||||
result = await self._get_existing_record_by_payload_id_async(
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool = False) -> Optional[MemoryRecord]:
|
||||
result = await self._get_existing_record_by_payload_id(
|
||||
collection_name=collection_name,
|
||||
payload_id=key,
|
||||
with_embedding=with_embedding,
|
||||
@@ -176,13 +176,13 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
return None
|
||||
|
||||
async def get_batch_async(
|
||||
async def get_batch(
|
||||
self, collection_name: str, keys: List[str], with_embeddings: bool = False
|
||||
) -> List[MemoryRecord]:
|
||||
tasks = []
|
||||
for key in keys:
|
||||
tasks.append(
|
||||
self.get_async(
|
||||
self.get(
|
||||
collection_name=collection_name,
|
||||
key=key,
|
||||
with_embedding=with_embeddings,
|
||||
@@ -190,8 +190,8 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
)
|
||||
return await asyncio.gather(*tasks)
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
existing_record = await self._get_existing_record_by_payload_id_async(
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
existing_record = await self._get_existing_record_by_payload_id(
|
||||
collection_name=collection_name,
|
||||
payload_id=key,
|
||||
with_embedding=False,
|
||||
@@ -203,11 +203,11 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
if result.status != qdrant_models.UpdateStatus.COMPLETED:
|
||||
raise Exception("Delete failed")
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
tasks = []
|
||||
for key in keys:
|
||||
tasks.append(
|
||||
self._get_existing_record_by_payload_id_async(
|
||||
self._get_existing_record_by_payload_id(
|
||||
collection_name=collection_name,
|
||||
payload_id=key,
|
||||
with_embedding=False,
|
||||
@@ -224,7 +224,7 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
if result.status != qdrant_models.UpdateStatus.COMPLETED:
|
||||
raise Exception("Delete failed")
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -258,14 +258,14 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
for result in match_results
|
||||
]
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
min_relevance_score: float,
|
||||
with_embedding: bool = False,
|
||||
) -> Tuple[MemoryRecord, float]:
|
||||
result = await self.get_nearest_matches_async(
|
||||
result = await self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
limit=1,
|
||||
@@ -274,7 +274,7 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
)
|
||||
return result[0] if result else None
|
||||
|
||||
async def _get_existing_record_by_payload_id_async(
|
||||
async def _get_existing_record_by_payload_id(
|
||||
self,
|
||||
collection_name: str,
|
||||
payload_id: str,
|
||||
@@ -312,14 +312,14 @@ class QdrantMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
return None
|
||||
|
||||
async def _convert_from_memory_record_async(
|
||||
async def _convert_from_memory_record(
|
||||
self, collection_name: str, record: MemoryRecord
|
||||
) -> qdrant_models.PointStruct:
|
||||
if record._key is not None and record._key != "":
|
||||
pointId = record._key
|
||||
|
||||
else:
|
||||
existing_record = await self._get_existing_record_by_payload_id_async(
|
||||
existing_record = await self._get_existing_record_by_payload_id(
|
||||
collection_name=collection_name,
|
||||
payload_id=record._id,
|
||||
)
|
||||
|
||||
@@ -76,14 +76,14 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
self._vector_type = np.float32 if vector_type == "FLOAT32" else np.float64
|
||||
self._vector_size = vector_size
|
||||
|
||||
async def close_async(self):
|
||||
async def close(self):
|
||||
"""
|
||||
Closes the Redis database connection
|
||||
"""
|
||||
logger.info("Closing Redis connection")
|
||||
self._database.close()
|
||||
|
||||
async def create_collection_async(self, collection_name: str) -> None:
|
||||
async def create_collection(self, collection_name: str) -> None:
|
||||
"""
|
||||
Creates a collection, implemented as a Redis index containing hashes
|
||||
prefixed with "collection_name:".
|
||||
@@ -93,7 +93,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
collection_name {str} -- Name for a collection of embeddings
|
||||
"""
|
||||
|
||||
if await self.does_collection_exist_async(collection_name):
|
||||
if await self.does_collection_exist(collection_name):
|
||||
logger.info(f'Collection "{collection_name}" already exists.')
|
||||
else:
|
||||
index_def = IndexDefinition(prefix=f"{collection_name}:", index_type=IndexType.HASH)
|
||||
@@ -118,7 +118,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
logger.error(e)
|
||||
raise e
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""
|
||||
Returns a list of names of all collection names present in the data store.
|
||||
|
||||
@@ -128,7 +128,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
# Note: FT._LIST is a temporary command that may be deprecated in the future according to Redis
|
||||
return [name.decode() for name in self._database.execute_command("FT._LIST")]
|
||||
|
||||
async def delete_collection_async(self, collection_name: str, delete_records: bool = True) -> None:
|
||||
async def delete_collection(self, collection_name: str, delete_records: bool = True) -> None:
|
||||
"""
|
||||
Deletes a collection from the data store.
|
||||
If the collection does not exist, the database is left unchanged.
|
||||
@@ -138,10 +138,10 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
delete_records {bool} -- Delete all data associated with the collection, default to True
|
||||
|
||||
"""
|
||||
if await self.does_collection_exist_async(collection_name):
|
||||
if await self.does_collection_exist(collection_name):
|
||||
self._ft(collection_name).dropindex(delete_documents=delete_records)
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""
|
||||
Determines if a collection exists in the data store.
|
||||
|
||||
@@ -157,7 +157,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
except ResponseError:
|
||||
return False
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""
|
||||
Upsert a memory record into the data store. Does not guarantee that the collection exists.
|
||||
* If the record already exists, it will be updated.
|
||||
@@ -174,7 +174,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
str -- Redis key associated with the upserted memory record
|
||||
"""
|
||||
|
||||
if not await self.does_collection_exist_async(collection_name):
|
||||
if not await self.does_collection_exist(collection_name):
|
||||
logger.error(f'Collection "{collection_name}" does not exist')
|
||||
raise Exception(f'Collection "{collection_name}" does not exist')
|
||||
|
||||
@@ -193,7 +193,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
logger.error(e)
|
||||
raise e
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""
|
||||
Upserts a group of memory records into the data store. Does not guarantee that the collection exists.
|
||||
* If the record already exists, it will be updated.
|
||||
@@ -212,12 +212,12 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
|
||||
keys = list()
|
||||
for record in records:
|
||||
record_key = await self.upsert_async(collection_name, record)
|
||||
record_key = await self.upsert(collection_name, record)
|
||||
keys.append(record_key)
|
||||
|
||||
return keys
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
"""
|
||||
Gets a memory record from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
@@ -230,7 +230,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
MemoryRecord -- The memory record if found, else None
|
||||
"""
|
||||
|
||||
if not await self.does_collection_exist_async(collection_name):
|
||||
if not await self.does_collection_exist(collection_name):
|
||||
logger.error(f'Collection "{collection_name}" does not exist')
|
||||
raise Exception(f'Collection "{collection_name}" does not exist')
|
||||
|
||||
@@ -246,7 +246,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
|
||||
return record
|
||||
|
||||
async def get_batch_async(
|
||||
async def get_batch(
|
||||
self, collection_name: str, keys: List[str], with_embeddings: bool = False
|
||||
) -> List[MemoryRecord]:
|
||||
"""
|
||||
@@ -263,13 +263,13 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
|
||||
records = list()
|
||||
for key in keys:
|
||||
record = await self.get_async(collection_name, key, with_embeddings)
|
||||
record = await self.get(collection_name, key, with_embeddings)
|
||||
if record:
|
||||
records.append(record)
|
||||
|
||||
return records
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""
|
||||
Removes a memory record from the data store. Does not guarantee that the collection exists.
|
||||
If the key does not exist, do nothing.
|
||||
@@ -278,13 +278,13 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
collection_name {str} -- Name for a collection of embeddings
|
||||
key {str} -- ID associated with the memory to remove
|
||||
"""
|
||||
if not await self.does_collection_exist_async(collection_name):
|
||||
if not await self.does_collection_exist(collection_name):
|
||||
logger.error(f'Collection "{collection_name}" does not exist')
|
||||
raise Exception(f'Collection "{collection_name}" does not exist')
|
||||
|
||||
self._database.delete(get_redis_key(collection_name, key))
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""
|
||||
Removes a batch of memory records from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
@@ -292,13 +292,13 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
collection_name {str} -- Name for a collection of embeddings
|
||||
keys {List[str]} -- IDs associated with the memory records to remove
|
||||
"""
|
||||
if not await self.does_collection_exist_async(collection_name):
|
||||
if not await self.does_collection_exist(collection_name):
|
||||
logger.error(f'Collection "{collection_name}" does not exist')
|
||||
raise Exception(f'Collection "{collection_name}" does not exist')
|
||||
|
||||
self._database.delete(*[get_redis_key(collection_name, key) for key in keys])
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -320,7 +320,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
List[Tuple[MemoryRecord, float]] -- Records and their relevance scores by descending
|
||||
order, or an empty list if no relevant matches are found
|
||||
"""
|
||||
if not await self.does_collection_exist_async(collection_name):
|
||||
if not await self.does_collection_exist(collection_name):
|
||||
logger.error(f'Collection "{collection_name}" does not exist')
|
||||
raise Exception(f'Collection "{collection_name}" does not exist')
|
||||
|
||||
@@ -353,7 +353,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
|
||||
return relevant_records
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -372,7 +372,7 @@ class RedisMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
Tuple[MemoryRecord, float] -- Record and the relevance score, or None if not found
|
||||
"""
|
||||
matches = await self.get_nearest_matches_async(
|
||||
matches = await self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
limit=1,
|
||||
|
||||
@@ -129,9 +129,9 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
This store helps searching embeddings with USearch, keeping collections in memory.
|
||||
To save collections to disk, provide the `persist_directory` param.
|
||||
Collections are saved when `close_async` is called.
|
||||
Collections are saved when `close` is called.
|
||||
|
||||
To both save collections and free up memory, call `close_async`.
|
||||
To both save collections and free up memory, call `close`.
|
||||
When `USearchMemoryStore` is used with a context manager, this will happen automatically.
|
||||
Otherwise, it should be called explicitly.
|
||||
|
||||
@@ -167,7 +167,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
return self._persist_directory / (collection_name + _collection_file_extensions[file_type])
|
||||
|
||||
async def create_collection_async(
|
||||
async def create_collection(
|
||||
self,
|
||||
collection_name: str,
|
||||
ndim: int = 0,
|
||||
@@ -273,7 +273,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
return collections
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""Get list of existing collections.
|
||||
|
||||
Returns:
|
||||
@@ -281,24 +281,24 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return list(self._collections.keys())
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
collection_name = collection_name.lower()
|
||||
collection = self._collections.pop(collection_name, None)
|
||||
if collection:
|
||||
collection.embeddings_index.reset()
|
||||
return None
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
collection_name = collection_name.lower()
|
||||
return collection_name in self._collections
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upsert single MemoryRecord and return its ID."""
|
||||
collection_name = collection_name.lower()
|
||||
res = await self.upsert_batch_async(collection_name=collection_name, records=[record])
|
||||
res = await self.upsert_batch(collection_name=collection_name, records=[record])
|
||||
return res[0]
|
||||
|
||||
async def upsert_batch_async(
|
||||
async def upsert_batch(
|
||||
self,
|
||||
collection_name: str,
|
||||
records: List[MemoryRecord],
|
||||
@@ -364,7 +364,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
return all_records_id
|
||||
|
||||
async def get_async(
|
||||
async def get(
|
||||
self,
|
||||
collection_name: str,
|
||||
key: str,
|
||||
@@ -373,7 +373,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
) -> MemoryRecord:
|
||||
"""Retrieve a single MemoryRecord using its key."""
|
||||
collection_name = collection_name.lower()
|
||||
result = await self.get_batch_async(
|
||||
result = await self.get_batch(
|
||||
collection_name=collection_name,
|
||||
keys=[key],
|
||||
with_embeddings=with_embedding,
|
||||
@@ -383,7 +383,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
raise KeyError(f"Key '{key}' not found in collection '{collection_name}'")
|
||||
return result[0]
|
||||
|
||||
async def get_batch_async(
|
||||
async def get_batch(
|
||||
self,
|
||||
collection_name: str,
|
||||
keys: List[str],
|
||||
@@ -403,13 +403,13 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
return pyarrow_table_to_memoryrecords(ucollection.embeddings_data_table.take(pa.array(labels)), vectors)
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Remove a single MemoryRecord using its key."""
|
||||
collection_name = collection_name.lower()
|
||||
await self.remove_batch_async(collection_name=collection_name, keys=[key])
|
||||
await self.remove_batch(collection_name=collection_name, keys=[key])
|
||||
return None
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Remove a batch of MemoryRecords using their keys."""
|
||||
collection_name = collection_name.lower()
|
||||
if collection_name not in self._collections:
|
||||
@@ -424,7 +424,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
return None
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -451,7 +451,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
Tuple[MemoryRecord, float]: The nearest matching record and its relevance score.
|
||||
"""
|
||||
collection_name = collection_name.lower()
|
||||
results = await self.get_nearest_matches_async(
|
||||
results = await self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
limit=1,
|
||||
@@ -461,7 +461,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
)
|
||||
return results[0]
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -572,7 +572,7 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
|
||||
return None
|
||||
|
||||
async def close_async(self) -> None:
|
||||
async def close(self) -> None:
|
||||
"""Persist collection, clear.
|
||||
|
||||
Returns:
|
||||
@@ -581,6 +581,6 @@ class USearchMemoryStore(MemoryStoreBase):
|
||||
if self._persist_directory:
|
||||
self._dump_collections()
|
||||
|
||||
for collection_name in await self.get_collections_async():
|
||||
await self.delete_collection_async(collection_name)
|
||||
for collection_name in await self.get_collections():
|
||||
await self.delete_collection(collection_name)
|
||||
self._collections = {}
|
||||
|
||||
@@ -134,23 +134,23 @@ class WeaviateMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
raise ValueError("Weaviate config must have either url or use_embed set")
|
||||
|
||||
async def create_collection_async(self, collection_name: str) -> None:
|
||||
async def create_collection(self, collection_name: str) -> None:
|
||||
schema = SCHEMA.copy()
|
||||
schema["class"] = collection_name
|
||||
await asyncio.get_running_loop().run_in_executor(None, self.client.schema.create_class, schema)
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
schemas = await asyncio.get_running_loop().run_in_executor(None, self.client.schema.get)
|
||||
return [schema["class"] for schema in schemas["classes"]]
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> bool:
|
||||
async def delete_collection(self, collection_name: str) -> bool:
|
||||
await asyncio.get_running_loop().run_in_executor(None, self.client.schema.delete_class, collection_name)
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
collections = await self.get_collections_async()
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
collections = await self.get_collections()
|
||||
return collection_name in collections
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
weaviate_record = self.FieldMapper.sk_to_weaviate(vars(record))
|
||||
|
||||
vector = weaviate_record.pop("vector", None)
|
||||
@@ -165,7 +165,7 @@ class WeaviateMemoryStore(MemoryStoreBase):
|
||||
vector,
|
||||
)
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
def _upsert_batch_inner():
|
||||
results = []
|
||||
with self.client.batch as batch:
|
||||
@@ -185,12 +185,12 @@ class WeaviateMemoryStore(MemoryStoreBase):
|
||||
|
||||
return await asyncio.get_running_loop().run_in_executor(None, _upsert_batch_inner)
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
# Call the batched version with a single key
|
||||
results = await self.get_batch_async(collection_name, [key], with_embedding)
|
||||
results = await self.get_batch(collection_name, [key], with_embedding)
|
||||
return results[0] if results else None
|
||||
|
||||
async def get_batch_async(self, collection_name: str, keys: List[str], with_embedding: bool) -> List[MemoryRecord]:
|
||||
async def get_batch(self, collection_name: str, keys: List[str], with_embedding: bool) -> List[MemoryRecord]:
|
||||
queries = self._build_multi_get_query(collection_name, keys, with_embedding)
|
||||
|
||||
results = await asyncio.get_running_loop().run_in_executor(None, self.client.query.multi_get(queries).do)
|
||||
@@ -230,10 +230,10 @@ class WeaviateMemoryStore(MemoryStoreBase):
|
||||
mem_vals = self.FieldMapper.remove_underscore_prefix(sk_doc)
|
||||
return MemoryRecord(**mem_vals)
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
await self.remove_batch_async(collection_name, [key])
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
await self.remove_batch(collection_name, [key])
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
# TODO: Use In operator when it's available
|
||||
# (https://github.com/weaviate/weaviate/issues/2387)
|
||||
# and handle max delete objects
|
||||
@@ -249,7 +249,7 @@ class WeaviateMemoryStore(MemoryStoreBase):
|
||||
None, self.client.batch.delete_objects, collection_name, where
|
||||
)
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: np.ndarray,
|
||||
@@ -289,14 +289,14 @@ class WeaviateMemoryStore(MemoryStoreBase):
|
||||
|
||||
return memory_records_and_scores
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: np.ndarray,
|
||||
min_relevance_score: float,
|
||||
with_embedding: bool,
|
||||
) -> Tuple[MemoryRecord, float]:
|
||||
results = await self.get_nearest_matches_async(
|
||||
results = await self.get_nearest_matches(
|
||||
collection_name,
|
||||
embedding,
|
||||
limit=1,
|
||||
|
||||
@@ -26,7 +26,7 @@ class BingConnector(ConnectorBase):
|
||||
if not self._api_key:
|
||||
raise ValueError("Bing API key cannot be null. Please set environment variable BING_API_KEY.")
|
||||
|
||||
async def search_async(self, query: str, num_results: str, offset: str) -> List[str]:
|
||||
async def search(self, query: str, num_results: str, offset: str) -> List[str]:
|
||||
"""
|
||||
Returns the search results of the query provided by pinging the Bing web search API.
|
||||
Returns `num_results` results and ignores the first `offset`.
|
||||
|
||||
@@ -8,5 +8,5 @@ class ConnectorBase:
|
||||
Base class for search engine connectors
|
||||
"""
|
||||
|
||||
def search_async(self, query: str, num_results: str, offset: str) -> List[str]:
|
||||
def search(self, query: str, num_results: str, offset: str) -> List[str]:
|
||||
pass
|
||||
|
||||
@@ -31,7 +31,7 @@ class GoogleConnector(ConnectorBase):
|
||||
if not self._search_engine_id:
|
||||
raise ValueError("Google search engine ID cannot be null.")
|
||||
|
||||
async def search_async(self, query: str, num_results: str, offset: str) -> List[str]:
|
||||
async def search(self, query: str, num_results: str, offset: str) -> List[str]:
|
||||
"""
|
||||
Returns the search results of the query provided by pinging the Google Custom search API.
|
||||
Returns `num_results` results and ignores the first `offset`.
|
||||
|
||||
@@ -41,7 +41,7 @@ class ConversationSummaryPlugin:
|
||||
name="SummarizeConversation",
|
||||
input_description="A long conversation transcript.",
|
||||
)
|
||||
async def summarize_conversation_async(self, input: str, context: "KernelContext") -> "KernelContext":
|
||||
async def summarize_conversation(self, input: str, context: "KernelContext") -> "KernelContext":
|
||||
"""
|
||||
Given a long conversation transcript, summarize the conversation.
|
||||
|
||||
@@ -51,10 +51,10 @@ class ConversationSummaryPlugin:
|
||||
"""
|
||||
from semantic_kernel.text import text_chunker
|
||||
from semantic_kernel.text.function_extension import (
|
||||
aggregate_chunked_results_async,
|
||||
aggregate_chunked_results,
|
||||
)
|
||||
|
||||
lines = text_chunker._split_text_lines(input, ConversationSummaryPlugin._max_tokens, True)
|
||||
paragraphs = text_chunker._split_text_paragraph(lines, ConversationSummaryPlugin._max_tokens)
|
||||
|
||||
return await aggregate_chunked_results_async(self._summarizeConversationFunction, paragraphs, context)
|
||||
return await aggregate_chunked_results(self._summarizeConversationFunction, paragraphs, context)
|
||||
|
||||
@@ -30,7 +30,7 @@ class FileIOPlugin(KernelBaseModel):
|
||||
name="readAsync",
|
||||
input_description="Path of the source file",
|
||||
)
|
||||
async def read_async(self, path: str) -> str:
|
||||
async def read(self, path: str) -> str:
|
||||
"""
|
||||
Read a file
|
||||
|
||||
@@ -55,7 +55,7 @@ class FileIOPlugin(KernelBaseModel):
|
||||
)
|
||||
@kernel_function_context_parameter(name="path", description="Destination path")
|
||||
@kernel_function_context_parameter(name="content", description="File content")
|
||||
async def write_async(self, context: "KernelContext") -> None:
|
||||
async def write(self, context: "KernelContext") -> None:
|
||||
"""
|
||||
Write a file
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class HttpPlugin(KernelBaseModel):
|
||||
"""
|
||||
|
||||
@kernel_function(description="Makes a GET request to a uri", name="getAsync")
|
||||
async def get_async(self, url: str) -> str:
|
||||
async def get(self, url: str) -> str:
|
||||
"""
|
||||
Sends an HTTP GET request to the specified URI and returns
|
||||
the response body as a string.
|
||||
@@ -46,7 +46,7 @@ class HttpPlugin(KernelBaseModel):
|
||||
|
||||
@kernel_function(description="Makes a POST request to a uri", name="postAsync")
|
||||
@kernel_function_context_parameter(name="body", description="The body of the request")
|
||||
async def post_async(self, url: str, context: "KernelContext") -> str:
|
||||
async def post(self, url: str, context: "KernelContext") -> str:
|
||||
"""
|
||||
Sends an HTTP POST request to the specified URI and returns
|
||||
the response body as a string.
|
||||
@@ -69,7 +69,7 @@ class HttpPlugin(KernelBaseModel):
|
||||
|
||||
@kernel_function(description="Makes a PUT request to a uri", name="putAsync")
|
||||
@kernel_function_context_parameter(name="body", description="The body of the request")
|
||||
async def put_async(self, url: str, context: "KernelContext") -> str:
|
||||
async def put(self, url: str, context: "KernelContext") -> str:
|
||||
"""
|
||||
Sends an HTTP PUT request to the specified URI and returns
|
||||
the response body as a string.
|
||||
@@ -90,7 +90,7 @@ class HttpPlugin(KernelBaseModel):
|
||||
return await response.text()
|
||||
|
||||
@kernel_function(description="Makes a DELETE request to a uri", name="deleteAsync")
|
||||
async def delete_async(self, url: str) -> str:
|
||||
async def delete(self, url: str) -> str:
|
||||
"""
|
||||
Sends an HTTP DELETE request to the specified URI and returns
|
||||
the response body as a string.
|
||||
|
||||
@@ -43,7 +43,7 @@ class TextMemoryPlugin(KernelBaseModel):
|
||||
description="The maximum number of relevant memories to recall.",
|
||||
default_value=DEFAULT_LIMIT,
|
||||
)
|
||||
async def recall_async(self, ask: str, context: "KernelContext") -> str:
|
||||
async def recall(self, ask: str, context: "KernelContext") -> str:
|
||||
"""
|
||||
Recall a fact from the long term memory.
|
||||
|
||||
@@ -78,7 +78,7 @@ class TextMemoryPlugin(KernelBaseModel):
|
||||
if limit is None or str(limit).strip() == "":
|
||||
raise ValueError("Limit value not defined for TextMemoryPlugin")
|
||||
|
||||
results = await context.memory.search_async(
|
||||
results = await context.memory.search(
|
||||
collection=collection,
|
||||
query=ask,
|
||||
limit=int(limit),
|
||||
@@ -104,7 +104,7 @@ class TextMemoryPlugin(KernelBaseModel):
|
||||
name=KEY_PARAM,
|
||||
description="The unique key to associate with the information",
|
||||
)
|
||||
async def save_async(self, text: str, context: "KernelContext") -> None:
|
||||
async def save(self, text: str, context: "KernelContext") -> None:
|
||||
"""
|
||||
Save a fact to the long term memory.
|
||||
|
||||
@@ -132,4 +132,4 @@ class TextMemoryPlugin(KernelBaseModel):
|
||||
if not key:
|
||||
raise ValueError("Memory key not defined for TextMemoryPlugin")
|
||||
|
||||
await context.memory.save_information_async(collection, text=text, id=key)
|
||||
await context.memory.save_information(collection, text=text, id=key)
|
||||
|
||||
@@ -38,7 +38,7 @@ class WebSearchEnginePlugin:
|
||||
description="The number of search results to skip",
|
||||
default_value="0",
|
||||
)
|
||||
async def search_async(self, query: str, context: "KernelContext") -> str:
|
||||
async def search(self, query: str, context: "KernelContext") -> str:
|
||||
"""
|
||||
Returns the search results of the query provided.
|
||||
Returns `num_results` results and ignores the first `offset`.
|
||||
@@ -50,5 +50,5 @@ class WebSearchEnginePlugin:
|
||||
|
||||
_num_results = context.variables.get("num_results")
|
||||
_offset = context.variables.get("offset")
|
||||
result = await self._connector.search_async(query, _num_results, _offset)
|
||||
result = await self._connector.search(query, _num_results, _offset)
|
||||
return str(result)
|
||||
|
||||
@@ -155,7 +155,7 @@ class Kernel:
|
||||
|
||||
return function
|
||||
|
||||
async def run_stream_async(
|
||||
async def run_stream(
|
||||
self,
|
||||
*functions: Any,
|
||||
input_context: Optional[KernelContext] = None,
|
||||
@@ -167,12 +167,12 @@ class Kernel:
|
||||
stream_function = functions[-1]
|
||||
|
||||
# run pipeline functions
|
||||
context = await self.run_async(pipeline_functions, input_context, input_vars, input_str)
|
||||
context = await self.run(pipeline_functions, input_context, input_vars, input_str)
|
||||
|
||||
elif len(functions) == 1:
|
||||
stream_function = functions[0]
|
||||
|
||||
# TODO: Preparing context for function invoke can be refactored as code below are same as run_async
|
||||
# TODO: Preparing context for function invoke can be refactored as code below are same as run
|
||||
# if the user passed in a context, prioritize it, but merge with any other inputs
|
||||
if input_context is not None:
|
||||
context = input_context
|
||||
@@ -205,7 +205,7 @@ class Kernel:
|
||||
raise ValueError("No functions passed to run")
|
||||
|
||||
try:
|
||||
async for stream_message in stream_function.invoke_stream_async(input=None, context=context):
|
||||
async for stream_message in stream_function.invoke_stream(input=None, context=context):
|
||||
yield stream_message
|
||||
|
||||
except Exception as ex:
|
||||
@@ -220,7 +220,7 @@ class Kernel:
|
||||
"Error occurred while invoking stream function",
|
||||
)
|
||||
|
||||
async def run_async(
|
||||
async def run(
|
||||
self,
|
||||
*functions: Any,
|
||||
input_context: Optional[KernelContext] = None,
|
||||
|
||||
@@ -13,14 +13,14 @@ class MemoryStoreBase(ABC):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *args):
|
||||
await self.close_async()
|
||||
await self.close()
|
||||
|
||||
async def close_async(self):
|
||||
async def close(self):
|
||||
"""Async close connection, invoked by MemoryStoreBase.__aexit__()"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def create_collection_async(self, collection_name: str) -> None:
|
||||
async def create_collection(self, collection_name: str) -> None:
|
||||
"""Creates a new collection in the data store.
|
||||
|
||||
Arguments:
|
||||
@@ -32,7 +32,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_collections_async(
|
||||
async def get_collections(
|
||||
self,
|
||||
) -> List[str]:
|
||||
"""Gets all collection names in the data store.
|
||||
@@ -43,7 +43,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection from the data store.
|
||||
|
||||
Arguments:
|
||||
@@ -55,7 +55,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Determines if a collection exists in the data store.
|
||||
|
||||
Arguments:
|
||||
@@ -68,7 +68,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upserts a memory record into the data store. Does not guarantee that the collection exists.
|
||||
If the record already exists, it will be updated.
|
||||
If the record does not exist, it will be created.
|
||||
@@ -83,7 +83,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""Upserts a group of memory records into the data store. Does not guarantee that the collection exists.
|
||||
If the record already exists, it will be updated.
|
||||
If the record does not exist, it will be created.
|
||||
@@ -98,7 +98,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool) -> MemoryRecord:
|
||||
"""Gets a memory record from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -112,7 +112,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_batch_async(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
async def get_batch(self, collection_name: str, keys: List[str], with_embeddings: bool) -> List[MemoryRecord]:
|
||||
"""Gets a batch of memory records from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -126,7 +126,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Removes a memory record from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -139,7 +139,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Removes a batch of memory records from the data store. Does not guarantee that the collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -152,7 +152,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -176,7 +176,7 @@ class MemoryStoreBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
|
||||
@@ -7,7 +7,7 @@ from semantic_kernel.memory.semantic_text_memory_base import SemanticTextMemoryB
|
||||
|
||||
|
||||
class NullMemory(SemanticTextMemoryBase):
|
||||
async def save_information_async(
|
||||
async def save_information(
|
||||
self,
|
||||
collection: str,
|
||||
text: str,
|
||||
@@ -15,10 +15,10 @@ class NullMemory(SemanticTextMemoryBase):
|
||||
description: Optional[str] = None,
|
||||
additional_metadata: Optional[str] = None,
|
||||
) -> None:
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.save_information_async()"""
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.save_information()"""
|
||||
return None
|
||||
|
||||
async def save_reference_async(
|
||||
async def save_reference(
|
||||
self,
|
||||
collection: str,
|
||||
text: str,
|
||||
@@ -27,25 +27,25 @@ class NullMemory(SemanticTextMemoryBase):
|
||||
description: Optional[str] = None,
|
||||
additional_metadata: Optional[str] = None,
|
||||
) -> None:
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.save_reference_async()"""
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.save_reference()"""
|
||||
return None
|
||||
|
||||
async def get_async(self, collection: str, query: str) -> Optional[MemoryQueryResult]:
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.get_async()"""
|
||||
async def get(self, collection: str, query: str) -> Optional[MemoryQueryResult]:
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.get()"""
|
||||
return None
|
||||
|
||||
async def search_async(
|
||||
async def search(
|
||||
self,
|
||||
collection: str,
|
||||
query: str,
|
||||
limit: int = 1,
|
||||
min_relevance_score: float = 0.7,
|
||||
) -> List[MemoryQueryResult]:
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.search_async()"""
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.search()"""
|
||||
return []
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.get_collections_async()"""
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""Nullifies behavior of SemanticTextMemoryBase.get_collections()"""
|
||||
return []
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class SemanticTextMemory(SemanticTextMemoryBase):
|
||||
self._storage = storage
|
||||
self._embeddings_generator = embeddings_generator
|
||||
|
||||
async def save_information_async(
|
||||
async def save_information(
|
||||
self,
|
||||
collection: str,
|
||||
text: str,
|
||||
@@ -52,10 +52,10 @@ class SemanticTextMemory(SemanticTextMemoryBase):
|
||||
None -- None.
|
||||
"""
|
||||
# TODO: not the best place to create collection, but will address this behavior together with .NET SK
|
||||
if not await self._storage.does_collection_exist_async(collection_name=collection):
|
||||
await self._storage.create_collection_async(collection_name=collection)
|
||||
if not await self._storage.does_collection_exist(collection_name=collection):
|
||||
await self._storage.create_collection(collection_name=collection)
|
||||
|
||||
embedding = (await self._embeddings_generator.generate_embeddings_async([text]))[0]
|
||||
embedding = (await self._embeddings_generator.generate_embeddings([text]))[0]
|
||||
data = MemoryRecord.local_record(
|
||||
id=id,
|
||||
text=text,
|
||||
@@ -64,9 +64,9 @@ class SemanticTextMemory(SemanticTextMemoryBase):
|
||||
embedding=embedding,
|
||||
)
|
||||
|
||||
await self._storage.upsert_async(collection_name=collection, record=data)
|
||||
await self._storage.upsert(collection_name=collection, record=data)
|
||||
|
||||
async def save_reference_async(
|
||||
async def save_reference(
|
||||
self,
|
||||
collection: str,
|
||||
text: str,
|
||||
@@ -88,10 +88,10 @@ class SemanticTextMemory(SemanticTextMemoryBase):
|
||||
None -- None.
|
||||
"""
|
||||
# TODO: not the best place to create collection, but will address this behavior together with .NET SK
|
||||
if not await self._storage.does_collection_exist_async(collection_name=collection):
|
||||
await self._storage.create_collection_async(collection_name=collection)
|
||||
if not await self._storage.does_collection_exist(collection_name=collection):
|
||||
await self._storage.create_collection(collection_name=collection)
|
||||
|
||||
embedding = (await self._embeddings_generator.generate_embeddings_async([text]))[0]
|
||||
embedding = (await self._embeddings_generator.generate_embeddings([text]))[0]
|
||||
data = MemoryRecord.reference_record(
|
||||
external_id=external_id,
|
||||
source_name=external_source_name,
|
||||
@@ -100,9 +100,9 @@ class SemanticTextMemory(SemanticTextMemoryBase):
|
||||
embedding=embedding,
|
||||
)
|
||||
|
||||
await self._storage.upsert_async(collection_name=collection, record=data)
|
||||
await self._storage.upsert(collection_name=collection, record=data)
|
||||
|
||||
async def get_async(
|
||||
async def get(
|
||||
self,
|
||||
collection: str,
|
||||
key: str,
|
||||
@@ -116,10 +116,10 @@ class SemanticTextMemory(SemanticTextMemoryBase):
|
||||
Returns:
|
||||
Optional[MemoryQueryResult] -- The MemoryQueryResult if found, None otherwise.
|
||||
"""
|
||||
record = await self._storage.get_async(collection_name=collection, key=key)
|
||||
record = await self._storage.get(collection_name=collection, key=key)
|
||||
return MemoryQueryResult.from_memory_record(record, 1.0) if record else None
|
||||
|
||||
async def search_async(
|
||||
async def search(
|
||||
self,
|
||||
collection: str,
|
||||
query: str,
|
||||
@@ -139,8 +139,8 @@ class SemanticTextMemory(SemanticTextMemoryBase):
|
||||
Returns:
|
||||
List[MemoryQueryResult] -- The list of MemoryQueryResult found.
|
||||
"""
|
||||
query_embedding = (await self._embeddings_generator.generate_embeddings_async([query]))[0]
|
||||
results = await self._storage.get_nearest_matches_async(
|
||||
query_embedding = (await self._embeddings_generator.generate_embeddings([query]))[0]
|
||||
results = await self._storage.get_nearest_matches(
|
||||
collection_name=collection,
|
||||
embedding=query_embedding,
|
||||
limit=limit,
|
||||
@@ -150,10 +150,10 @@ class SemanticTextMemory(SemanticTextMemoryBase):
|
||||
|
||||
return [MemoryQueryResult.from_memory_record(r[0], r[1]) for r in results]
|
||||
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""Get the list of collections in the memory (calls the memory store's get_collections method).
|
||||
|
||||
Returns:
|
||||
List[str] -- The list of all the memory collection names.
|
||||
"""
|
||||
return await self._storage.get_collections_async()
|
||||
return await self._storage.get_collections()
|
||||
|
||||
@@ -11,7 +11,7 @@ SemanticTextMemoryT = TypeVar("SemanticTextMemoryT", bound="SemanticTextMemoryBa
|
||||
|
||||
class SemanticTextMemoryBase(KernelBaseModel):
|
||||
@abstractmethod
|
||||
async def save_information_async(
|
||||
async def save_information(
|
||||
self,
|
||||
collection: str,
|
||||
text: str,
|
||||
@@ -34,7 +34,7 @@ class SemanticTextMemoryBase(KernelBaseModel):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def save_reference_async(
|
||||
async def save_reference(
|
||||
self,
|
||||
collection: str,
|
||||
text: str,
|
||||
@@ -58,7 +58,7 @@ class SemanticTextMemoryBase(KernelBaseModel):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_async(
|
||||
async def get(
|
||||
self,
|
||||
collection: str,
|
||||
query: str,
|
||||
@@ -76,7 +76,7 @@ class SemanticTextMemoryBase(KernelBaseModel):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def search_async(
|
||||
async def search(
|
||||
self,
|
||||
collection: str,
|
||||
query: str,
|
||||
@@ -99,7 +99,7 @@ class SemanticTextMemoryBase(KernelBaseModel):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_collections_async(self) -> List[str]:
|
||||
async def get_collections(self) -> List[str]:
|
||||
"""Get the list of collections in the memory (calls the memory store's get_collections method).
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -21,7 +21,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
logger.warning("The `logger` parameter is deprecated. Please use the `logging` module instead.")
|
||||
self._store = {}
|
||||
|
||||
async def create_collection_async(self, collection_name: str) -> None:
|
||||
async def create_collection(self, collection_name: str) -> None:
|
||||
"""Creates a new collection if it does not exist.
|
||||
|
||||
Arguments:
|
||||
@@ -35,7 +35,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
else:
|
||||
self._store[collection_name] = {}
|
||||
|
||||
async def get_collections_async(
|
||||
async def get_collections(
|
||||
self,
|
||||
) -> List[str]:
|
||||
"""Gets the list of collections.
|
||||
@@ -45,7 +45,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return list(self._store.keys())
|
||||
|
||||
async def delete_collection_async(self, collection_name: str) -> None:
|
||||
async def delete_collection(self, collection_name: str) -> None:
|
||||
"""Deletes a collection.
|
||||
|
||||
Arguments:
|
||||
@@ -57,7 +57,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
if collection_name in self._store:
|
||||
del self._store[collection_name]
|
||||
|
||||
async def does_collection_exist_async(self, collection_name: str) -> bool:
|
||||
async def does_collection_exist(self, collection_name: str) -> bool:
|
||||
"""Checks if a collection exists.
|
||||
|
||||
Arguments:
|
||||
@@ -68,7 +68,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
"""
|
||||
return collection_name in self._store
|
||||
|
||||
async def upsert_async(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
|
||||
"""Upserts a record.
|
||||
|
||||
Arguments:
|
||||
@@ -85,7 +85,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
self._store[collection_name][record._key] = record
|
||||
return record._key
|
||||
|
||||
async def upsert_batch_async(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
async def upsert_batch(self, collection_name: str, records: List[MemoryRecord]) -> List[str]:
|
||||
"""Upserts a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -103,7 +103,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
self._store[collection_name][record._key] = record
|
||||
return [record._key for record in records]
|
||||
|
||||
async def get_async(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
async def get(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord:
|
||||
"""Gets a record.
|
||||
|
||||
Arguments:
|
||||
@@ -128,7 +128,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
result._embedding = None
|
||||
return result
|
||||
|
||||
async def get_batch_async(
|
||||
async def get_batch(
|
||||
self, collection_name: str, keys: List[str], with_embeddings: bool = False
|
||||
) -> List[MemoryRecord]:
|
||||
"""Gets a batch of records.
|
||||
@@ -153,7 +153,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
result._embedding = None
|
||||
return results
|
||||
|
||||
async def remove_async(self, collection_name: str, key: str) -> None:
|
||||
async def remove(self, collection_name: str, key: str) -> None:
|
||||
"""Removes a record.
|
||||
|
||||
Arguments:
|
||||
@@ -171,7 +171,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
|
||||
del self._store[collection_name][key]
|
||||
|
||||
async def remove_batch_async(self, collection_name: str, keys: List[str]) -> None:
|
||||
async def remove_batch(self, collection_name: str, keys: List[str]) -> None:
|
||||
"""Removes a batch of records.
|
||||
|
||||
Arguments:
|
||||
@@ -188,7 +188,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
if key in self._store[collection_name]:
|
||||
del self._store[collection_name][key]
|
||||
|
||||
async def get_nearest_match_async(
|
||||
async def get_nearest_match(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
@@ -206,7 +206,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
Returns:
|
||||
Tuple[MemoryRecord, float] -- The record and the relevance score.
|
||||
"""
|
||||
return self.get_nearest_matches_async(
|
||||
return self.get_nearest_matches(
|
||||
collection_name=collection_name,
|
||||
embedding=embedding,
|
||||
limit=1,
|
||||
@@ -214,7 +214,7 @@ class VolatileMemoryStore(MemoryStoreBase):
|
||||
with_embeddings=with_embedding,
|
||||
)
|
||||
|
||||
async def get_nearest_matches_async(
|
||||
async def get_nearest_matches(
|
||||
self,
|
||||
collection_name: str,
|
||||
embedding: ndarray,
|
||||
|
||||
@@ -22,7 +22,7 @@ class ChatMessage(KernelBaseModel):
|
||||
"""Return the content of the message."""
|
||||
return self.fixed_content
|
||||
|
||||
async def render_message_async(self, context: "KernelContext") -> None:
|
||||
async def render_message(self, context: "KernelContext") -> None:
|
||||
"""Render the message.
|
||||
The first time this is called for a given message,
|
||||
it will render the message with the context at that time.
|
||||
@@ -30,10 +30,10 @@ class ChatMessage(KernelBaseModel):
|
||||
"""
|
||||
if self.fixed_content is None:
|
||||
if self.content_template is not None:
|
||||
self.fixed_content = await self.content_template.render_async(context)
|
||||
self.fixed_content = await self.content_template.render(context)
|
||||
|
||||
def as_dict(self) -> Dict[str, str]:
|
||||
"""Return the message as a dict.
|
||||
Make sure to call render_message_async first to embed the context in the content.
|
||||
Make sure to call render_message first to embed the context in the content.
|
||||
"""
|
||||
return self.model_dump(exclude_none=True, by_alias=True, exclude={"content_template"})
|
||||
|
||||
@@ -19,7 +19,7 @@ def _infers(delegate_type):
|
||||
def _is_annotation_of_type(annotation, type_to_match) -> bool:
|
||||
return (annotation is type_to_match) or (
|
||||
# Handle cases where the annotation is provided as a string to avoid circular imports
|
||||
# for example: `async def read_async(self, context: "KernelContext"):` in file_io_plugin.py
|
||||
# for example: `async def read(self, context: "KernelContext"):` in file_io_plugin.py
|
||||
isinstance(annotation, str)
|
||||
and annotation == type_to_match.__name__
|
||||
)
|
||||
|
||||
@@ -127,8 +127,8 @@ class KernelFunction(KernelFunctionBase):
|
||||
|
||||
try:
|
||||
if not function_config.has_chat_prompt:
|
||||
prompt = await function_config.prompt_template.render_async(context)
|
||||
completion = await client.complete_async(prompt, request_settings)
|
||||
prompt = await function_config.prompt_template.render(context)
|
||||
completion = await client.complete(prompt, request_settings)
|
||||
context.variables.update(completion)
|
||||
return context
|
||||
except Exception as e:
|
||||
@@ -139,9 +139,9 @@ class KernelFunction(KernelFunctionBase):
|
||||
as_chat_prompt = function_config.prompt_template
|
||||
# Similar to non-chat, render prompt (which renders to a
|
||||
# dict of <role, content, name> messages)
|
||||
messages = await as_chat_prompt.render_messages_async(context)
|
||||
messages = await as_chat_prompt.render_messages(context)
|
||||
try:
|
||||
result = await client.complete_chat_async(messages, request_settings)
|
||||
result = await client.complete_chat(messages, request_settings)
|
||||
if isinstance(result, list):
|
||||
# TODO: handle multiple completions
|
||||
result = result[0]
|
||||
@@ -176,8 +176,8 @@ class KernelFunction(KernelFunctionBase):
|
||||
# Similar to non-chat, render prompt (which renders to a
|
||||
# list of <role, content> messages)
|
||||
completion = ""
|
||||
messages = await chat_prompt.render_messages_async(context)
|
||||
async for partial_content in client.complete_chat_stream_async(
|
||||
messages = await chat_prompt.render_messages(context)
|
||||
async for partial_content in client.complete_chat_stream(
|
||||
messages=messages, settings=request_settings
|
||||
):
|
||||
if isinstance(partial_content, str):
|
||||
@@ -196,10 +196,10 @@ class KernelFunction(KernelFunctionBase):
|
||||
chat_prompt.add_assistant_message(completion)
|
||||
context.variables.update(completion)
|
||||
else:
|
||||
prompt = await function_config.prompt_template.render_async(context)
|
||||
prompt = await function_config.prompt_template.render(context)
|
||||
|
||||
completion = ""
|
||||
async for partial_content in client.complete_stream_async(prompt, request_settings):
|
||||
async for partial_content in client.complete_stream(prompt, request_settings):
|
||||
completion += partial_content
|
||||
yield partial_content
|
||||
context.variables.update(completion)
|
||||
@@ -375,16 +375,16 @@ class KernelFunction(KernelFunctionBase):
|
||||
|
||||
def run_coroutine():
|
||||
if self.is_semantic:
|
||||
return self._invoke_semantic_async(context, settings)
|
||||
return self._invoke_semantic(context, settings)
|
||||
else:
|
||||
return self._invoke_native_async(context)
|
||||
return self._invoke_native(context)
|
||||
|
||||
return self.run_async_in_executor(run_coroutine)
|
||||
else:
|
||||
if self.is_semantic:
|
||||
return asyncio.run(self._invoke_semantic_async(context, settings))
|
||||
return asyncio.run(self._invoke_semantic(context, settings))
|
||||
else:
|
||||
return asyncio.run(self._invoke_native_async(context))
|
||||
return asyncio.run(self._invoke_native(context))
|
||||
|
||||
async def invoke_async(
|
||||
self,
|
||||
@@ -415,21 +415,21 @@ class KernelFunction(KernelFunctionBase):
|
||||
|
||||
try:
|
||||
if self.is_semantic:
|
||||
return await self._invoke_semantic_async(context, settings, **kwargs)
|
||||
return await self._invoke_semantic(context, settings, **kwargs)
|
||||
else:
|
||||
return await self._invoke_native_async(context, **kwargs)
|
||||
return await self._invoke_native(context, **kwargs)
|
||||
except Exception as e:
|
||||
context.fail(str(e), e)
|
||||
return context
|
||||
|
||||
async def _invoke_semantic_async(self, context: "KernelContext", settings: AIRequestSettings, **kwargs):
|
||||
async def _invoke_semantic(self, context: "KernelContext", settings: AIRequestSettings, **kwargs):
|
||||
self._verify_is_semantic()
|
||||
self._ensure_context_has_plugins(context)
|
||||
new_context = await self._function(self._ai_service, settings or self._ai_request_settings, context)
|
||||
context.variables.merge_or_overwrite(new_context.variables)
|
||||
return context
|
||||
|
||||
async def _invoke_native_async(self, context):
|
||||
async def _invoke_native(self, context):
|
||||
self._verify_is_native()
|
||||
|
||||
self._ensure_context_has_plugins(context)
|
||||
@@ -462,7 +462,7 @@ class KernelFunction(KernelFunctionBase):
|
||||
"Invalid operation, the method requires a native function",
|
||||
)
|
||||
|
||||
async def invoke_stream_async(
|
||||
async def invoke_stream(
|
||||
self,
|
||||
input: Optional[str] = None,
|
||||
variables: ContextVariables = None,
|
||||
@@ -490,10 +490,10 @@ class KernelFunction(KernelFunctionBase):
|
||||
|
||||
try:
|
||||
if self.is_semantic:
|
||||
async for stream_msg in self._invoke_semantic_stream_async(context, settings):
|
||||
async for stream_msg in self._invoke_semantic_stream(context, settings):
|
||||
yield stream_msg
|
||||
else:
|
||||
async for stream_msg in self._invoke_native_stream_async(context):
|
||||
async for stream_msg in self._invoke_native_stream(context):
|
||||
yield stream_msg
|
||||
except Exception as e:
|
||||
context.fail(str(e), e)
|
||||
@@ -502,13 +502,13 @@ class KernelFunction(KernelFunctionBase):
|
||||
"Error occurred while invoking stream function",
|
||||
)
|
||||
|
||||
async def _invoke_semantic_stream_async(self, context, settings):
|
||||
async def _invoke_semantic_stream(self, context, settings):
|
||||
self._verify_is_semantic()
|
||||
self._ensure_context_has_plugins(context)
|
||||
async for stream_msg in self._stream_function(self._ai_service, settings or self._ai_request_settings, context):
|
||||
yield stream_msg
|
||||
|
||||
async def _invoke_native_stream_async(self, context):
|
||||
async def _invoke_native_stream(self, context):
|
||||
self._verify_is_native()
|
||||
|
||||
self._ensure_context_has_plugins(context)
|
||||
|
||||
@@ -75,7 +75,7 @@ class ActionPlanner:
|
||||
self._kernel = kernel
|
||||
self._context = kernel.create_new_context()
|
||||
|
||||
async def create_plan_async(self, goal: str) -> Plan:
|
||||
async def create_plan(self, goal: str) -> Plan:
|
||||
"""
|
||||
:param goal: The input to the planner based on which the plan is made
|
||||
:return: a Plan object
|
||||
|
||||
@@ -171,7 +171,7 @@ class BasicPlanner:
|
||||
|
||||
return available_functions_string
|
||||
|
||||
async def create_plan_async(
|
||||
async def create_plan(
|
||||
self,
|
||||
goal: str,
|
||||
kernel: Kernel,
|
||||
@@ -195,7 +195,7 @@ class BasicPlanner:
|
||||
generated_plan = await planner.invoke_async(variables=context)
|
||||
return Plan(prompt=prompt, goal=goal, plan=generated_plan)
|
||||
|
||||
async def execute_plan_async(self, plan: Plan, kernel: Kernel) -> str:
|
||||
async def execute_plan(self, plan: Plan, kernel: Kernel) -> str:
|
||||
"""
|
||||
Given a plan, execute each of the functions within the plan
|
||||
from start to finish and output the result.
|
||||
|
||||
@@ -289,7 +289,7 @@ class Plan(KernelFunctionBase):
|
||||
self._is_semantic = function.is_semantic
|
||||
self._request_settings = function.request_settings
|
||||
|
||||
async def run_next_step_async(
|
||||
async def run_next_step(
|
||||
self,
|
||||
kernel: Kernel,
|
||||
variables: ContextVariables,
|
||||
|
||||
@@ -77,13 +77,11 @@ class SequentialPlanner:
|
||||
function_config=function_config,
|
||||
)
|
||||
|
||||
async def create_plan_async(self, goal: str) -> Plan:
|
||||
async def create_plan(self, goal: str) -> Plan:
|
||||
if len(goal) == 0:
|
||||
raise PlanningException(PlanningException.ErrorCodes.InvalidGoal, "The goal specified is empty")
|
||||
|
||||
relevant_function_manual = await KernelContextExtension.get_functions_manual_async(
|
||||
self._context, goal, self.config
|
||||
)
|
||||
relevant_function_manual = await KernelContextExtension.get_functions_manual(self._context, goal, self.config)
|
||||
self._context.variables.set("available_functions", relevant_function_manual)
|
||||
|
||||
self._context.variables.update(goal)
|
||||
|
||||
@@ -13,7 +13,7 @@ class SequentialPlannerConfig:
|
||||
included_functions: List[str] = None,
|
||||
max_tokens: int = 1024,
|
||||
allow_missing_functions: bool = False,
|
||||
get_available_functions_async: Callable = None,
|
||||
get_available_functions: Callable = None,
|
||||
get_plugin_function: Callable = None,
|
||||
):
|
||||
self.relevancy_threshold: float = relevancy_threshold
|
||||
@@ -23,5 +23,5 @@ class SequentialPlannerConfig:
|
||||
self.included_functions: List[str] = included_functions or []
|
||||
self.max_tokens: int = max_tokens
|
||||
self.allow_missing_functions: bool = allow_missing_functions
|
||||
self.get_available_functions_async = get_available_functions_async
|
||||
self.get_available_functions = get_available_functions
|
||||
self.get_plugin_function = get_plugin_function
|
||||
|
||||
+12
-12
@@ -45,24 +45,24 @@ class SequentialPlannerKernelContextExtension:
|
||||
PLAN_KERNEL_FUNCTIONS_ARE_REMEMBERED = "Planning.KernelFunctionsAreRemembered"
|
||||
|
||||
@staticmethod
|
||||
async def get_functions_manual_async(
|
||||
async def get_functions_manual(
|
||||
context: KernelContext,
|
||||
semantic_query: str = None,
|
||||
config: SequentialPlannerConfig = None,
|
||||
) -> str:
|
||||
config = config or SequentialPlannerConfig()
|
||||
|
||||
if config.get_available_functions_async is None:
|
||||
functions = await SequentialPlannerKernelContextExtension.get_available_functions_async(
|
||||
if config.get_available_functions is None:
|
||||
functions = await SequentialPlannerKernelContextExtension.get_available_functions(
|
||||
context, config, semantic_query
|
||||
)
|
||||
else:
|
||||
functions = await config.get_available_functions_async(config, semantic_query)
|
||||
functions = await config.get_available_functions(config, semantic_query)
|
||||
|
||||
return "\n\n".join([SequentialPlannerFunctionViewExtension.to_manual_string(func) for func in functions])
|
||||
|
||||
@staticmethod
|
||||
async def get_available_functions_async(
|
||||
async def get_available_functions(
|
||||
context: KernelContext,
|
||||
config: SequentialPlannerConfig,
|
||||
semantic_query: str = None,
|
||||
@@ -97,10 +97,10 @@ class SequentialPlannerKernelContextExtension:
|
||||
return available_functions
|
||||
|
||||
# Remember functions in memory so that they can be searched.
|
||||
await SequentialPlannerKernelContextExtension.remember_functions_async(context, available_functions)
|
||||
await SequentialPlannerKernelContextExtension.remember_functions(context, available_functions)
|
||||
|
||||
# Search for functions that match the semantic query.
|
||||
memories = await context.memory.search_async(
|
||||
memories = await context.memory.search(
|
||||
SequentialPlannerKernelContextExtension.PLANNER_MEMORY_COLLECTION_NAME,
|
||||
semantic_query,
|
||||
config.max_relevant_functions,
|
||||
@@ -108,7 +108,7 @@ class SequentialPlannerKernelContextExtension:
|
||||
)
|
||||
|
||||
# Add functions that were found in the search results.
|
||||
relevant_functions = await SequentialPlannerKernelContextExtension.get_relevant_functions_async(
|
||||
relevant_functions = await SequentialPlannerKernelContextExtension.get_relevant_functions(
|
||||
context, available_functions, memories
|
||||
)
|
||||
|
||||
@@ -122,7 +122,7 @@ class SequentialPlannerKernelContextExtension:
|
||||
return sorted(relevant_functions, key=lambda x: (x.plugin_name, x.name))
|
||||
|
||||
@staticmethod
|
||||
async def get_relevant_functions_async(
|
||||
async def get_relevant_functions(
|
||||
context: KernelContext,
|
||||
available_functions: List[FunctionView],
|
||||
memories: AsyncIterable[MemoryQueryResult],
|
||||
@@ -150,7 +150,7 @@ class SequentialPlannerKernelContextExtension:
|
||||
return relevant_functions
|
||||
|
||||
@staticmethod
|
||||
async def remember_functions_async(context: KernelContext, available_functions: List[FunctionView]):
|
||||
async def remember_functions(context: KernelContext, available_functions: List[FunctionView]):
|
||||
# Check if the functions have already been saved to memory.
|
||||
if SequentialPlannerKernelContextExtension.PLAN_KERNEL_FUNCTIONS_ARE_REMEMBERED in context.variables:
|
||||
return
|
||||
@@ -162,7 +162,7 @@ class SequentialPlannerKernelContextExtension:
|
||||
text_to_embed = SequentialPlannerFunctionViewExtension.to_embedding_string(function)
|
||||
|
||||
# It'd be nice if there were a saveIfNotExists method on the memory interface
|
||||
memory_entry = await context.memory.get_async(
|
||||
memory_entry = await context.memory.get(
|
||||
collection=SequentialPlannerKernelContextExtension.PLANNER_MEMORY_COLLECTION_NAME,
|
||||
key=key,
|
||||
with_embedding=False,
|
||||
@@ -171,7 +171,7 @@ class SequentialPlannerKernelContextExtension:
|
||||
# TODO It'd be nice if the minRelevanceScore could be a parameter for each item that was saved to memory
|
||||
# As folks may want to tune their functions to be more or less relevant.
|
||||
# Memory now supports these such strategies.
|
||||
await context.memory.save_information_async(
|
||||
await context.memory.save_information(
|
||||
collection=SequentialPlannerKernelContextExtension.PLANNER_MEMORY_COLLECTION_NAME,
|
||||
text=text_to_embed,
|
||||
id=key,
|
||||
|
||||
@@ -120,7 +120,7 @@ class StepwisePlanner:
|
||||
@kernel_function(name="ExecutePlan", description="Execute a plan")
|
||||
@kernel_function_context_parameter(name="question", description="The question to answer")
|
||||
@kernel_function_context_parameter(name="function_descriptions", description="List of tool descriptions")
|
||||
async def execute_plan_async(self, context: KernelContext) -> KernelContext:
|
||||
async def execute_plan(self, context: KernelContext) -> KernelContext:
|
||||
question = context["question"]
|
||||
|
||||
steps_taken: List[SystemStep] = []
|
||||
@@ -167,7 +167,7 @@ class StepwisePlanner:
|
||||
|
||||
try:
|
||||
await asyncio.sleep(self.config.min_iteration_time_ms / 1000)
|
||||
result = await self.invoke_action_async(next_step.action, next_step.action_variables)
|
||||
result = await self.invoke_action(next_step.action, next_step.action_variables)
|
||||
|
||||
if is_null_or_empty(result):
|
||||
next_step.observation = "Got no result from action"
|
||||
@@ -296,7 +296,7 @@ class StepwisePlanner:
|
||||
|
||||
return scratch_pad
|
||||
|
||||
async def invoke_action_async(self, action_name: str, action_variables: Dict[str, str]) -> str:
|
||||
async def invoke_action(self, action_name: str, action_variables: Dict[str, str]) -> str:
|
||||
available_functions = self.get_available_functions()
|
||||
target_function = next(
|
||||
(f for f in available_functions if self.to_fully_qualified_name(f) == action_name),
|
||||
|
||||
@@ -14,9 +14,7 @@ logger: logging.Logger = logging.getLogger(__name__)
|
||||
class PassThroughWithoutRetry(RetryMechanismBase, KernelBaseModel):
|
||||
"""A retry mechanism that does not retry."""
|
||||
|
||||
async def execute_with_retry_async(
|
||||
self, action: Callable[[], Awaitable[T]], log: Optional[Any] = None
|
||||
) -> Awaitable[T]:
|
||||
async def execute_with_retry(self, action: Callable[[], Awaitable[T]], log: Optional[Any] = None) -> Awaitable[T]:
|
||||
"""Executes the given action with retry logic.
|
||||
|
||||
Arguments:
|
||||
|
||||
@@ -11,9 +11,7 @@ logger: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
class RetryMechanismBase(ABC):
|
||||
@abstractmethod
|
||||
async def execute_with_retry_async(
|
||||
self, action: Callable[[], Awaitable[T]], log: Optional[Any] = None
|
||||
) -> Awaitable[T]:
|
||||
async def execute_with_retry(self, action: Callable[[], Awaitable[T]], log: Optional[Any] = None) -> Awaitable[T]:
|
||||
"""Executes the given action with retry logic.
|
||||
|
||||
Arguments:
|
||||
|
||||
@@ -69,10 +69,8 @@ class ChatPromptTemplate(PromptTemplate, Generic[ChatMessageT]):
|
||||
for message in self.prompt_config.execution_settings.messages:
|
||||
self.add_message(**message)
|
||||
|
||||
async def render_async(self, context: "KernelContext") -> str:
|
||||
raise NotImplementedError(
|
||||
"Can't call render_async on a ChatPromptTemplate.\n" "Use render_messages_async instead."
|
||||
)
|
||||
async def render(self, context: "KernelContext") -> str:
|
||||
raise NotImplementedError("Can't call render on a ChatPromptTemplate.\n" "Use render_messages instead.")
|
||||
|
||||
def add_system_message(self, message: str) -> None:
|
||||
"""Add a system message to the chat template."""
|
||||
@@ -109,14 +107,14 @@ class ChatPromptTemplate(PromptTemplate, Generic[ChatMessageT]):
|
||||
)
|
||||
)
|
||||
|
||||
async def render_messages_async(self, context: "KernelContext") -> List[Dict[str, str]]:
|
||||
async def render_messages(self, context: "KernelContext") -> List[Dict[str, str]]:
|
||||
"""Render the content of the message in the chat template, based on the context."""
|
||||
if len(self.messages) == 0 or self.messages[-1].role in [
|
||||
"assistant",
|
||||
"system",
|
||||
]:
|
||||
self.add_user_message(message=self.template)
|
||||
await asyncio.gather(*[message.render_message_async(context) for message in self.messages])
|
||||
await asyncio.gather(*[message.render_message(context) for message in self.messages])
|
||||
return [message.as_dict() for message in self.messages]
|
||||
|
||||
def dump_messages(self) -> List[Dict[str, str]]:
|
||||
|
||||
@@ -77,5 +77,5 @@ class PromptTemplate(PromptTemplateBase):
|
||||
|
||||
return result
|
||||
|
||||
async def render_async(self, context: "KernelContext") -> str:
|
||||
return await self.template_engine.render_async(self.template, context)
|
||||
async def render(self, context: "KernelContext") -> str:
|
||||
return await self.template_engine.render(self.template, context)
|
||||
|
||||
@@ -16,5 +16,5 @@ class PromptTemplateBase(KernelBaseModel, ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def render_async(self, context: "KernelContext") -> str:
|
||||
async def render(self, context: "KernelContext") -> str:
|
||||
pass
|
||||
|
||||
@@ -68,7 +68,7 @@ class CodeBlock(Block):
|
||||
|
||||
return True, ""
|
||||
|
||||
async def render_code_async(self, context):
|
||||
async def render_code(self, context):
|
||||
if not self._validated:
|
||||
is_valid, error = self.is_valid()
|
||||
if not is_valid:
|
||||
@@ -80,11 +80,11 @@ class CodeBlock(Block):
|
||||
return self._tokens[0].render(context.variables)
|
||||
|
||||
if self._tokens[0].type == BlockTypes.FUNCTION_ID:
|
||||
return await self._render_function_call_async(self._tokens[0], context)
|
||||
return await self._render_function_call(self._tokens[0], context)
|
||||
|
||||
raise ValueError(f"Unexpected first token type: {self._tokens[0].type}")
|
||||
|
||||
async def _render_function_call_async(self, f_block: FunctionIdBlock, context):
|
||||
async def _render_function_call(self, f_block: FunctionIdBlock, context):
|
||||
if not context.plugins:
|
||||
raise ValueError("Plugin collection not set")
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class PromptTemplateEngine(KernelBaseModel):
|
||||
|
||||
return blocks
|
||||
|
||||
async def render_async(self, template_text: str, context: "KernelContext") -> str:
|
||||
async def render(self, template_text: str, context: "KernelContext") -> str:
|
||||
"""
|
||||
Given a prompt template, replace the variables with their values
|
||||
and execute the functions replacing their reference with the
|
||||
@@ -62,9 +62,9 @@ class PromptTemplateEngine(KernelBaseModel):
|
||||
"""
|
||||
logger.debug(f"Rendering string template: {template_text}")
|
||||
blocks = self.extract_blocks(template_text)
|
||||
return await self.render_blocks_async(blocks, context)
|
||||
return await self.render_blocks(blocks, context)
|
||||
|
||||
async def render_blocks_async(self, blocks: List[Block], context: "KernelContext") -> str:
|
||||
async def render_blocks(self, blocks: List[Block], context: "KernelContext") -> str:
|
||||
"""
|
||||
Given a list of blocks render each block and compose the final result.
|
||||
|
||||
@@ -80,7 +80,7 @@ class PromptTemplateEngine(KernelBaseModel):
|
||||
if isinstance(block, TextRenderer):
|
||||
rendered_blocks.append(block.render(context.variables))
|
||||
elif isinstance(block, CodeRenderer):
|
||||
rendered_blocks.append(await block.render_code_async(context))
|
||||
rendered_blocks.append(await block.render_code(context))
|
||||
else:
|
||||
error = "unexpected block type, the block doesn't have a rendering " "protocol assigned to it"
|
||||
logger.error(error)
|
||||
@@ -114,7 +114,7 @@ class PromptTemplateEngine(KernelBaseModel):
|
||||
|
||||
return rendered_blocks
|
||||
|
||||
async def render_code_async(self, blocks: List[Block], execution_context: "KernelContext") -> List[Block]:
|
||||
async def render_code(self, blocks: List[Block], execution_context: "KernelContext") -> List[Block]:
|
||||
"""
|
||||
Given a list of blocks, render the Code Blocks, executing the
|
||||
functions and replacing placeholders with the functions result.
|
||||
@@ -136,6 +136,6 @@ class PromptTemplateEngine(KernelBaseModel):
|
||||
continue
|
||||
if not isinstance(block, CodeRenderer):
|
||||
raise ValueError("CodeBlock must implement CodeRenderer protocol")
|
||||
rendered_blocks.append(TextBlock.from_text(await block.render_code_async(execution_context)))
|
||||
rendered_blocks.append(TextBlock.from_text(await block.render_code(execution_context)))
|
||||
|
||||
return rendered_blocks
|
||||
|
||||
@@ -11,7 +11,7 @@ class CodeRenderer(Protocol):
|
||||
Protocol for dynamic code blocks that need async IO to be rendered.
|
||||
"""
|
||||
|
||||
async def render_code_async(self, context: KernelContext) -> str:
|
||||
async def render_code(self, context: KernelContext) -> str:
|
||||
"""
|
||||
Render the block using the given context.
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class PromptTemplatingEngine(Protocol):
|
||||
"""
|
||||
...
|
||||
|
||||
async def render_async(self, template_text: str, context: "KernelContext") -> str:
|
||||
async def render(self, template_text: str, context: "KernelContext") -> str:
|
||||
"""
|
||||
Given a prompt template, replace the variables with their values
|
||||
and execute the functions replacing their reference with the
|
||||
@@ -40,7 +40,7 @@ class PromptTemplatingEngine(Protocol):
|
||||
"""
|
||||
...
|
||||
|
||||
async def render_blocks_async(self, blocks: List[Block], context: "KernelContext") -> str:
|
||||
async def render_blocks(self, blocks: List[Block], context: "KernelContext") -> str:
|
||||
"""
|
||||
Given a list of blocks render each block and compose the final result.
|
||||
|
||||
@@ -62,7 +62,7 @@ class PromptTemplatingEngine(Protocol):
|
||||
"""
|
||||
...
|
||||
|
||||
async def render_code_async(self, blocks: List[Block], execution_context: "KernelContext") -> List[Block]:
|
||||
async def render_code(self, blocks: List[Block], execution_context: "KernelContext") -> List[Block]:
|
||||
"""
|
||||
Given a list of blocks, render the Code Blocks, executing the
|
||||
functions and replacing placeholders with the functions result.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
from semantic_kernel.text.function_extension import aggregate_chunked_results_async
|
||||
from semantic_kernel.text.function_extension import aggregate_chunked_results
|
||||
from semantic_kernel.text.text_chunker import (
|
||||
split_markdown_lines,
|
||||
split_markdown_paragraph,
|
||||
@@ -13,5 +13,5 @@ __all__ = [
|
||||
"split_markdown_paragraph",
|
||||
"split_plaintext_paragraph",
|
||||
"split_markdown_lines",
|
||||
"aggregate_chunked_results_async",
|
||||
"aggregate_chunked_results",
|
||||
]
|
||||
|
||||
@@ -6,7 +6,7 @@ from semantic_kernel.orchestration.kernel_context import KernelContext
|
||||
from semantic_kernel.orchestration.kernel_function import KernelFunction
|
||||
|
||||
|
||||
async def aggregate_chunked_results_async(
|
||||
async def aggregate_chunked_results(
|
||||
func: KernelFunction, chunked_results: List[str], context: KernelContext
|
||||
) -> KernelContext:
|
||||
"""
|
||||
|
||||
@@ -33,7 +33,7 @@ async def test_azure_e2e_chat_completion_with_plugin(setup_tldr_function_for_oai
|
||||
# Create the semantic function
|
||||
tldr_function = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0, top_p=0.5)
|
||||
|
||||
summary = await retry(lambda: kernel.run_async(tldr_function, input_str=text_to_summarize))
|
||||
summary = await retry(lambda: kernel.run(tldr_function, input_str=text_to_summarize))
|
||||
output = str(summary).strip()
|
||||
print(f"TLDR using input string: '{output}'")
|
||||
assert "First Law" not in output and ("human" in output or "Human" in output or "preserve" in output)
|
||||
@@ -77,7 +77,7 @@ async def test_azure_e2e_chat_completion_with_plugin_and_provided_client(
|
||||
# Create the semantic function
|
||||
tldr_function = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0, top_p=0.5)
|
||||
|
||||
summary = await retry(lambda: kernel.run_async(tldr_function, input_str=text_to_summarize))
|
||||
summary = await retry(lambda: kernel.run(tldr_function, input_str=text_to_summarize))
|
||||
output = str(summary).strip()
|
||||
print(f"TLDR using input string: '{output}'")
|
||||
assert "First Law" not in output and ("human" in output or "Human" in output or "preserve" in output)
|
||||
|
||||
@@ -37,10 +37,10 @@ async def create_memory_store():
|
||||
# Create an index and populate it with some data
|
||||
collection = f"int-tests-chat-extensions-{randint(1000, 9999)}"
|
||||
memory_store = AzureCognitiveSearchMemoryStore(vector_size=4)
|
||||
await memory_store.create_collection_async(collection)
|
||||
await memory_store.create_collection(collection)
|
||||
time.sleep(1)
|
||||
try:
|
||||
assert await memory_store.does_collection_exist_async(collection)
|
||||
assert await memory_store.does_collection_exist(collection)
|
||||
rec = MemoryRecord(
|
||||
is_reference=False,
|
||||
external_source_name=None,
|
||||
@@ -53,11 +53,11 @@ async def create_memory_store():
|
||||
additional_metadata=None,
|
||||
embedding=np.array([0.2, 0.1, 0.2, 0.7]),
|
||||
)
|
||||
await memory_store.upsert_async(collection, rec)
|
||||
await memory_store.upsert(collection, rec)
|
||||
time.sleep(1)
|
||||
return collection, memory_store
|
||||
except:
|
||||
await memory_store.delete_collection_async(collection)
|
||||
await memory_store.delete_collection(collection)
|
||||
raise
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ async def create_with_data_chat_function(get_aoai_config, create_kernel, create_
|
||||
chat_function = kernel.register_semantic_function("ChatBot", "Chat", function_config)
|
||||
return chat_function, kernel, collection, memory_store
|
||||
except:
|
||||
await memory_store.delete_collection_async(collection)
|
||||
await memory_store.delete_collection(collection)
|
||||
raise
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ async def test_azure_e2e_chat_completion_with_extensions(
|
||||
|
||||
try:
|
||||
result = []
|
||||
async for message in kernel.run_stream_async(chat_function, input_str="who are Emily and David?"):
|
||||
async for message in kernel.run_stream(chat_function, input_str="who are Emily and David?"):
|
||||
result.append(message)
|
||||
print(message, end="")
|
||||
output = "".join(result).strip()
|
||||
@@ -148,7 +148,7 @@ async def test_azure_e2e_chat_completion_with_extensions(
|
||||
print(f"Answer using input string: '{output}'")
|
||||
assert len(result) > 1
|
||||
|
||||
await memory_store.delete_collection_async(collection)
|
||||
await memory_store.delete_collection(collection)
|
||||
except:
|
||||
await memory_store.delete_collection_async(collection)
|
||||
await memory_store.delete_collection(collection)
|
||||
raise
|
||||
|
||||
@@ -37,7 +37,7 @@ async def test_azure_e2e_text_completion_with_plugin(setup_tldr_function_for_oai
|
||||
# Create the semantic function
|
||||
tldr_function = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0, top_p=0.5)
|
||||
|
||||
summary = await retry(lambda: kernel.run_async(tldr_function, input_str=text_to_summarize))
|
||||
summary = await retry(lambda: kernel.run(tldr_function, input_str=text_to_summarize))
|
||||
output = str(summary).strip()
|
||||
print(f"TLDR using input string: '{output}'")
|
||||
assert "First Law" not in output and ("human" in output or "Human" in output or "preserve" in output)
|
||||
@@ -81,7 +81,7 @@ async def test_azure_e2e_text_completion_with_plugin_with_provided_client(
|
||||
# Create the semantic function
|
||||
tldr_function = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0, top_p=0.5)
|
||||
|
||||
summary = await retry(lambda: kernel.run_async(tldr_function, input_str=text_to_summarize))
|
||||
summary = await retry(lambda: kernel.run(tldr_function, input_str=text_to_summarize))
|
||||
output = str(summary).strip()
|
||||
print(f"TLDR using input string: '{output}'")
|
||||
assert "First Law" not in output and ("human" in output or "Human" in output or "preserve" in output)
|
||||
|
||||
@@ -33,7 +33,7 @@ async def test_azure_summarize_conversation_using_plugin(setup_summarize_convers
|
||||
conversationSummaryPlugin = kernel.import_plugin(ConversationSummaryPlugin(kernel), "conversationSummary")
|
||||
|
||||
summary = await retry(
|
||||
lambda: kernel.run_async(conversationSummaryPlugin["SummarizeConversation"], input_str=chatTranscript)
|
||||
lambda: kernel.run(conversationSummaryPlugin["SummarizeConversation"], input_str=chatTranscript)
|
||||
)
|
||||
|
||||
output = str(summary).strip().lower()
|
||||
@@ -63,7 +63,7 @@ async def test_oai_summarize_conversation_using_plugin(
|
||||
conversationSummaryPlugin = kernel.import_plugin(ConversationSummaryPlugin(kernel), "conversationSummary")
|
||||
|
||||
summary = await retry(
|
||||
lambda: kernel.run_async(conversationSummaryPlugin["SummarizeConversation"], input_str=chatTranscript)
|
||||
lambda: kernel.run(conversationSummaryPlugin["SummarizeConversation"], input_str=chatTranscript)
|
||||
)
|
||||
|
||||
output = str(summary).strip().lower()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user