mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
### Motivation and Context The `python-preview` branch is under active development and many docs/tests/examples are getting a bit out of sync. There are also a few small cleanup chores/refactors to make _usage_ easier (e.g., to make examples cleaner). I've grouped these small fixes (plus a few bug fixes) into this "cleanup" PR. ### Description This PR does the following: 1. Updates the out-of-date example in `README.md` 2. Fixes all 5 of the notebooks we support right now (1,2,3,4, and 6; notebook 5 is planner, I've blanked out most of the code there so we don't confuse people, especially as the planner API is changing) 3. Fixes a bug w/ `stop_sequences` in `(Azure)OpenAITextCompletion` 4. Fixes a bug introduced in our upgrades to the embeddings cosine-sim check (we should add more thorough tests here) 5. Cleans up tests 6. Ensures end-to-end tests are all runnable 7. Fixes up the `kernel_extensions` to work more naturally (so that end users can use them directly on the `kernel` object and get good type-hinting)
154 lines
4.3 KiB
Python
154 lines
4.3 KiB
Python
# Copyright (c) Microsoft. All rights reserved.
|
|
|
|
import asyncio
|
|
from typing import Tuple
|
|
|
|
import semantic_kernel as sk
|
|
import semantic_kernel.ai.open_ai as sk_oai
|
|
|
|
|
|
def build_kernel() -> sk.Kernel:
|
|
# Setup kernel with OpenAI completion and embedding backends
|
|
api_key, org_id = sk.openai_settings_from_dot_env()
|
|
|
|
kernel = (
|
|
sk.kernel_builder()
|
|
.configure(
|
|
lambda c: c.add_text_backend(
|
|
"davinci-003",
|
|
sk_oai.OpenAITextCompletion("text-davinci-003", api_key, org_id),
|
|
)
|
|
)
|
|
.configure(
|
|
lambda c: c.add_embedding_backend(
|
|
"ada-002",
|
|
sk_oai.OpenAITextEmbedding("text-embedding-ada-002", api_key, org_id),
|
|
)
|
|
)
|
|
.with_memory_storage(sk.memory.VolatileMemoryStore())
|
|
.build()
|
|
)
|
|
|
|
kernel.import_skill(sk.core_skills.TextMemorySkill())
|
|
|
|
return kernel
|
|
|
|
|
|
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"
|
|
)
|
|
|
|
|
|
async def search_memory_examples(kernel: sk.Kernel) -> None:
|
|
questions = [
|
|
"what's my name",
|
|
"where do I live?",
|
|
"where's my family from?",
|
|
"where have I traveled?",
|
|
"what do I do for work",
|
|
]
|
|
|
|
for question in questions:
|
|
print(f"Question: {question}")
|
|
result = await kernel.memory.search_async("aboutMe", question)
|
|
print(f"Answer: {result[0].text}\n")
|
|
|
|
|
|
async def setup_chat_with_memory(
|
|
kernel: sk.Kernel,
|
|
) -> Tuple[sk.SKFunctionBase, sk.SKContext]:
|
|
sk_prompt = """
|
|
ChatBot can have a conversation with you about any topic.
|
|
It can give explicit instructions or say 'I don't know' if
|
|
it does not have an answer.
|
|
|
|
Information about me, from previous conversations:
|
|
- {{$fact1}} {{recall $fact1}}
|
|
- {{$fact2}} {{recall $fact2}}
|
|
- {{$fact3}} {{recall $fact3}}
|
|
- {{$fact4}} {{recall $fact4}}
|
|
- {{$fact5}} {{recall $fact5}}
|
|
|
|
Chat:
|
|
{{$chat_history}}
|
|
User: {{$user_input}}
|
|
ChatBot: """.strip()
|
|
|
|
chat_func = kernel.create_semantic_function(
|
|
sk_prompt, max_tokens=200, temperature=0.8
|
|
)
|
|
|
|
context = kernel.create_new_context()
|
|
context["fact1"] = "what is my name?"
|
|
context["fact2"] = "where do I live?"
|
|
context["fact3"] = "where's my family from?"
|
|
context["fact4"] = "where have I traveled?"
|
|
context["fact5"] = "what do I do for work?"
|
|
|
|
context[sk.core_skills.TextMemorySkill.COLLECTION_PARAM] = "aboutMe"
|
|
context[sk.core_skills.TextMemorySkill.RELEVANCE_PARAM] = 0.8
|
|
|
|
context["chat_history"] = ""
|
|
|
|
return chat_func, context
|
|
|
|
|
|
async def chat(
|
|
kernel: sk.Kernel, chat_func: sk.SKFunctionBase, context: sk.SKContext
|
|
) -> bool:
|
|
try:
|
|
user_input = input("User:> ")
|
|
context["user_input"] = user_input
|
|
except KeyboardInterrupt:
|
|
print("\n\nExiting chat...")
|
|
return False
|
|
except EOFError:
|
|
print("\n\nExiting chat...")
|
|
return False
|
|
|
|
if user_input == "exit":
|
|
print("\n\nExiting chat...")
|
|
return False
|
|
|
|
answer = await kernel.run_on_vars_async(context.variables, chat_func)
|
|
context["chat_history"] += f"\nUser:> {user_input}\nChatBot:> {answer}\n"
|
|
|
|
print(f"ChatBot:> {answer}")
|
|
return True
|
|
|
|
|
|
async def main() -> None:
|
|
kernel = build_kernel()
|
|
|
|
print("Populating memory...")
|
|
await populate_memory(kernel)
|
|
|
|
print("Asking questions... (manually)")
|
|
await search_memory_examples(kernel)
|
|
|
|
print("Setting up a chat (with memory!)")
|
|
chat_func, context = await setup_chat_with_memory(kernel)
|
|
|
|
print("Begin chatting (type 'exit' to exit):\n")
|
|
chatting = True
|
|
while chatting:
|
|
chatting = await chat(kernel, chat_func, context)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|