Merge branch 'microsoft:main' into update-modelid

This commit is contained in:
Sandra Ahlgrimm
2024-01-08 14:22:56 +01:00
committed by GitHub
24 changed files with 1372 additions and 1214 deletions
+2 -2
View File
@@ -46,7 +46,7 @@
<PackageVersion Include="Moq" Version="[4.18.4]" />
<PackageVersion Include="System.Threading.Channels" Version="8.0.0" />
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="8.0.0" />
<PackageVersion Include="xunit" Version="2.6.3" />
<PackageVersion Include="xunit" Version="2.6.4" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.6" />
<PackageVersion Include="xretry" Version="1.9.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.0" />
@@ -91,7 +91,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageVersion Include="xunit.analyzers" Version="1.7.0" />
<PackageVersion Include="xunit.analyzers" Version="1.8.0" />
<PackageReference Include="xunit.analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
@@ -35,21 +36,14 @@ internal sealed class NamedArgBlock : Block, ITextRendering
public NamedArgBlock(string? text, ILoggerFactory? logger = null)
: base(NamedArgBlock.TrimWhitespace(text), logger)
{
var argParts = this.Content.Split(Symbols.NamedArgBlockSeparator);
if (argParts.Length != 2)
if (!TryGetNameAndValue(this.Content, out string argName, out string argValue))
{
this.Logger.LogError("Invalid named argument `{Text}`", text);
throw new KernelException($"A function named argument must contain a name and value separated by a '{Symbols.NamedArgBlockSeparator}' character.");
}
this.Name = argParts[0];
this._argNameAsVarBlock = new VarBlock($"{Symbols.VarPrefix}{argParts[0]}");
var argValue = argParts[1];
if (argValue.Length == 0)
{
this.Logger.LogError("Invalid named argument `{Text}`", text);
throw new KernelException($"A function named argument must contain a quoted value or variable after the '{Symbols.NamedArgBlockSeparator}' character.");
}
this.Name = argName;
this._argNameAsVarBlock = new VarBlock($"{Symbols.VarPrefix}{argName}");
if (argValue[0] == Symbols.VarPrefix)
{
@@ -61,6 +55,34 @@ internal sealed class NamedArgBlock : Block, ITextRendering
}
}
/// <summary>
/// Attempts to extract the name and value of a named argument block from a string
/// </summary>
/// <param name="text">String from which to extract a name and value</param>
/// <param name="name">Name extracted from argument block, when successful. Empty string otherwise.</param>
/// <param name="value">Value extracted from argument block, when successful. Empty string otherwise.</param>
/// <returns>true when a name and value are successfully extracted from the given text, false otherwise</returns>
internal static bool TryGetNameAndValue(string? text, out string name, out string value)
{
name = string.Empty;
value = string.Empty;
if (!string.IsNullOrEmpty(text))
{
string[] argBlockParts = text!.Split(new char[] { Symbols.NamedArgBlockSeparator }, StringSplitOptions.RemoveEmptyEntries);
if (argBlockParts.Length == 2)
{
name = argBlockParts[0];
value = argBlockParts[1];
return true;
}
}
return false;
}
/// <summary>
/// Gets the rendered value of the function argument. If the value is a <see cref="ValBlock"/>, the value stays the same.
/// If the value is a <see cref="VarBlock"/>, the value of the variable is determined by the arguments passed in.
@@ -322,14 +322,13 @@ internal sealed class CodeTokenizer
Justification = "Does not throw an exception by design.")]
private static bool IsValidNamedArg(string tokenContent)
{
try
if (NamedArgBlock.TryGetNameAndValue(tokenContent, out string _, out string _))
{
var tokenContentAsNamedArg = new NamedArgBlock(tokenContent);
return tokenContentAsNamedArg.IsValid(out var error);
}
catch
{
return false;
return tokenContentAsNamedArg.IsValid(out string _);
}
return false;
}
}
@@ -115,11 +115,11 @@ public class NamedArgBlockTests
public void ArgNameShouldBeNonEmpty()
{
// Arrange
var target = new NamedArgBlock("='b'");
static NamedArgBlock funcToTest() => new("='b'");
// Act + Assert
Assert.False(target.IsValid(out var error));
Assert.Equal("A named argument must have a name", error);
KernelException exception = Assert.Throws<KernelException>(funcToTest);
Assert.Equal("A function named argument must contain a name and value separated by a '=' character.", exception.Message);
}
[Fact]
@@ -209,12 +209,12 @@ public class CodeTokenizerTests
}
[Theory]
[InlineData("f a =", "A function named argument must contain a quoted value or variable after the '=' character.")]
[InlineData("f a='b' arg2", "A function named argument must contain a name and value separated by a '=' character.")]
public void ItThrowsWhenArgValueIsMissing(string template, string expectedErrorMessage)
[InlineData("f a =")]
[InlineData("f a='b' arg2")]
public void ItThrowsWhenArgValueIsMissing(string template)
{
// Act & Assert
var exception = Assert.Throws<KernelException>(() => this._target.Tokenize(template));
Assert.Equal(expectedErrorMessage, exception.Message);
Assert.Equal("A function named argument must contain a name and value separated by a '=' character.", exception.Message);
}
}
+2 -2
View File
@@ -16,7 +16,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -57,7 +57,7 @@
"\n",
"api_key, org_id = sk.openai_settings_from_dot_env()\n",
"\n",
"kernel.add_chat_service(\"chat-gpt\", OpenAIChatCompletion(ai_model_id=\"gpt-3.5-turbo\", api_key=api_key, org_id=org_id))"
"kernel.add_chat_service(\"chat-gpt\", OpenAIChatCompletion(ai_model_id=\"gpt-3.5-turbo-1106\", api_key=api_key, org_id=org_id))"
]
},
{
@@ -25,17 +25,20 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import semantic_kernel as sk\n",
"from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion, OpenAIChatCompletion"
"from semantic_kernel.connectors.ai.open_ai import (\n",
" AzureChatCompletion,\n",
" OpenAIChatCompletion,\n",
")"
]
},
{
@@ -48,7 +51,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@@ -85,13 +88,13 @@
" )\n",
")\n",
"\n",
"kernel.add_chat_service( # We are adding a text service\n",
" \"OpenAI_chat_gpt\", # The alias we can use in prompt templates' config.json\n",
"kernel.add_chat_service( # We are adding a text service\n",
" \"OpenAI_chat_gpt\", # The alias we can use in prompt templates' config.json\n",
" OpenAIChatCompletion(\n",
" ai_model_id=\"gpt-3.5-turbo\", # OpenAI Model Name\n",
" api_key=\"...your OpenAI API Key...\", # OpenAI API key\n",
" org_id=\"...your OpenAI Org ID...\" # *optional* OpenAI Organization ID\n",
" )\n",
" ai_model_id=\"gpt-3.5-turbo\", # OpenAI Model Name\n",
" api_key=\"...your OpenAI API Key...\", # OpenAI API key\n",
" org_id=\"...your OpenAI Org ID...\", # *optional* OpenAI Organization ID\n",
" ),\n",
")"
]
},
@@ -143,7 +146,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.10.12"
},
"polyglot_notebook": {
"kernelInfo": {
@@ -89,7 +89,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -100,7 +100,10 @@
"outputs": [],
"source": [
"import semantic_kernel as sk\n",
"from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion, OpenAIChatCompletion\n",
"from semantic_kernel.connectors.ai.open_ai import (\n",
" AzureChatCompletion,\n",
" OpenAIChatCompletion,\n",
")\n",
"\n",
"kernel = sk.Kernel()\n",
"\n",
@@ -109,7 +112,9 @@
"# Configure AI service used by the kernel\n",
"if useAzureOpenAI:\n",
" deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
" azure_chat_service = AzureChatCompletion(deployment_name=\"turbo\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your chat model\n",
" azure_chat_service = AzureChatCompletion(\n",
" deployment_name=\"turbo\", endpoint=endpoint, api_key=api_key\n",
" ) # set the deployment name to the value of your chat model\n",
" kernel.add_chat_service(\"chat_completion\", azure_chat_service)\n",
"else:\n",
" api_key, org_id = sk.openai_settings_from_dot_env()\n",
@@ -192,7 +197,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.10.12"
}
},
"nbformat": 4,
@@ -55,7 +55,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -66,7 +66,10 @@
"outputs": [],
"source": [
"import semantic_kernel as sk\n",
"from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion\n",
"from semantic_kernel.connectors.ai.open_ai import (\n",
" AzureTextCompletion,\n",
" OpenAITextCompletion,\n",
")\n",
"\n",
"kernel = sk.Kernel()\n",
"\n",
@@ -75,7 +78,9 @@
"# Configure AI service used by the kernel\n",
"if useAzureOpenAI:\n",
" deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
" azure_text_service = AzureTextCompletion(deployment_name=\"text\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your text model\n",
" azure_text_service = AzureTextCompletion(\n",
" deployment_name=\"text\", endpoint=endpoint, api_key=api_key\n",
" ) # set the deployment name to the value of your text model\n",
" kernel.add_text_completion_service(\"dv\", azure_text_service)\n",
"else:\n",
" api_key, org_id = sk.openai_settings_from_dot_env()\n",
@@ -196,7 +201,10 @@
"outputs": [],
"source": [
"import semantic_kernel as sk\n",
"from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion, OpenAIChatCompletion\n",
"from semantic_kernel.connectors.ai.open_ai import (\n",
" AzureChatCompletion,\n",
" OpenAIChatCompletion,\n",
")\n",
"\n",
"kernel = sk.Kernel()\n",
"\n",
@@ -205,7 +213,9 @@
"# Configure AI service used by the kernel\n",
"if useAzureOpenAI:\n",
" deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
" azure_chat_service = AzureChatCompletion(deployment_name=\"turbo\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your chat model\n",
" azure_chat_service = AzureChatCompletion(\n",
" deployment_name=\"turbo\", endpoint=endpoint, api_key=api_key\n",
" ) # set the deployment name to the value of your chat model\n",
" kernel.add_chat_service(\"chat_completion\", azure_chat_service)\n",
"else:\n",
" api_key, org_id = sk.openai_settings_from_dot_env()\n",
@@ -241,7 +251,7 @@
"\n",
"summary = tldr_function(text)\n",
"\n",
"print(f\"Output: {summary}\") # Output: Robots must not harm humans."
"print(f\"Output: {summary}\") # Output: Robots must not harm humans."
]
}
],
@@ -26,7 +26,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -37,7 +37,10 @@
"outputs": [],
"source": [
"import semantic_kernel as sk\n",
"from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion, OpenAIChatCompletion\n",
"from semantic_kernel.connectors.ai.open_ai import (\n",
" AzureChatCompletion,\n",
" OpenAIChatCompletion,\n",
")\n",
"\n",
"kernel = sk.Kernel()\n",
"\n",
@@ -46,10 +49,16 @@
"# Configure AI service used by the kernel\n",
"if useAzureOpenAI:\n",
" deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
" kernel.add_chat_service(\"chat_completion\", AzureChatCompletion(deployment_name=deployment, endpoint=endpoint, api_key=api_key))\n",
" kernel.add_chat_service(\n",
" \"chat_completion\",\n",
" AzureChatCompletion(deployment_name=deployment, endpoint=endpoint, api_key=api_key),\n",
" )\n",
"else:\n",
" api_key, org_id = sk.openai_settings_from_dot_env()\n",
" kernel.add_chat_service(\"gpt-3.5\", OpenAIChatCompletion(ai_model_id=\"gpt-3.5-turbo\", api_key=api_key, org_id=org_id))\n"
" kernel.add_chat_service(\n",
" \"gpt-3.5\",\n",
" OpenAIChatCompletion(ai_model_id=\"gpt-3.5-turbo\", api_key=api_key, org_id=org_id),\n",
" )"
]
},
{
@@ -98,7 +107,8 @@
" function_name=\"ChatBot\",\n",
" max_tokens=2000,\n",
" temperature=0.7,\n",
" top_p=0.5)"
" top_p=0.5,\n",
")"
]
},
{
+29 -15
View File
@@ -23,7 +23,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -34,7 +34,10 @@
"outputs": [],
"source": [
"import semantic_kernel as sk\n",
"from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion, AzureChatCompletion\n",
"from semantic_kernel.connectors.ai.open_ai import (\n",
" OpenAIChatCompletion,\n",
" AzureChatCompletion,\n",
")\n",
"\n",
"kernel = sk.Kernel()\n",
"\n",
@@ -43,10 +46,16 @@
"# Configure AI backend used by the kernel\n",
"if useAzureOpenAI:\n",
" deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
" kernel.add_chat_service(\"chat_completion\", AzureChatCompletion(deployment_name=deployment, endpoint=endpoint, api_key=api_key))\n",
" kernel.add_chat_service(\n",
" \"chat_completion\",\n",
" AzureChatCompletion(deployment_name=deployment, endpoint=endpoint, api_key=api_key),\n",
" )\n",
"else:\n",
" api_key, org_id = sk.openai_settings_from_dot_env()\n",
" kernel.add_chat_service(\"gpt-3.5\", OpenAIChatCompletion(ai_model_id=\"gpt-3.5-turbo\", api_key=api_key, org_id=org_id))"
" kernel.add_chat_service(\n",
" \"gpt-3.5\",\n",
" OpenAIChatCompletion(ai_model_id=\"gpt-3.5-turbo\", api_key=api_key, org_id=org_id),\n",
" )"
]
},
{
@@ -127,6 +136,7 @@
"outputs": [],
"source": [
"from semantic_kernel.planning.basic_planner import BasicPlanner\n",
"\n",
"planner = BasicPlanner()"
]
},
@@ -185,7 +195,8 @@
" function_name=\"shakespeare\",\n",
" skill_name=\"ShakespeareSkill\",\n",
" max_tokens=2000,\n",
" temperature=0.8)"
" temperature=0.8,\n",
")"
]
},
{
@@ -299,6 +310,7 @@
"outputs": [],
"source": [
"from semantic_kernel.planning import SequentialPlanner\n",
"\n",
"planner = SequentialPlanner(kernel)"
]
},
@@ -383,6 +395,7 @@
"outputs": [],
"source": [
"from semantic_kernel.planning import ActionPlanner\n",
"\n",
"planner = ActionPlanner(kernel)"
]
},
@@ -402,6 +415,7 @@
"outputs": [],
"source": [
"from semantic_kernel.core_skills import FileIOSkill, MathSkill, TextSkill, TimeSkill\n",
"\n",
"kernel.import_skill(MathSkill(), \"math\")\n",
"kernel.import_skill(FileIOSkill(), \"fileIO\")\n",
"kernel.import_skill(TimeSkill(), \"time\")\n",
@@ -502,15 +516,17 @@
" \"\"\"\n",
" A search engine skill.\n",
" \"\"\"\n",
"\n",
" from semantic_kernel.orchestration.sk_context import SKContext\n",
" from semantic_kernel.skill_definition import sk_function, sk_function_context_parameter\n",
" from semantic_kernel.skill_definition import (\n",
" sk_function,\n",
" sk_function_context_parameter,\n",
" )\n",
"\n",
" def __init__(self, connector) -> None:\n",
" self._connector = connector\n",
"\n",
" @sk_function(\n",
" description=\"Performs a web search for a given query\", name=\"searchAsync\"\n",
" )\n",
" @sk_function(description=\"Performs a web search for a given query\", name=\"searchAsync\")\n",
" @sk_function_context_parameter(\n",
" name=\"query\",\n",
" description=\"The search query\",\n",
@@ -564,9 +580,7 @@
"metadata": {},
"outputs": [],
"source": [
"planner = StepwisePlanner(\n",
" kernel, StepwisePlannerConfig(max_iterations=10, min_iteration_time_ms=1000)\n",
")"
"planner = StepwisePlanner(kernel, StepwisePlannerConfig(max_iterations=10, min_iteration_time_ms=1000))"
]
},
{
@@ -626,10 +640,10 @@
"source": [
"for index, step in enumerate(plan._steps):\n",
" print(\"Step:\", index)\n",
" print(\"Description:\",step.description)\n",
" print(\"Description:\", step.description)\n",
" print(\"Function:\", step.skill_name + \".\" + step._function.name)\n",
" if len(step._outputs) > 0:\n",
" print( \" Output:\\n\", str.replace(result[step._outputs[0]],\"\\n\", \"\\n \"))"
" print(\" Output:\\n\", str.replace(result[step._outputs[0]], \"\\n\", \"\\n \"))"
]
}
],
@@ -649,7 +663,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.10.12"
}
},
"nbformat": 4,
File diff suppressed because one or more lines are too long
@@ -20,7 +20,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0\n",
"!python -m pip install semantic-kernel==0.4.4.dev0\n",
"\n",
"# Note that additional dependencies are required for the Hugging Face connectors:\n",
"!python -m pip install torch==2.0.0\n",
@@ -184,7 +184,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.10.12"
}
},
"nbformat": 4,
@@ -46,7 +46,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -576,7 +576,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.10.12"
}
},
"nbformat": 4,
@@ -81,7 +81,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -352,7 +352,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.3"
"version": "3.10.12"
}
},
"nbformat": 4,
@@ -25,7 +25,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -36,7 +36,13 @@
"outputs": [],
"source": [
"import semantic_kernel as sk\n",
"from semantic_kernel.connectors.ai import ChatRequestSettings, CompleteRequestSettings\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 AzureTextCompletion, AzureChatCompletion, OpenAITextCompletion, OpenAIChatCompletion\n",
"from semantic_kernel.connectors.ai.hugging_face import HuggingFaceTextCompletion"
]
@@ -61,9 +67,8 @@
"\n",
"# Configure Azure LLM service\n",
"deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
"azure_text_service = AzureTextCompletion(deployment_name=\"text\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your text model\n",
"azure_chat_service = AzureChatCompletion(deployment_name=\"turbo\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your chat model\n",
"\n",
"azure_text_service = AzureTextCompletion(deployment_name=\"text-davinci-003\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your text model\n",
"azure_chat_service = AzureChatCompletion(deployment_name=\"gpt-35-turbo\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your chat model\n",
"\n",
"# Configure OpenAI service\n",
"api_key, org_id = sk.openai_settings_from_dot_env()\n",
@@ -90,14 +95,7 @@
"metadata": {},
"outputs": [],
"source": [
"request_settings = CompleteRequestSettings(\n",
" max_tokens=80,\n",
" temperature=0.7,\n",
" top_p=1,\n",
" frequency_penalty=0.5,\n",
" presence_penalty=0.5,\n",
" number_of_responses=3\n",
")"
"oai_text_request_settings = OpenAITextRequestSettings(extension_data = { \"max_tokens\": 80, \"temperature\": 0.7, \"top_p\": 1, \"frequency_penalty\": 0.5, \"presence_penalty\": 0.5, \"number_of_responses\": 3})"
]
},
{
@@ -117,7 +115,7 @@
"outputs": [],
"source": [
"prompt = \"what is the purpose of a rubber duck?\"\n",
"results = await oai_text_service.complete_async(prompt=prompt, settings=request_settings)\n",
"results = await oai_text_service.complete_async(prompt=prompt, settings=oai_text_request_settings)\n",
"i = 1\n",
"for result in results:\n",
" print(f\"Result {i}: {result}\")\n",
@@ -141,7 +139,7 @@
"outputs": [],
"source": [
"prompt = \"provide me a list of possible meanings for the acronym 'ORLD'\"\n",
"results = await azure_text_service.complete_async(prompt=prompt, settings=request_settings)\n",
"results = await azure_text_service.complete_async(prompt=prompt, settings=oai_text_request_settings)\n",
"i = 1\n",
"for result in results:\n",
" print(f\"Result {i}: {result}\")\n",
@@ -157,6 +155,20 @@
"## Multiple Hugging Face Text Completions"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4a148709",
"metadata": {},
"outputs": [],
"source": [
"from semantic_kernel.connectors.ai.hugging_face.hf_request_settings import (\n",
" HuggingFaceRequestSettings,\n",
")\n",
"\n",
"hf_request_settings = HuggingFaceRequestSettings(extension_data = { \"max_new_tokens\": 80, \"temperature\": 0.7, \"top_p\": 1})"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -165,11 +177,8 @@
"outputs": [],
"source": [
"prompt = \"The purpose of a rubber duck is\"\n",
"results = await hf_text_service.complete_async(prompt=prompt, request_settings=request_settings)\n",
"i = 1\n",
"for result in results:\n",
" print(f\"Result {i}: {result}\")\n",
" i += 1"
"results = await hf_text_service.complete_async(prompt=prompt, request_settings=hf_request_settings)\n",
"print(\"\".join(results))"
]
},
{
@@ -188,7 +197,7 @@
"metadata": {},
"outputs": [],
"source": [
"chat_request_settings = ChatRequestSettings(\n",
"oai_chat_request_settings = OpenAIChatRequestSettings(\n",
" max_tokens=80,\n",
" temperature=0.7,\n",
" top_p=1,\n",
@@ -217,10 +226,10 @@
"role = \"user\"\n",
"content = \"It's a beautiful day outside, birds are singing, flowers are blooming. On days like these, kids like you...\"\n",
"message = { \"role\":role, \"content\":content }\n",
"results = await oai_chat_service.complete_chat_async(messages=[message], settings=chat_request_settings)\n",
"results = await oai_chat_service.complete_chat_async(messages=[message], settings=oai_chat_request_settings)\n",
"i = 0\n",
"for result in results:\n",
" print(f\"Result {i}: {result}\")\n",
" print(f\"Result {i}: {result[0]}\")\n",
" i += 1"
]
},
@@ -233,6 +242,23 @@
"## Multiple Azure OpenAI Chat Completions"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "66ba4767",
"metadata": {},
"outputs": [],
"source": [
"az_oai_request_settings = AzureChatRequestSettings(\n",
" max_tokens=80,\n",
" temperature=0.7,\n",
" top_p=1,\n",
" frequency_penalty=0.5,\n",
" presence_penalty=0.5,\n",
" number_of_responses=3\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -243,10 +269,10 @@
"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=chat_request_settings)\n",
"results = await azure_chat_service.complete_chat_async(messages=[message], settings=az_oai_request_settings)\n",
"i = 0\n",
"for result in results:\n",
" print(f\"Result {i}: {result}\")\n",
" print(f\"Result {i}: {result[0]}\")\n",
" i += 1"
]
},
@@ -270,24 +296,39 @@
"source": [
"import os\n",
"from IPython.display import clear_output\n",
"import time\n",
"\n",
"if os.name == \"nt\":\n",
" clear = \"cls\"\n",
"else:\n",
" clear = \"clear\"\n",
"# Determine the clear command based on OS\n",
"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=request_settings)\n",
"texts = [\"\"] * request_settings.number_of_responses\n",
"async for results in stream:\n",
" i = 1\n",
" clear_output(wait=True)\n",
" for result in results:\n",
" texts[i - 1] += result\n",
" print(f\"Result {i}: {texts[i - 1]}\")\n",
" i += 1\n",
"stream = oai_text_service.complete_stream_async(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",
"print(\"----------------------------------------\")\n"
"last_clear_time = time.time()\n",
"clear_interval = 0.5 # seconds\n",
"\n",
"# Note: there are some quirks with displaying the output, which sometimes flashes and disappears.\n",
"# This could be influenced by a few factors specific to Jupyter notebooks and asynchronous processing.\n",
"# The following code attempts to buffer the results to avoid the output flashing on/off the screen.\n",
"\n",
"async for results in stream:\n",
" current_time = time.time()\n",
"\n",
" # Update texts with new results\n",
" for idx, result in enumerate(results):\n",
" if idx < number_of_responses:\n",
" texts[idx] += result\n",
"\n",
" # Clear and display output at intervals\n",
" if current_time - last_clear_time > clear_interval:\n",
" clear_output(wait=True)\n",
" for idx, text in enumerate(texts):\n",
" print(f\"Result {idx + 1}: {text}\")\n",
" last_clear_time = current_time\n",
"\n",
"print(\"----------------------------------------\")"
]
}
],
@@ -307,7 +348,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.10.12"
}
},
"nbformat": 4,
+73 -21
View File
@@ -16,7 +16,7 @@
"metadata": {},
"outputs": [],
"source": [
"!python -m pip install semantic-kernel==0.4.3.dev0"
"!python -m pip install semantic-kernel==0.4.4.dev0"
]
},
{
@@ -27,8 +27,19 @@
"outputs": [],
"source": [
"import semantic_kernel as sk\n",
"from semantic_kernel.connectors.ai import ChatRequestSettings, CompleteRequestSettings\n",
"from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, AzureChatCompletion, OpenAITextCompletion, OpenAIChatCompletion\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",
"from semantic_kernel.connectors.ai.hugging_face import HuggingFaceTextCompletion"
]
},
@@ -52,8 +63,12 @@
"\n",
"# Configure Azure LLM service\n",
"deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n",
"azure_text_service = AzureTextCompletion(deployment_name=\"text\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your text model\n",
"azure_chat_service = AzureChatCompletion(deployment_name=\"turbo\", endpoint=endpoint, api_key=api_key) # set the deployment name to the value of your chat model\n",
"azure_text_service = AzureTextCompletion(\n",
" deployment_name=\"text\", endpoint=endpoint, api_key=api_key\n",
") # set the deployment name to the value of your text model\n",
"azure_chat_service = AzureChatCompletion(\n",
" deployment_name=\"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",
"api_key, org_id = sk.openai_settings_from_dot_env()\n",
@@ -80,12 +95,12 @@
"metadata": {},
"outputs": [],
"source": [
"request_settings = CompleteRequestSettings(\n",
"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",
" presence_penalty=0.5,\n",
")"
]
},
@@ -106,9 +121,9 @@
"outputs": [],
"source": [
"prompt = \"what is the purpose of a rubber duck?\"\n",
"stream = oai_text_service.complete_stream_async(prompt=prompt, settings=request_settings)\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"
" print(text, end=\"\") # end = \"\" to avoid newlines"
]
},
{
@@ -128,9 +143,9 @@
"outputs": [],
"source": [
"prompt = \"provide me a list of possible meanings for the acronym 'ORLD'\"\n",
"stream = azure_text_service.complete_stream_async(prompt=prompt, settings=request_settings)\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"
" print(text, end=\"\") # end = \"\" to avoid newlines"
]
},
{
@@ -142,6 +157,27 @@
"## Streaming Hugging Face Text Completion"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "be7b1c2e",
"metadata": {},
"outputs": [],
"source": [
"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,
@@ -150,9 +186,9 @@
"outputs": [],
"source": [
"prompt = \"The purpose of a rubber duck is\"\n",
"stream = hf_text_service.complete_stream_async(prompt=prompt, request_settings=request_settings)\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"
" print(text, end=\"\") # end = \"\" to avoid newlines"
]
},
{
@@ -171,7 +207,7 @@
"metadata": {},
"outputs": [],
"source": [
"chat_request_settings = ChatRequestSettings(\n",
"oai_chat_request_settings = OpenAIChatRequestSettings(\n",
" max_tokens=150,\n",
" temperature=0.7,\n",
" top_p=1,\n",
@@ -198,10 +234,10 @@
"source": [
"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=chat_request_settings)\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"
" print(text, end=\"\") # end = \"\" to avoid newlines"
]
},
{
@@ -213,6 +249,22 @@
"## 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,
@@ -222,10 +274,10 @@
"source": [
"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=chat_request_settings)\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"
" print(text, end=\"\") # end = \"\" to avoid newlines"
]
}
],
@@ -245,7 +297,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.10.12"
}
},
"nbformat": 4,
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "semantic-kernel"
version = "0.4.3.dev"
version = "0.4.4.dev"
description = "Semantic Kernel Python SDK"
authors = ["Microsoft <[email protected]>"]
readme = "pip/README.md"
@@ -1,9 +1,17 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from typing import Any, Dict
import semantic_kernel as sk
import semantic_kernel.connectors.ai.open_ai as sk_oai
from semantic_kernel.connectors.ai.ai_request_settings import AIRequestSettings
from semantic_kernel.connectors.ai.chat_completion_client_base import (
ChatCompletionClientBase,
)
from semantic_kernel.connectors.ai.text_completion_client_base import (
TextCompletionClientBase,
)
"""
Logit bias enables prioritizing certain tokens within a given output.
@@ -13,13 +21,11 @@ Read more about logit bias and how to configure output: https://help.openai.com/
"""
def _config_ban_tokens(settings_type, keys):
settings = sk_oai.OpenAIRequestSettings()
def _config_ban_tokens(settings: AIRequestSettings, keys: Dict[Any, Any]):
# Map each token in the keys list to a bias value from -100 (a potential ban) to 100 (exclusive selection)
for k in keys:
# -100 to potentially ban all tokens in the list
settings.token_selection_biases[k] = -100
settings.logit_bias[k] = -100
return settings
@@ -59,7 +65,8 @@ async def chat_request_example(kernel, api_key, org_id):
]
# Model will try its best to avoid using any of the above words
settings = _config_ban_tokens("chat", keys)
settings = kernel.get_request_settings_from_service(ChatCompletionClientBase, "chat_service")
settings = _config_ban_tokens(settings, keys)
prompt_config = sk.PromptTemplateConfig.from_completion_parameters(max_tokens=2000, temperature=0.7, top_p=0.8)
prompt_template = sk.ChatPromptTemplate("{{$user_input}}", kernel.prompt_template_engine, prompt_config)
@@ -71,15 +78,18 @@ async def chat_request_example(kernel, api_key, org_id):
function_config = sk.SemanticFunctionConfig(prompt_config, prompt_template)
kernel.register_semantic_function("ChatBot", "Chat", function_config)
chat_messages = list()
chat_messages = []
messages = [{"role": "user", "content": user_mssg}]
chat_messages.append(("user", user_mssg))
answer = await openai_chat_completion.complete_chat_async(chat_messages, settings)
chat_messages.append(("assistant", str(answer)))
answer = await openai_chat_completion.complete_chat_async(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(chat_messages, settings)
chat_messages.append(("assistant", str(answer)))
answer = await openai_chat_completion.complete_chat_async(messages=messages, settings=settings)
chat_messages.append(("assistant", str(answer[0])))
context_vars = sk.ContextVariables()
context_vars["chat_history"] = ""
@@ -140,7 +150,8 @@ async def text_complete_request_example(kernel, api_key, org_id):
]
# Model will try its best to avoid using any of the above words
settings = _config_ban_tokens("complete", keys)
settings = kernel.get_request_settings_from_service(TextCompletionClientBase, "text_service")
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)
@@ -28,7 +28,7 @@ class HuggingFaceRequestSettings(AIRequestSettings):
gen_config = self.get_generation_config()
if "prompt" in kwargs and kwargs["prompt"] is not None:
return {
"prompt": kwargs["prompt"],
"text_inputs": kwargs["prompt"],
"generation_config": gen_config,
"num_return_sequences": self.num_return_sequences,
"do_sample": self.do_sample,
@@ -81,7 +81,7 @@ class HuggingFaceTextCompletion(TextCompletionClientBase, AIServiceClientBase):
if kwargs.get("logger"):
logger.warning("The `logger` parameter is deprecated. Please use the `logging` module instead.")
try:
results = self.generator(**request_settings.prepare_settings_dict(prompt))
results = self.generator(**request_settings.prepare_settings_dict(prompt=prompt))
result_field_name = "summary_text" if self.task == "summarization" else "generated_text"
if len(results) == 1:
return results[0][result_field_name]
@@ -14,7 +14,7 @@ class OpenAIRequestSettings(AIRequestSettings):
ai_model_id: Optional[str] = Field(None, serialization_alias="model")
frequency_penalty: float = Field(0.0, ge=-2.0, le=2.0)
logit_bias: Dict[str, float] = Field(default_factory=dict)
logit_bias: Dict[Union[str, int], float] = Field(default_factory=dict)
max_tokens: int = Field(256, gt=0)
number_of_responses: int = Field(1, ge=1, le=128, serialization_alias="n")
presence_penalty: float = Field(0.0, ge=-2.0, le=2.0)
@@ -366,7 +366,10 @@ class SKFunction(SKFunctionBase):
if input is not None:
context.variables.update(input)
loop = asyncio.get_running_loop() if asyncio.get_event_loop().is_running() else None
try:
loop = asyncio.get_running_loop() if asyncio.get_event_loop().is_running() else None
except RuntimeError:
loop = None
if loop and loop.is_running():
coroutine_function = self._invoke_semantic_async if self.is_semantic else self._invoke_native_async