From 6d574f263bf334d94c3dbdc64abb11dfc4b984aa Mon Sep 17 00:00:00 2001 From: John Oliver <1615532+johnoliver@users.noreply.github.com> Date: Fri, 3 Nov 2023 13:50:38 +0000 Subject: [PATCH 001/576] Java: Merge java-development into main (#3361) ### Motivation and Context ### Description ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: --------- Signed-off-by: dependabot[bot] Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Co-authored-by: Teresa Hoang <125500434+teresaqhoang@users.noreply.github.com> Co-authored-by: Gil LaHaye Co-authored-by: Craig Presti <146438+craigomatic@users.noreply.github.com> Co-authored-by: adityachallapally Co-authored-by: Devis Lucato Co-authored-by: Gina Triolo <51341242+gitri-ms@users.noreply.github.com> Co-authored-by: Adrian Bonar <56417140+adrianwyatt@users.noreply.github.com> Co-authored-by: Gudge Co-authored-by: Shawn Callegari <36091529+shawncal@users.noreply.github.com> Co-authored-by: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Co-authored-by: Stephen Toub Co-authored-by: Jadyn Co-authored-by: Lee Miller Co-authored-by: name Co-authored-by: Milder Hernandez Cagua Co-authored-by: Milder Hernandez Co-authored-by: Yoshio Terada Co-authored-by: Almir Kazazic Co-authored-by: Alexander Siniouguine Co-authored-by: Harleen Thind <39630244+hathind-ms@users.noreply.github.com> Co-authored-by: David Barkol Co-authored-by: Mark Karle Co-authored-by: poweihuang0817 <131632377+poweihuang0817@users.noreply.github.com> Co-authored-by: Po-Wei Huang Co-authored-by: Ikko Eltociear Ashimine Co-authored-by: Adrian Bonar (HE/HIM) Co-authored-by: Tao Chen Co-authored-by: Vivien Hung Co-authored-by: Abby Harrison <54643756+awharrison-28@users.noreply.github.com> Co-authored-by: Abby Harrison Co-authored-by: Devis Lucato Co-authored-by: fabio fumarola Co-authored-by: cdMSFT <60192871+cdMSFT@users.noreply.github.com> Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com> Co-authored-by: Lex Li <425130+lextm@users.noreply.github.com> Co-authored-by: Damir Dobric Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Aman Sachan <51973971+amsacha@users.noreply.github.com> Co-authored-by: Joowon Co-authored-by: Richard Edgar Co-authored-by: nacharya1 <41800911+nacharya1@users.noreply.github.com> Co-authored-by: Kevdome3000 Co-authored-by: tech Co-authored-by: Masumi Morishige Co-authored-by: Alex Chao <5111035+alexchaomander@users.noreply.github.com> Co-authored-by: Alex Chao Co-authored-by: markwallace-microsoft Co-authored-by: David Grieve Co-authored-by: Bruno Borges Co-authored-by: Martijn Verburg Co-authored-by: Luigi Montoya Co-authored-by: joe-braley Co-authored-by: Luigi96 Co-authored-by: GitHub Co-authored-by: Derek Keeler Co-authored-by: Joe Braley <106336504+joe-braley@users.noreply.github.com> Co-authored-by: Craig Presti Co-authored-by: cschadewitz Co-authored-by: Desmond Howard Co-authored-by: Jean-Sylvain Boige Co-authored-by: Dave Arlin Co-authored-by: Ben Thomas Co-authored-by: Ben Thomas Co-authored-by: Sebastian Santoyo <115967275+SebasX5@users.noreply.github.com> Co-authored-by: sneha Co-authored-by: Alisha Maddy <59581465+am831@users.noreply.github.com> Co-authored-by: Alisha Maddy Co-authored-by: Sneha <55897319+sneha-afk@users.noreply.github.com> Co-authored-by: Guy Bowerman Co-authored-by: kshitijcode Co-authored-by: dantelmomsft <113094107+dantelmomsft@users.noreply.github.com> Co-authored-by: Vikram Seshadri --- .github/workflows/codeql-analysis.yml | 73 +- .github/workflows/java-build.yml | 84 + .github/workflows/java-integration-tests.yml | 91 + java/.mvn/jvm.config | 10 + java/.mvn/wrapper/maven-wrapper.properties | 18 + java/.vscode/settings.json | 3 + java/PACKAGES.md | 154 + java/README.md | 103 + java/api-test/api-usage-example/pom.xml | 34 + .../src/main/java/InlineFunctionExample.java | 137 + ...nlineFunctionWithPreBuiltSkillExample.java | 139 + .../src/main/resources/log4j2.xml | 13 + java/api-test/integration-tests/pom.xml | 133 + .../memory/jdbc/JDBCMemoryStoreTest.java | 721 + .../memory/mysql/MySQLMemoryStoreTest.java | 720 + .../postgresql/PostgreSQLMemoryStoreTest.java | 720 + .../memory/sqlite/SQLiteMemoryStoreTest.java | 711 + .../e2e/AbstractKernelTest.java | 102 + .../e2e/ContextVariableFunctionTest.java | 107 + .../semantickernel/e2e/FunSkillTest.java | 29 + .../e2e/InlineFunctionTest.java | 50 + .../semantickernel/e2e/KernelTest.java | 66 + .../semantickernel/e2e/PlannerTest.java | 37 + .../e2e/TextEmbeddingsTest.java | 149 + .../sequentialplanner/SequentialPlanTest.java | 184 + .../src/test/resources/log4j2.xml | 13 + java/api-test/pom.xml | 54 + java/api-test/spotbugs-exclude.xml | 4 + .../pom.xml | 37 + .../ai/openai/azuresdk/ClientBase.java | 33 + .../chatcompletion/OpenAIChatCompletion.java | 247 + .../chatcompletion/OpenAIChatHistory.java | 49 + .../textcompletion/OpenAITextCompletion.java | 169 + .../OpenAITextEmbeddingGeneration.java | 70 + ...embeddings.TextEmbeddingGeneration$Builder | 1 + ...rnel.chatcompletion.ChatCompletion$Builder | 1 + ...rnel.textcompletion.TextCompletion$Builder | 1 + .../pom.xml | 68 + .../AzureCognitiveSearchMemoryException.java | 64 + .../AzureCognitiveSearchMemoryRecord.java | 179 + .../AzureCognitiveSearchMemoryStore.java | 510 + .../AzureCognitiveSearchMemoryTests.java | 434 + .../pom.xml | 56 + .../semantickernel-connectors-memory-jdbc.iml | 10 + .../connectors/memory/jdbc/DatabaseEntry.java | 43 + .../connectors/memory/jdbc/JDBCConnector.java | 495 + .../memory/jdbc/JDBCMemoryStore.java | 316 + .../connectors/memory/jdbc/SQLConnector.java | 125 + .../memory/jdbc/SQLConnectorException.java | 61 + .../memory/jdbc/SQLMemoryStore.java | 25 + .../memory/jdbc/JDBCConnectorTest.java | 35 + .../pom.xml | 36 + .../memory/mysql/MySQLConnector.java | 370 + .../memory/mysql/MySQLMemoryStore.java | 61 + .../pom.xml | 50 + ...tickernel-connectors-memory-postgresql.iml | 10 + .../postgresql/PostgreSQLConnector.java | 155 + .../postgresql/PostgreSQLMemoryStore.java | 64 + .../pom.xml | 56 + .../memory/sqlite/SQLiteMemoryStore.java | 76 + .../semantickernel-gpt3-tokenizer/pom.xml | 41 + .../semantickernel/GPT3Tokenizer.java | 302 + .../settings/EmbeddedResource.java | 60 + .../semantickernel/settings/GPT3Settings.java | 75 + .../src/main/resources/encoder.json | 1 + .../src/main/resources/vocab.bpe | 50001 ++++++++++++++++ .../semantickernel/GPT3TokenizerTest.java | 31 + .../semantickernel-planners/pom.xml | 39 + .../actionplanner/ActionPlanResponse.java | 46 + .../planner/actionplanner/ActionPlanner.java | 358 + .../planner/actionplanner/Plan.java | 559 + .../DefaultSequentialPlannerSKContext.java | 256 + .../sequentialplanner/EmbeddedResource.java | 19 + .../SequentialPlanParser.java | 206 + .../sequentialplanner/SequentialPlanner.java | 134 + .../SequentialPlannerRequestSettings.java | 121 + .../DefaultStepwisePlanner.java | 656 + .../stepwiseplanner/StepwisePlanner.java | 16 + .../StepwisePlannerConfig.java | 103 + .../planner/stepwiseplanner/SystemStep.java | 133 + .../planner/actionplanner/skprompt.txt | 11 + .../planner/sequentialplanner/skprompt.txt | 118 + .../planner/stepwiseplanner/config.json | 32 + .../planner/stepwiseplanner/skprompt.txt | 49 + .../semantickernel-settings-loader/pom.xml | 32 + .../SemanticKernelHttpSettings.java | 31 + .../util/AbstractOpenAIClientSettings.java | 27 + .../ai/openai/util/AzureOpenAISettings.java | 83 + .../connectors/ai/openai/util/ClientType.java | 8 + .../ai/openai/util/OpenAIClientProvider.java | 254 + .../ai/openai/util/OpenAISettings.java | 51 + .../semantickernel/settings/SettingsMap.java | 173 + .../ai/openai/util/ConfigLoadingTest.java | 59 + java/mvnw | 308 + java/mvnw.cmd | 205 + .../semantickernel-plugin-core/pom.xml | 39 + .../coreskills/ConversationSummarySkill.java | 157 + .../coreskills/FileIOSkill.java | 85 + .../semantickernel/coreskills/HttpSkill.java | 98 + .../semantickernel/coreskills/MathSkill.java | 79 + .../coreskills/SemanticFunctionConstants.java | 96 + .../coreskills/TextMemorySkill.java | 243 + .../semantickernel/coreskills/TextSkill.java | 39 + .../semantickernel/coreskills/TimeSkill.java | 428 + .../semantickernel/coreskills/WaitSkill.java | 36 + .../semantickernel/text/TextChunker.java | 296 + .../semantickernel/util/LocaleParser.java | 45 + .../coreskills/FileIOSkillTest.java | 55 + .../coreskills/HttpSkillTest.java | 70 + .../coreskills/MathSkillTest.java | 23 + .../coreskills/TimeSkillTest.java | 145 + .../coreskills/WaitSkillTest.java | 41 + .../semantickernel/text/TextChunkerTest.java | 363 + java/pom.xml | 813 + java/samples/example.conf.properties | 6 + java/samples/pom.xml | 173 + java/samples/sample-code/README.md | 125 + java/samples/sample-code/pom.xml | 111 + .../Example99_BlogAnnouncement.java | 74 + .../Example_PlanWithNativeFunctions.java | 121 + .../semantickernel/SamplesConfig.java | 27 + .../samples/Example00_GettingStarted.java | 81 + .../Example02_RunningPromptsFromFile.java | 63 + .../Example03_SemanticFunctionInline.java | 136 + .../Example04_ContextVariablesChat.java | 120 + .../samples/Example05_UsingThePlanner.java | 53 + .../Example01_NativeFunctions.java | 20 + .../syntaxexamples/Example02_Pipeline.java | 29 + .../syntaxexamples/Example03_Variables.java | 61 + ...mple04_CombineLLMPromptsAndNativeCode.java | 62 + .../Example05_InlineFunctionDefinition.java | 86 + .../Example06_TemplateLanguage.java | 103 + .../Example08_RetryHandler.java | 105 + .../Example09_FunctionTypes.java | 285 + .../Example12_SequentialPlanner.java | 221 + .../Example13_ConversationSummarySkill.java | 196 + .../Example14_SemanticMemory.java | 175 + .../syntaxexamples/Example15_MemorySkill.java | 229 + .../syntaxexamples/Example17_ChatGPT.java | 67 + .../Example25_ReadOnlyMemoryStore.java | 287 + .../Example28_ActionPlanner.java | 66 + .../syntaxexamples/Example29_Tokenizer.java | 86 + .../Example33_StreamingChat.java | 79 + .../Example51_StepwisePlanner.java | 132 + .../samples/syntaxexamples/RunAll.java | 48 + .../syntaxexamples/SampleSkillsUtil.java | 30 + .../Java_Example01_ResourceLoading.java | 41 + .../SequentialPlanner_AnswerQuestion.java | 81 + .../ExampleFunctionRoot/config.json | 12 + .../ExampleFunctionRoot/skprompt.txt | 1 + .../Plugins/Answer/AnswerQuestion/config.json | 24 + .../Answer/AnswerQuestion/skprompt.txt | 30 + .../ExampleFunction/config.json | 12 + .../ExampleFunction/skprompt.txt | 1 + ...equire_context_variable_planner_prompt.txt | 118 + .../sample-code/src/main/resources/log4j2.xml | 20 + .../semantickernel-samples-guice/pom.xml | 48 + .../guice/CompletionFunctionFactory.java | 30 + .../semantickernel/guice/Config.java | 62 + .../guice/SemanticKernelModule.java | 131 + .../guice/CompletionFunctionExample.java | 80 + .../guice/GuiceEmbeddingExample.java | 45 + java/semantickernel-api/pom.xml | 45 + .../com/microsoft/semantickernel/Kernel.java | 204 + .../semantickernel/KernelConfig.java | 20 + .../semantickernel/KernelException.java | 71 + .../microsoft/semantickernel/SKBuilders.java | 82 + .../semantickernel/SKCheckedException.java | 49 + .../microsoft/semantickernel/SKException.java | 47 + .../semantickernel/SkillExecutor.java | 93 + .../com/microsoft/semantickernel/Verify.java | 19 + .../semantickernel/ai/AIException.java | 101 + .../ai/embeddings/Embedding.java | 105 + .../ai/embeddings/EmbeddingGeneration.java | 27 + .../embeddings/TextEmbeddingGeneration.java | 9 + .../ai/embeddings/VectorOperations.java | 113 + .../semantickernel/builders/Buildable.java | 8 + .../builders/BuildersSingleton.java | 127 + .../builders/SemanticKernelBuilder.java | 18 + .../builders/ServiceLoadUtil.java | 86 + .../chatcompletion/ChatCompletion.java | 55 + .../chatcompletion/ChatHistory.java | 92 + .../chatcompletion/ChatRequestSettings.java | 16 + .../exceptions/ConfigurationException.java | 56 + .../exceptions/NotSupportedException.java | 43 + .../exceptions/SkillsNotFoundException.java | 43 + .../extensions/KernelExtensions.java | 186 + .../semantickernel/memory/DataEntryBase.java | 42 + .../memory/MemoryException.java | 98 + .../memory/MemoryQueryResult.java | 78 + .../semantickernel/memory/MemoryRecord.java | 196 + .../memory/MemoryRecordMetadata.java | 159 + .../semantickernel/memory/MemoryStore.java | 156 + .../semantickernel/memory/NullMemory.java | 149 + .../memory/SemanticTextMemory.java | 111 + .../orchestration/AbstractSKContext.java | 140 + .../orchestration/AbstractSkFunction.java | 274 + .../orchestration/ContextVariables.java | 91 + .../FunctionNotRegisteredException.java | 57 + .../orchestration/RegistrableSkFunction.java | 9 + .../orchestration/SKContext.java | 141 + .../orchestration/SKFunction.java | 129 + .../WritableContextVariables.java | 52 + .../planner/PlanningException.java | 73 + .../semanticfunctions/PromptTemplate.java | 42 + .../PromptTemplateConfig.java | 411 + .../SemanticFunctionConfig.java | 29 + .../semantickernel/services/AIService.java | 5 + .../services/AIServiceCollection.java | 166 + .../services/AIServiceProvider.java | 4 + .../services/DefaultAIServiceProvider.java | 15 + .../services/DefaultNamedServiceProvider.java | 84 + .../services/NamedServiceProvider.java | 16 + .../skilldefinition/FunctionNotFound.java | 45 + .../skilldefinition/FunctionView.java | 79 + .../skilldefinition/KernelSkillsSupplier.java | 12 + .../skilldefinition/ParameterView.java | 46 + .../ReadOnlyFunctionCollection.java | 36 + .../ReadOnlySkillCollection.java | 57 + .../annotations/DefineSKFunction.java | 20 + .../annotations/SKFunctionInputAttribute.java | 14 + .../annotations/SKFunctionParameters.java | 29 + .../templateengine/PromptTemplateEngine.java | 51 + .../templateengine/blocks/Block.java | 48 + .../templateengine/blocks/BlockTypes.java | 19 + .../CompletionRequestSettings.java | 215 + .../textcompletion/CompletionSKFunction.java | 52 + .../textcompletion/CompletionType.java | 8 + .../textcompletion/TextCompletion.java | 63 + .../util/EmbeddedResourceLoader.java | 108 + java/semantickernel-bom/pom.xml | 208 + java/semantickernel-core/pom.xml | 95 + .../semantickernel/DefaultKernel.java | 511 + .../semantickernel/SkFunctionBuilders.java | 7 + .../coreskills/SkillImporter.java | 31 + .../memory/DefaultSemanticTextMemory.java | 208 + .../memory/MemoryConfiguration.java | 72 + .../memory/VolatileMemoryStore.java | 289 + .../DefaultCompletionSKFunction.java | 408 + .../DefaultContextVariables.java | 178 + .../orchestration/DefaultSKContext.java | 102 + .../DefaultSemanticSKFunction.java | 61 + .../DefaultTextCompletionSupplier.java | 13 + .../orchestration/NativeSKFunction.java | 538 + .../orchestration/SKNativeTask.java | 8 + .../orchestration/SKSemanticAsyncTask.java | 11 + .../semantickernel/orchestration/SKTask.java | 4 + .../DefaultPromptTemplate.java | 105 + .../skilldefinition/CaseInsensitiveMap.java | 138 + .../DefaultSkillCollection.java | 153 + .../skilldefinition/FunctionCollection.java | 127 + .../templateengine/CodeTokenizer.java | 228 + .../DefaultPromptTemplateEngine.java | 128 + .../templateengine/TemplateException.java | 135 + .../templateengine/TemplateTokenizer.java | 224 + .../templateengine/blocks/CodeBlock.java | 139 + .../templateengine/blocks/CodeRendering.java | 16 + .../blocks/FunctionIdBlock.java | 70 + .../templateengine/blocks/Symbols.java | 18 + .../templateengine/blocks/TextBlock.java | 25 + .../templateengine/blocks/TextRendering.java | 18 + .../templateengine/blocks/ValBlock.java | 63 + .../templateengine/blocks/VarBlock.java | 78 + ...om.microsoft.semantickernel.Kernel$Builder | 1 + ...t.semantickernel.builders.FunctionBuilders | 1 + ....semantickernel.memory.MemoryStore$Builder | 1 + ...nel.orchestration.ContextVariables$Builder | 1 + ...ntickernel.orchestration.SKContext$Builder | 1 + ...estration.WritableContextVariables$Builder | 1 + ...l.semanticfunctions.PromptTemplate$Builder | 1 + ...definition.ReadOnlySkillCollection$Builder | 1 + ...emplateengine.PromptTemplateEngine$Builder | 1 + ...extcompletion.CompletionSKFunction$Builder | 1 + .../semantickernel/AiServiceRegistryTest.java | 67 + .../semantickernel/DefaultKernelTest.java | 405 + .../semantickernel/TextEmbeddingsTest.java | 64 + .../OpenAIChatCompletionTest.java | 113 + .../memory/MemoryExceptionTests.java | 67 + .../memory/MemoryRecordTests.java | 265 + .../memory/VolatileMemoryStoreTests.java | 942 + .../orchestration/NativeSKFunctionTest.java | 150 + .../actionplanner/ActionPlannerTest.java | 73 + .../stepwiseplanner/StepwisePlannerTest.java | 135 + .../Example01NativeFunctionsTest.java | 20 + .../syntaxexamples/Example02PipelineTest.java | 32 + .../Example03VariablesTest.java | 41 + ...e04CombineLLMPromptsAndNativeCodeTest.java | 63 + .../Example05UsingThePlannerTest.java | 50 + .../Example06TemplateLanguageTest.java | 80 + .../Example12SequentialPlannerTest.java | 202 + ...Example13ConversationSummarySkillTest.java | 234 + .../syntaxexamples/Example17ChatGPTTest.java | 96 + .../Example28ActionPlannerTest.java | 139 + .../Example33StreamingChatTest.java | 70 + .../syntaxexamples/Examples.java | 4 + .../skills/SearchEngineSkill.java | 15 + .../skills/StaticTextSkill.java | 24 + .../planner/stepwiseplanner/response1.txt | 4 + .../planner/stepwiseplanner/response2.txt | 2 + .../planner/stepwiseplanner/response3.txt | 2 + .../planner/stepwiseplanner/response4.txt | 2 + .../src/test/resources/log4j2.xml | 13 + .../org.mockito.plugins.MockMaker | 1 + java/semantickernel-extensions-parent/pom.xml | 0 .../pom.xml | 0 java/spotbugs-exclude.xml | 119 + samples/java/JavaReferenceSkill/pom.xml | 2 +- 307 files changed, 83736 insertions(+), 31 deletions(-) create mode 100644 .github/workflows/java-build.yml create mode 100644 .github/workflows/java-integration-tests.yml create mode 100644 java/.mvn/jvm.config create mode 100644 java/.mvn/wrapper/maven-wrapper.properties create mode 100644 java/.vscode/settings.json create mode 100644 java/PACKAGES.md create mode 100644 java/README.md create mode 100644 java/api-test/api-usage-example/pom.xml create mode 100644 java/api-test/api-usage-example/src/main/java/InlineFunctionExample.java create mode 100644 java/api-test/api-usage-example/src/main/java/InlineFunctionWithPreBuiltSkillExample.java create mode 100644 java/api-test/api-usage-example/src/main/resources/log4j2.xml create mode 100644 java/api-test/integration-tests/pom.xml create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCMemoryStoreTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLMemoryStoreTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLMemoryStoreTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/sqlite/SQLiteMemoryStoreTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/AbstractKernelTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/ContextVariableFunctionTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/FunSkillTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/InlineFunctionTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/KernelTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/PlannerTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/TextEmbeddingsTest.java create mode 100644 java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanTest.java create mode 100644 java/api-test/integration-tests/src/test/resources/log4j2.xml create mode 100644 java/api-test/pom.xml create mode 100644 java/api-test/spotbugs-exclude.xml create mode 100644 java/connectors/semantickernel-connectors-ai-openai/pom.xml create mode 100644 java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/azuresdk/ClientBase.java create mode 100644 java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletion.java create mode 100644 java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatHistory.java create mode 100644 java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textcompletion/OpenAITextCompletion.java create mode 100644 java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textembeddings/OpenAITextEmbeddingGeneration.java create mode 100644 java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration$Builder create mode 100644 java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.chatcompletion.ChatCompletion$Builder create mode 100644 java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.textcompletion.TextCompletion$Builder create mode 100644 java/connectors/semantickernel-connectors-memory-azurecognitivesearch/pom.xml create mode 100644 java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryException.java create mode 100644 java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryRecord.java create mode 100644 java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryStore.java create mode 100644 java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/test/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryTests.java create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/pom.xml create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/semantickernel-connectors-memory-jdbc.iml create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/DatabaseEntry.java create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCConnector.java create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCMemoryStore.java create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLConnector.java create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLConnectorException.java create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLMemoryStore.java create mode 100644 java/connectors/semantickernel-connectors-memory-jdbc/src/test/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCConnectorTest.java create mode 100644 java/connectors/semantickernel-connectors-memory-mysql/pom.xml create mode 100644 java/connectors/semantickernel-connectors-memory-mysql/src/main/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLConnector.java create mode 100644 java/connectors/semantickernel-connectors-memory-mysql/src/main/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLMemoryStore.java create mode 100644 java/connectors/semantickernel-connectors-memory-postgresql/pom.xml create mode 100644 java/connectors/semantickernel-connectors-memory-postgresql/semantickernel-connectors-memory-postgresql.iml create mode 100644 java/connectors/semantickernel-connectors-memory-postgresql/src/main/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLConnector.java create mode 100644 java/connectors/semantickernel-connectors-memory-postgresql/src/main/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLMemoryStore.java create mode 100644 java/connectors/semantickernel-connectors-memory-sqlite/pom.xml create mode 100644 java/connectors/semantickernel-connectors-memory-sqlite/src/main/java/com/microsoft/semantickernel/connectors/memory/sqlite/SQLiteMemoryStore.java create mode 100644 java/extensions/semantickernel-gpt3-tokenizer/pom.xml create mode 100644 java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/GPT3Tokenizer.java create mode 100644 java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/settings/EmbeddedResource.java create mode 100644 java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/settings/GPT3Settings.java create mode 100644 java/extensions/semantickernel-gpt3-tokenizer/src/main/resources/encoder.json create mode 100644 java/extensions/semantickernel-gpt3-tokenizer/src/main/resources/vocab.bpe create mode 100644 java/extensions/semantickernel-gpt3-tokenizer/src/test/java/com/microsoft/semantickernel/GPT3TokenizerTest.java create mode 100644 java/extensions/semantickernel-planners/pom.xml create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanResponse.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanner.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/Plan.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/DefaultSequentialPlannerSKContext.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/EmbeddedResource.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanParser.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanner.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlannerRequestSettings.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/stepwiseplanner/DefaultStepwisePlanner.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/stepwiseplanner/StepwisePlanner.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/stepwiseplanner/StepwisePlannerConfig.java create mode 100644 java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/stepwiseplanner/SystemStep.java create mode 100644 java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/actionplanner/skprompt.txt create mode 100644 java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/sequentialplanner/skprompt.txt create mode 100644 java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/stepwiseplanner/config.json create mode 100644 java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/stepwiseplanner/skprompt.txt create mode 100644 java/extensions/semantickernel-settings-loader/pom.xml create mode 100644 java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/SemanticKernelHttpSettings.java create mode 100644 java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/AbstractOpenAIClientSettings.java create mode 100644 java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/AzureOpenAISettings.java create mode 100644 java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/ClientType.java create mode 100644 java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/OpenAIClientProvider.java create mode 100644 java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/OpenAISettings.java create mode 100644 java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/settings/SettingsMap.java create mode 100644 java/extensions/semantickernel-settings-loader/src/test/java/com/microsoft/semantickernel/connectors/ai/openai/util/ConfigLoadingTest.java create mode 100755 java/mvnw create mode 100644 java/mvnw.cmd create mode 100644 java/plugins/semantickernel-plugin-core/pom.xml create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/ConversationSummarySkill.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/FileIOSkill.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/HttpSkill.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/MathSkill.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/SemanticFunctionConstants.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TextMemorySkill.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TextSkill.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TimeSkill.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/WaitSkill.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/text/TextChunker.java create mode 100644 java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/util/LocaleParser.java create mode 100644 java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/FileIOSkillTest.java create mode 100644 java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/HttpSkillTest.java create mode 100644 java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/MathSkillTest.java create mode 100644 java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/TimeSkillTest.java create mode 100644 java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/WaitSkillTest.java create mode 100644 java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/text/TextChunkerTest.java create mode 100644 java/pom.xml create mode 100644 java/samples/example.conf.properties create mode 100644 java/samples/pom.xml create mode 100644 java/samples/sample-code/README.md create mode 100644 java/samples/sample-code/pom.xml create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example99_BlogAnnouncement.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example_PlanWithNativeFunctions.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/SamplesConfig.java create mode 100755 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example00_GettingStarted.java create mode 100755 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example02_RunningPromptsFromFile.java create mode 100755 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example03_SemanticFunctionInline.java create mode 100755 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example04_ContextVariablesChat.java create mode 100755 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example05_UsingThePlanner.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example01_NativeFunctions.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example02_Pipeline.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example03_Variables.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example04_CombineLLMPromptsAndNativeCode.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example05_InlineFunctionDefinition.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example06_TemplateLanguage.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example08_RetryHandler.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example09_FunctionTypes.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example12_SequentialPlanner.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example13_ConversationSummarySkill.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example14_SemanticMemory.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example15_MemorySkill.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example17_ChatGPT.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example25_ReadOnlyMemoryStore.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example28_ActionPlanner.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example29_Tokenizer.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example33_StreamingChat.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example51_StepwisePlanner.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/SampleSkillsUtil.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Java_Example01_ResourceLoading.java create mode 100644 java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/SequentialPlanner_AnswerQuestion.java create mode 100644 java/samples/sample-code/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/config.json create mode 100644 java/samples/sample-code/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/skprompt.txt create mode 100644 java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/config.json create mode 100644 java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/skprompt.txt create mode 100644 java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/config.json create mode 100644 java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt create mode 100644 java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/require_context_variable_planner_prompt.txt create mode 100644 java/samples/sample-code/src/main/resources/log4j2.xml create mode 100644 java/samples/semantickernel-samples-guice/pom.xml create mode 100644 java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/CompletionFunctionFactory.java create mode 100644 java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/Config.java create mode 100644 java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/SemanticKernelModule.java create mode 100644 java/samples/semantickernel-samples-guice/src/test/java/com/microsoft/semantickernel/guice/CompletionFunctionExample.java create mode 100644 java/samples/semantickernel-samples-guice/src/test/java/com/microsoft/semantickernel/guice/GuiceEmbeddingExample.java create mode 100644 java/semantickernel-api/pom.xml create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelConfig.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKBuilders.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKCheckedException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SkillExecutor.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Verify.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/AIException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/Embedding.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/EmbeddingGeneration.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/TextEmbeddingGeneration.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/VectorOperations.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/Buildable.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/BuildersSingleton.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SemanticKernelBuilder.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/ServiceLoadUtil.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatCompletion.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatHistory.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatRequestSettings.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/ConfigurationException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/NotSupportedException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SkillsNotFoundException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/extensions/KernelExtensions.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/DataEntryBase.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryQueryResult.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecord.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecordMetadata.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryStore.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/NullMemory.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/SemanticTextMemory.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSKContext.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSkFunction.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ContextVariables.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionNotRegisteredException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/RegistrableSkFunction.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKContext.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKFunction.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/WritableContextVariables.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/planner/PlanningException.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateConfig.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/SemanticFunctionConfig.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIService.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceCollection.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceProvider.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/DefaultAIServiceProvider.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/DefaultNamedServiceProvider.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/NamedServiceProvider.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionNotFound.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionView.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/KernelSkillsSupplier.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ParameterView.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlyFunctionCollection.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlySkillCollection.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/DefineSKFunction.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/SKFunctionInputAttribute.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/SKFunctionParameters.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/PromptTemplateEngine.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/blocks/Block.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/blocks/BlockTypes.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionRequestSettings.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKFunction.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionType.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/TextCompletion.java create mode 100644 java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/EmbeddedResourceLoader.java create mode 100644 java/semantickernel-bom/pom.xml create mode 100644 java/semantickernel-core/pom.xml create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/DefaultKernel.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/SkFunctionBuilders.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/coreskills/SkillImporter.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/DefaultSemanticTextMemory.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/MemoryConfiguration.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/VolatileMemoryStore.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKFunction.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultContextVariables.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSKContext.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKFunction.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultTextCompletionSupplier.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/NativeSKFunction.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKNativeTask.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKSemanticAsyncTask.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKTask.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/semanticfunctions/DefaultPromptTemplate.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/CaseInsensitiveMap.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/DefaultSkillCollection.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionCollection.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/CodeTokenizer.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/DefaultPromptTemplateEngine.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/TemplateException.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/TemplateTokenizer.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/CodeBlock.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/CodeRendering.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/FunctionIdBlock.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/Symbols.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/TextBlock.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/TextRendering.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/ValBlock.java create mode 100644 java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/VarBlock.java create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.Kernel$Builder create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.builders.FunctionBuilders create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.memory.MemoryStore$Builder create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.ContextVariables$Builder create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.SKContext$Builder create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.WritableContextVariables$Builder create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.semanticfunctions.PromptTemplate$Builder create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection$Builder create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.templateengine.PromptTemplateEngine$Builder create mode 100644 java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.textcompletion.CompletionSKFunction$Builder create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/AiServiceRegistryTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/DefaultKernelTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/TextEmbeddingsTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletionTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/MemoryExceptionTests.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/MemoryRecordTests.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/VolatileMemoryStoreTests.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/orchestration/NativeSKFunctionTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlannerTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/planner/stepwiseplanner/StepwisePlannerTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example01NativeFunctionsTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example02PipelineTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example03VariablesTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example04CombineLLMPromptsAndNativeCodeTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example05UsingThePlannerTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example06TemplateLanguageTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example12SequentialPlannerTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example13ConversationSummarySkillTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example17ChatGPTTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example28ActionPlannerTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example33StreamingChatTest.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Examples.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/skills/SearchEngineSkill.java create mode 100644 java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/skills/StaticTextSkill.java create mode 100644 java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response1.txt create mode 100644 java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response2.txt create mode 100644 java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response3.txt create mode 100644 java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response4.txt create mode 100644 java/semantickernel-core/src/test/resources/log4j2.xml create mode 100644 java/semantickernel-core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100644 java/semantickernel-extensions-parent/pom.xml create mode 100644 java/semantickernel-extensions-parent/semantickernel-sequentialplanner-extension/pom.xml create mode 100644 java/spotbugs-exclude.xml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a3f6d583cd..5272af4ada 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -6,9 +6,9 @@ name: "CodeQL" on: push: - branches: [ "main", "experimental*", "feature*" ] + branches: ["main", "experimental*", "feature*", "*-development"] schedule: - - cron: '17 11 * * 2' + - cron: "17 11 * * 2" jobs: analyze: @@ -22,45 +22,58 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'csharp', 'python' ] + language: ["csharp", "python", "java"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Use only 'java' to analyze code written in Java, Kotlin or both # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + if: ${{ matrix.language != 'java' }} + uses: github/codeql-action/autobuild@v2 - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + - name: Setup JDK + uses: actions/setup-java@v3 + if: ${{ matrix.language == 'java' }} + with: + java-version: 17 + distribution: microsoft + cache: maven - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - name: Build Java + if: ${{ matrix.language == 'java' }} + run: ./mvnw -B -DskipTests -Pcompile-jdk17 clean install --file pom.xml + working-directory: java - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/java-build.yml b/.github/workflows/java-build.yml new file mode 100644 index 0000000000..e5ca4090e3 --- /dev/null +++ b/.github/workflows/java-build.yml @@ -0,0 +1,84 @@ +name: Build Java Semantic Kernel + +on: + workflow_dispatch: + push: + branches: [ "main", "java-development" ] + paths: + - 'java/**' + pull_request: + branches: [ "main", "java-development" ] + paths: + - 'java/**' + +permissions: + contents: read + +jobs: + paths-filter: + runs-on: ubuntu-latest + outputs: + javaChanges: ${{ steps.filter.outputs.java }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + java: + - 'java/**' + - '**/java/**' + # run only if 'java' files were changed + - name: java tests + if: steps.filter.outputs.java == 'true' + run: echo "Java file" + # run only if not 'java' files were changed + - name: not java tests + if: steps.filter.outputs.java != 'true' + run: echo "NOT java file" + java-build: + runs-on: ubuntu-latest + needs: paths-filter + if: needs.paths-filter.outputs.javaChanges == 'true' + strategy: + fail-fast: false + matrix: + java-versions: [8, 17] + + name: Java CI on JDK${{ matrix.java-versions }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + # Need to use JDK 11 to build for JDK 8 + - name: Set JDK + id: set-jdk + shell: bash + run: | + if [[ ${{ matrix.java-versions }} == 8 ]]; then + echo "JDK_VERSION=11" >> $GITHUB_OUTPUT + else + version=${{ matrix.java-versions }} + echo "JDK_VERSION=$version" >> $GITHUB_OUTPUT + fi + + - uses: actions/setup-java@v3 + with: + java-version: ${{ steps.set-jdk.outputs.JDK_VERSION }} + distribution: microsoft + cache: maven + + - name: Build with Maven + run: ./mvnw -B -Pbug-check -DskipTests -Pcompile-jdk${{ matrix.java-versions }} clean install --file pom.xml + working-directory: java + + - name: Run tests + run: ./mvnw -B -Pbug-check -Pcompile-jdk${{ matrix.java-versions }} test --file pom.xml + working-directory: java + + - uses: actions/upload-artifact@v2 + if: always() + with: + name: test_output_sk_jdk${{ matrix.java-versions }}u + path: java/**/target/surefire-reports/*Test.txt diff --git a/.github/workflows/java-integration-tests.yml b/.github/workflows/java-integration-tests.yml new file mode 100644 index 0000000000..fba52abaa5 --- /dev/null +++ b/.github/workflows/java-integration-tests.yml @@ -0,0 +1,91 @@ +name: Run Java Integration Tests and Samples + +on: + workflow_dispatch: + push: + branches: [ "main", "java-development" ] + paths: + - 'java/**' + pull_request: + branches: [ "main", "java-development" ] + paths: + - 'java/**' + +permissions: + contents: read + +jobs: + paths-filter: + runs-on: ubuntu-latest + outputs: + javaChanges: ${{ steps.filter.outputs.java }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + java: + - 'java/**' + - '**/java/**' + # run only if 'java' files were changed + - name: java tests + if: steps.filter.outputs.java == 'true' + run: echo "Java file" + # run only if not 'java' files were changed + - name: not java tests + if: steps.filter.outputs.java != 'true' + run: echo "NOT java file" + java-integration-tests: + runs-on: ubuntu-latest + needs: paths-filter + if: needs.paths-filter.outputs.javaChanges == 'true' + strategy: + fail-fast: false + matrix: + java-versions: [8, 17] + + name: Java Tests on JDK${{ matrix.java-versions }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + # Need to use JDK 11 to build for JDK 8 + - name: Set JDK + id: set-jdk + shell: bash + run: | + if [[ ${{ matrix.java-versions }} == 8 ]]; then + echo "JDK_VERSION=11" >> $GITHUB_OUTPUT + else + version=${{ matrix.java-versions }} + echo "JDK_VERSION=$version" >> $GITHUB_OUTPUT + fi + + - uses: actions/setup-java@v3 + with: + java-version: ${{ steps.set-jdk.outputs.JDK_VERSION }} + distribution: microsoft + cache: maven + + - name: Build with Maven + run: ./mvnw -B -Pbug-check -DskipTests -Pcompile-jdk${{ matrix.java-versions }} clean install --file pom.xml + working-directory: java + + # API tests run on JDK 17+ + - name: Run integration tests + run: ../mvnw -B -Pbug-check clean install --file pom.xml + working-directory: java/api-test + env: + OPENAI_API_KEY: "" + AZURE_OPENAI_ENDPOINT: "" + AZURE_OPENAI_API_KEY: "" + AZURE_OPENAI_DEPLOYMENT_NAME: "" + if: ${{ matrix.java-versions >= 17 }} + + # Samples build on JDK 17+ + - name: Build semantic-kernel samples + run: ../mvnw -B clean install --file pom.xml + working-directory: java/samples + if: ${{ matrix.java-versions >= 17 }} diff --git a/java/.mvn/jvm.config b/java/.mvn/jvm.config new file mode 100644 index 0000000000..32599cefea --- /dev/null +++ b/java/.mvn/jvm.config @@ -0,0 +1,10 @@ +--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED diff --git a/java/.mvn/wrapper/maven-wrapper.properties b/java/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..6d3a56651d --- /dev/null +++ b/java/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/java/.vscode/settings.json b/java/.vscode/settings.json new file mode 100644 index 0000000000..a63ac867ca --- /dev/null +++ b/java/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.compile.nullAnalysis.mode": "automatic" +} \ No newline at end of file diff --git a/java/PACKAGES.md b/java/PACKAGES.md new file mode 100644 index 0000000000..b781350690 --- /dev/null +++ b/java/PACKAGES.md @@ -0,0 +1,154 @@ +# Semantic Kernel for Java Packages + +The Semantic Kernel has the packages below, all are under the groupId `com.microsoft.semantic-kernel`, and can be imported +to maven. + +```xml + + com.microsoft.semantic-kernel + semantickernel-api + +``` + +A BOM is provided that can be used to define the versions of all Semantic Kernel packages. + +```xml + + + + com.microsoft.semantic-kernel + semantickernel-bom + ${semantickernel.version} + import + pom + + + +``` + +## Common Packages + +`semantickernel-bom` +: A Maven project BOM that can be used to define the versions of all Semantic Kernel packages. + +`semantickernel-api` +: Package that defines the core public API for the Semantic Kernel for a Maven project. + +`semantickernel-core` +: The internal implementation of the Semantic Kernel API. +This package contains the core implementation of the Semantic Kernel. This must be made available to the +application at runtime. Note that these classes are considered internal and should not be used directly by the application. Should they be used directly, it could cause instability in the application as they may change without notice over time. + +## Connectors + +`semantickernel-connectors-ai-openai` +: Provides a connector that can be used to interact with the OpenAI API. + +### Memory Connectors + +#### JDBC Memory Connectors + +`semantickernel-connectors-memory-jdbc` +: A package that serves as a parent for all JDBC based connectors, adding a new JDBC database should be a matter of extending the classes within this module. + +Provides a memory connector that can be used to interact with a JDBC database. +- `semantickernel-connectors-memory-sqlite` +- `semantickernel-connectors-memory-postgresql` +- `semantickernel-connectors-memory-mysql` + +`semantickernel-connectors-memory-azurecognitivesearch` +: Provides a memory connector for using Azure Cognitive Search as the memory provider for an application. + +### Miscellaneous Packages + +`semantickernel-planners` +: Implementations of various planners that can be used in the execution of semantic functions. + +`semantickernel-plugin-core` +: Several example plugins, many of which are used in the [Semantic Kernel for Java samples](./samples). + +`semantickernel-gpt3-tokenizer` +: A tokenizer that can be used to tokenize text for use with GPT-3. Can be used to estimate cost. + + +## Example Configurations + +### Example: OpenAI + SQLite + +POM XML for a simple project that uses OpenAI for text or chat completion with an SQLite database as the memory provider. + +```xml + + + + com.microsoft.semantic-kernel + semantickernel-bom + ${semantickernel.version} + import + pom + + + + + + com.microsoft.semantic-kernel + semantickernel-api + + + com.microsoft.semantic-kernel + semantickernel-core + runtime + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-sqlite + + +``` + +### Example: Planner using Open AI + Cognitive Search + +The POM XML content for a project that uses Open AI for planning, using Azure Cognitive Search as the memory provider. + +```xml + + + + com.microsoft.semantic-kernel + semantickernel-bom + ${semantickernel.version} + import + pom + + + + + + com.microsoft.semantic-kernel + semantickernel-api + + + com.microsoft.semantic-kernel + semantickernel-core + runtime + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-azurecognitivesearch + + + com.microsoft.semantic-kernel + semantickernel-planners + + +``` + + diff --git a/java/README.md b/java/README.md new file mode 100644 index 0000000000..83f312fb4c --- /dev/null +++ b/java/README.md @@ -0,0 +1,103 @@ +# Semantic Kernel for Java + +Semantic Kernel (SK) is a lightweight foundation that lets you easily mix conventional programming languages with the latest in +Large Language Model (LLM) AI "prompts" with templating, chaining, and planning capabilities out-of-the-box. + +To learn more about Microsoft Semantic Kernel, visit +the [Microsoft Semantic Kernel documentation](https://learn.microsoft.com/en-us/semantic-kernel/whatissk). + +The Microsoft Semantic Kernel for Java is a library that implements the key concepts and foundations of Microsoft Semantic Kernel. It is designed +to be used in Java applications in both client (desktop, mobile, CLIs) and server environments in an idiomatic way, and to be easily integrated with other Java libraries +and frameworks. + +## Get started + +To run the LLM prompts and semantic functions in this kernel, make sure you have +an [Open AI API Key](https://openai.com/api/) +or [Azure Open AI service key](https://learn.microsoft.com/azure/cognitive-services/openai/). + +### Requirements + +To build the Semantic Kernel for Java, you will need: + +- **Required**: + - [OpenJDK 17](https://microsoft.com/openjdk/) or newer + +### Build the Semantic Kernel + +1. Clone this repository + + git clone -b java-development https://github.com/microsoft/semantic-kernel/ + +2. Build the project with the Maven Wrapper + + cd semantic-kernel/java + ./mvnw install + +## Using the Semantic Kernel for Java + +The library is organized in a set of dependencies published to Maven Central. For a list of the Maven dependencies and how to use each of them, see [PACKAGES.md](PACKAGES.md). + +Alternatively, check the `samples` folder for examples of common AI-enabled scenarios implemented with Semantic Kernel for Java. + +## Discord community + +Join the [Microsoft Semantic Kernel Discord community](https://aka.ms/java-sk-discord) to discuss the Semantic Kernel +and get help from the community. We have a `#java` channel for Java-specific questions. + +## Contributing + +### Testing locally + +The project may contain end-to-end tests that require an OpenAI key to run. To run these tests locally, you +will need to set the following environment variable: + +- `OPENAI_API_KEY` - the OpenAI API key. + +If you are using Azure OpenAI, you will also need to set the following environment variables: + +- `AZURE_OPENAI_ENDPOINT` - the Azure OpenAI endpoint found in **Keys * Endpoint** section of the Azure OpenAI service. +- `AZURE_OPENAI_API_KEY` - the Azure OpenAI API key found in **Keys * Endpoint** section of the Azure OpenAI service. +- `AZURE_OPENAI_DEPLOYMENT_NAME` - the custom name you chose for your deployment when you deployed a model. It can be + found under **Resource Management > Deployments** in the Azure Portal. + +For more information, see the Azure OpenAI documentation +on [how to get your Azure OpenAI credentials](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart?pivots=rest-api&tabs=command-line#retrieve-key-and-endpoint). + +To run the unit tests only, run the following command: + + ./mvnw package + +To run all tests, including integration tests that require an OpenAI key, run the following command: + + ./mvnw verify + +### Submitting a pull request + +Before submitting a pull request, please make sure that you have run the project with the command: + +```shell +./mvnw clean package -Pbug-check +``` + +The bug-check profile will detect some static analysis issues that will prevent merging as well as apply formatting +requirements to the code base. + +Also ensure that: + +- All new code is covered by unit tests +- All new code is covered by integration tests + +Once your proposal is ready, submit a pull request to the `java-development` branch. The pull request will be reviewed by the +project maintainers. + +Make sure your pull request has an objective title and a clear description explaining the problem and solution. + +## License + +This project is licensed under the [MIT License](../LICENSE). + +## Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](../CODE_OF_CONDUCT.md). + diff --git a/java/api-test/api-usage-example/pom.xml b/java/api-test/api-usage-example/pom.xml new file mode 100644 index 0000000000..20472bdd94 --- /dev/null +++ b/java/api-test/api-usage-example/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel.test + api-test + 0.2.10-alpha-SNAPSHOT + ../pom.xml + + + api-usage-example + jar + + + + com.microsoft.semantic-kernel + semantickernel-core + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + + + org.apache.logging.log4j + log4j-slf4j2-impl + + + \ No newline at end of file diff --git a/java/api-test/api-usage-example/src/main/java/InlineFunctionExample.java b/java/api-test/api-usage-example/src/main/java/InlineFunctionExample.java new file mode 100644 index 0000000000..1080c79847 --- /dev/null +++ b/java/api-test/api-usage-example/src/main/java/InlineFunctionExample.java @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft. All rights reserved. +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class InlineFunctionExample { + public static final String AZURE_CONF_PROPERTIES = "conf.properties"; + private static final Logger LOGGER = LoggerFactory.getLogger(InlineFunctionExample.class); + private static final String MODEL = "text-davinci-003"; + + private static final String API_KEY; + private static final String ENDPOINT; + private static final String TEXT_TO_SUMMARIZE = + """ + Demo (ancient Greek poet) + From Wikipedia, the free encyclopedia + Demo or Damo (Greek: ΔÎĩÎŧĪŽ, ΔαÎŧĪŽ; fl. c. AD 200) was a Greek woman of the + Roman period, known for a single epigram, engraved upon the Colossus of + Memnon, which bears her name. She speaks of herself therein as a lyric + poetess dedicated to the Muses, but nothing is known of her life.[1] + Identity + Demo was evidently Greek, as her name, a traditional epithet of Demeter, + signifies. The name was relatively common in the Hellenistic world, in + Egypt and elsewhere, and she cannot be further identified. The date of her + visit to the Colossus of Memnon cannot be established with certainty, but + internal evidence on the left leg suggests her poem was inscribed there at + some point in or after AD 196.[2] + Epigram + There are a number of graffiti inscriptions on the Colossus of Memnon. + Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac + couplets, entitled and presumably authored by "Demo" or "Damo" (the + Greek inscription is difficult to read), is a dedication to the Muses.[2] + The poem is traditionally published with the works of Balbilla, though the + internal evidence suggests a different author.[1] + In the poem, Demo explains that Memnon has shown her special respect. In + return, Demo offers the gift for poetry, as a gift to the hero. At the end + of this epigram, she addresses Memnon, highlighting his divine status by + recalling his strength and holiness.[2] + Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic + dialect. The language indicates she was knowledgeable in Homeric + poetry—'bearing a pleasant gift', for example, alludes to the use of that + phrase throughout the Iliad and Odyssey.[a][2]; + """; + + static { + try { + API_KEY = getToken(); + ENDPOINT = getEndpoint(); + } catch (IOException e) { + throw new ExceptionInInitializerError( + "Error reading config file or properties. " + e.getMessage()); + } + } + + private static String getToken() throws IOException { + return getConfigValue("token"); + } + + private static String getEndpoint() throws IOException { + return getConfigValue("endpoint"); + } + + private static String getConfigValue(String propertyName) throws IOException { + String propertyValue; + Path configPath = Paths.get(System.getProperty("user.home"), ".oai", AZURE_CONF_PROPERTIES); + Properties props = new Properties(); + try (var reader = Files.newBufferedReader(configPath)) { + props.load(reader); + propertyValue = props.getProperty(propertyName); + if (propertyValue == null || propertyValue.isEmpty()) { + throw new IOException("No property for: " + propertyName + " in " + configPath); + } + } catch (IOException e) { + throw new IOException("Please create a file at " + configPath, e); + } + return propertyValue; + } + + public static void main(String[] args) { + OpenAIAsyncClient client = + new OpenAIClientBuilder() + .endpoint(ENDPOINT) + .credential(new AzureKeyCredential(API_KEY)) + .buildAsyncClient(); + + TextCompletion textCompletion = + SKBuilders.textCompletion().withOpenAIClient(client).withModelId(MODEL).build(); + String prompt = "{{$input}}\n" + "Summarize the content above."; + + Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build(); + + CompletionSKFunction summarize = + kernel.getSemanticFunctionBuilder() + .withPromptTemplate(prompt) + .withFunctionName("summarize") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000)) + .build(); + + if (summarize == null) { + LOGGER.error("Null function"); + return; + } + + CountDownLatch cdl = new CountDownLatch(1); + summarize + .invokeAsync(TEXT_TO_SUMMARIZE) + .subscribe( + context -> LOGGER.info("Result: {} ", context.getResult()), + error -> { + LOGGER.error("Error: {} ", error.getMessage()); + cdl.countDown(); + }, + () -> { + LOGGER.info("Completed"); + cdl.countDown(); + }); + try { + cdl.await(); + } catch (InterruptedException e) { + LOGGER.error("Error: {} ", e.getMessage()); + } + } +} diff --git a/java/api-test/api-usage-example/src/main/java/InlineFunctionWithPreBuiltSkillExample.java b/java/api-test/api-usage-example/src/main/java/InlineFunctionWithPreBuiltSkillExample.java new file mode 100644 index 0000000000..f828d08929 --- /dev/null +++ b/java/api-test/api-usage-example/src/main/java/InlineFunctionWithPreBuiltSkillExample.java @@ -0,0 +1,139 @@ +// Copyright (c) Microsoft. All rights reserved. +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class InlineFunctionWithPreBuiltSkillExample { + public static final String AZURE_CONF_PROPERTIES = "conf.properties"; + private static final Logger LOGGER = + LoggerFactory.getLogger(InlineFunctionWithPreBuiltSkillExample.class); + private static final String MODEL = "text-davinci-003"; + + private static final String API_KEY; + private static final String ENDPOINT; + private static final String TEXT_TO_SUMMARIZE = + """ + Demo (ancient Greek poet) + From Wikipedia, the free encyclopedia + Demo or Damo (Greek: ΔÎĩÎŧĪŽ, ΔαÎŧĪŽ; fl. c. AD 200) was a Greek woman of the + Roman period, known for a single epigram, engraved upon the Colossus of + Memnon, which bears her name. She speaks of herself therein as a lyric + poetess dedicated to the Muses, but nothing is known of her life.[1] + Identity + Demo was evidently Greek, as her name, a traditional epithet of Demeter, + signifies. The name was relatively common in the Hellenistic world, in + Egypt and elsewhere, and she cannot be further identified. The date of her + visit to the Colossus of Memnon cannot be established with certainty, but + internal evidence on the left leg suggests her poem was inscribed there at + some point in or after AD 196.[2] + Epigram + There are a number of graffiti inscriptions on the Colossus of Memnon. + Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac + couplets, entitled and presumably authored by "Demo" or "Damo" (the + Greek inscription is difficult to read), is a dedication to the Muses.[2] + The poem is traditionally published with the works of Balbilla, though the + internal evidence suggests a different author.[1] + In the poem, Demo explains that Memnon has shown her special respect. In + return, Demo offers the gift for poetry, as a gift to the hero. At the end + of this epigram, she addresses Memnon, highlighting his divine status by + recalling his strength and holiness.[2] + Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic + dialect. The language indicates she was knowledgeable in Homeric + poetry—'bearing a pleasant gift', for example, alludes to the use of that + phrase throughout the Iliad and Odyssey.[a][2]; + """; + + static { + try { + API_KEY = getToken(); + ENDPOINT = getEndpoint(); + } catch (IOException e) { + throw new ExceptionInInitializerError( + "Error reading config file or properties. " + e.getMessage()); + } + } + + public static String getToken() throws IOException { + return getConfigValue("token"); + } + + public static String getEndpoint() throws IOException { + return getConfigValue("endpoint"); + } + + private static String getConfigValue(String propertyName) throws IOException { + String propertyValue; + Path configPath = Paths.get(System.getProperty("user.home"), ".oai", AZURE_CONF_PROPERTIES); + Properties props = new Properties(); + try (var reader = Files.newBufferedReader(configPath)) { + props.load(reader); + propertyValue = props.getProperty(propertyName); + if (propertyValue == null || propertyValue.isEmpty()) { + throw new IOException("No property for: " + propertyName + " in " + configPath); + } + } catch (IOException e) { + throw new IOException("Please create a file at " + configPath, e); + } + return propertyValue; + } + + public static void main(String[] args) { + OpenAIAsyncClient client = + new OpenAIClientBuilder() + .endpoint(ENDPOINT) + .credential(new AzureKeyCredential(API_KEY)) + .buildAsyncClient(); + + TextCompletion textCompletion = + SKBuilders.textCompletion().withOpenAIClient(client).withModelId(MODEL).build(); + String prompt = "{{$input}}\nSummarize the content above."; + + Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build(); + + CompletionSKFunction summarize = + SKBuilders.completionFunctions() + .withKernel(kernel) + .withPromptTemplate(prompt) + .withFunctionName("summarize") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000)) + .build(); + + if (summarize == null) { + LOGGER.error("Null function"); + return; + } + + CountDownLatch cdl = new CountDownLatch(1); + summarize + .invokeAsync(TEXT_TO_SUMMARIZE) + .subscribe( + context -> LOGGER.info("Result: {} ", context.getResult()), + error -> { + LOGGER.error("Error: {} ", error.getMessage()); + cdl.countDown(); + }, + () -> { + LOGGER.info("Completed"); + cdl.countDown(); + }); + try { + cdl.await(); + } catch (InterruptedException e) { + LOGGER.error("Error: {} ", e.getMessage()); + } + } +} diff --git a/java/api-test/api-usage-example/src/main/resources/log4j2.xml b/java/api-test/api-usage-example/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..50a638f0dc --- /dev/null +++ b/java/api-test/api-usage-example/src/main/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/api-test/integration-tests/pom.xml b/java/api-test/integration-tests/pom.xml new file mode 100644 index 0000000000..09da67e296 --- /dev/null +++ b/java/api-test/integration-tests/pom.xml @@ -0,0 +1,133 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel.test + api-test + 0.2.10-alpha-SNAPSHOT + ../pom.xml + + + integration-tests + jar + + + + com.microsoft.semantic-kernel + semantickernel-core + test + + + org.apache.logging.log4j + log4j-api + test + + + org.apache.logging.log4j + log4j-core + test + + + org.apache.logging.log4j + log4j-slf4j2-impl + test + + + org.mockito + mockito-core + test + + + org.junit.jupiter + junit-jupiter + test + + + org.junit.jupiter + junit-jupiter-api + test + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + test + + + com.microsoft.semantic-kernel + semantickernel-planners + test + + + com.microsoft.semantic-kernel + semantickernel-plugin-core + test + + + com.microsoft.semantic-kernel + sample-code + ${project.version} + + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-jdbc + ${project.version} + test + + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-postgresql + ${project.version} + test + + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-mysql + ${project.version} + test + + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-sqlite + ${project.version} + test + + + + org.xerial + sqlite-jdbc + + + org.testcontainers + junit-jupiter + test + + + org.testcontainers + postgresql + test + + + org.testcontainers + mysql + test + + + + + + + org.testcontainers + testcontainers-bom + 1.18.3 + pom + import + + + + \ No newline at end of file diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCMemoryStoreTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCMemoryStoreTest.java new file mode 100644 index 0000000000..9f6903e0ae --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCMemoryStoreTest.java @@ -0,0 +1,721 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.jdbc; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.memory.MemoryException; +import com.microsoft.semantickernel.memory.MemoryRecord; +import com.microsoft.semantickernel.memory.MemoryStore; +import java.awt.*; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Flux; +import reactor.util.function.Tuple2; + +public class JDBCMemoryStoreTest { + + private static JDBCMemoryStore.Builder builder; + private static MemoryStore db; + private static int collectionNum = 0; + private static final String NULL_ADDITIONAL_METADATA = null; + private static final String NULL_KEY = null; + private static final ZonedDateTime NULL_TIMESTAMP = null; + + @BeforeAll + static void setUp() throws SQLException { + builder = new JDBCMemoryStore.Builder() + .withConnection(DriverManager.getConnection("jdbc:sqlite::memory:")); + db = builder.buildAsync().block(); + } + + private Collection createBatchRecords(int numRecords) { + assertTrue(numRecords % 2 == 0, "Number of records must be even"); + assertTrue(numRecords > 0, "Number of records must be greater than 0"); + + List records = new ArrayList<>(numRecords); + for (int i = 0; i < numRecords / 2; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + for (int i = numRecords / 2; i < numRecords; i++) { + MemoryRecord testRecord = + MemoryRecord.referenceRecord( + "test" + i, + "sourceName" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + return records; + } + + @Test + void initializeDbConnectionSucceeds() { + assertNotNull(db); + } + + @Test + void itDoesNotFailWithExistingTables() { + // Act + db = builder.buildAsync().block(); + + // Assert + assertNotNull(db); + } + + @Test + void itCanCreateAndGetCollectionAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + Collection collections = db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertFalse(collections.isEmpty()); + assertTrue(collections.contains(collection)); + } + + @Test + void itHandlesExceptionsWhenCreatingCollectionAsync() { + // Arrange + String collection = null; + + // Assert + assertThrows( + NullPointerException.class, + () -> db.createCollectionAsync(collection).block(), + "Should not be able to create collection with null name"); + } + + @Test + void itCannotInsertIntoNonExistentCollectionAsync() { + + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Assert + assertThrows( + MemoryException.class, + () -> db.upsertAsync(collection, testRecord).block(), + "Should not be able to insert into a non-existent collection"); + } + + @Test + void getAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actualDefault = db.getAsync(collection, key, false).block(); + MemoryRecord actualWithEmbedding = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actualDefault); + assertNotNull(actualDefault.getEmbedding()); + assertNotNull(actualDefault.getEmbedding().getVector()); + assertTrue(actualDefault.getEmbedding().getVector().isEmpty()); + assertNotNull(actualWithEmbedding); + assertNotNull(actualWithEmbedding.getEmbedding()); + assertNotNull(actualWithEmbedding.getEmbedding().getVector()); + assertFalse(actualWithEmbedding.getEmbedding().getVector().isEmpty()); + assertNotEquals(testRecord, actualDefault); + assertEquals(testRecord.getMetadata(), actualWithEmbedding.getMetadata()); + assertEquals( + testRecord.getEmbedding().getVector(), + actualWithEmbedding.getEmbedding().getVector()); + } + + @Test + void itCanUpsertAndRetrieveARecordWithNoTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord.getMetadata(), actual.getMetadata()); + assertEquals(testRecord.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void itCanUpsertAndRetrieveARecordWithTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + ZonedDateTime.now(ZoneId.of("UTC"))); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord.getMetadata(), actual.getMetadata()); + assertEquals(testRecord.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void upsertReplacesExistingRecordWithSameIdAsync() { + // Arrange + String commonId = "test"; + MemoryRecord testRecord = + MemoryRecord.localRecord( + commonId, + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + MemoryRecord testRecord2 = + MemoryRecord.localRecord( + commonId, + "text2", + "description2", + new Embedding(Arrays.asList(1f, 2f, 4f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + String key2 = db.upsertAsync(collection, testRecord2).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertNotEquals(testRecord2, actual); + assertEquals(key, key2); + assertEquals(testRecord2.getMetadata(), actual.getMetadata()); + assertEquals(testRecord2.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void existingRecordCanBeRemovedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + assertNotNull(key); + db.removeAsync(collection, key).block(); + MemoryRecord actual = db.getAsync(collection, key, false).block(); + + // Assert + assertNull(actual); + } + + @Test + void removingNonExistingRecordDoesNothingAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.removeAsync(collection, "key").block(); + MemoryRecord actual = db.getAsync(collection, "key", false).block(); + + // Assert + assertNull(actual); + } + + @Test + void itCanListAllDatabaseCollectionsAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(collectionNum, collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Collection collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + int initialSize = collections.size(); + + Flux.fromArray(testCollections) + .concatMap(collection -> db.createCollectionAsync(collection)) + .blockLast(); + + // Act + collections = db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertEquals(initialSize + numCollections, collections.size()); + for (String collection : testCollections) { + assertTrue( + collections.contains(collection), + "Collections does not contain the newly-created collection " + collection); + } + } + + private String setUpNearestMatches() { + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + return collection; + } + + @Test + void getNearestMatchesReturnsAllResultsWithNoMinScoreAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, topN, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertEquals(topN, topNResults.size()); + Tuple2[] topNResultsArray = topNResults.toArray(new Tuple2[0]); + for (int j = 0; j < topN - 1; j++) { + int compare = + Double.compare(topNResultsArray[j].getT2(), topNResultsArray[j + 1].getT2()); + assertTrue(compare >= 0); + } + } + + @Test + void getNearestMatchesReturnsLimit() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfLimitZero() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync( + collection, compareEmbedding, Integer.MAX_VALUE, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + + String collection = setUpNearestMatches(); + + // Act + float threshold = 0.75f; + Tuple2 topNResultDefault = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + Tuple2 topNResultWithEmbedding = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, true).block(); + + // Assert + assertNotNull(topNResultDefault); + assertNotNull(topNResultWithEmbedding); + assertNotNull(topNResultDefault.getT1().getEmbedding()); + assertNotNull(topNResultDefault.getT1().getEmbedding().getVector()); + assertTrue(topNResultDefault.getT1().getEmbedding().getVector().isEmpty()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding().getVector()); + assertFalse(topNResultWithEmbedding.getT1().getEmbedding().getVector().isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsExpectedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = setUpNearestMatches(); + + // Act + float threshold = 0.75f; + Tuple2 topNResult = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + + // Assert + assertNotNull(topNResult); + assertEquals("test0", topNResult.getT1().getMetadata().getId()); + assertTrue(topNResult.getT2() >= threshold); + } + + @Test + void getNearestMatcheReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Tuple2 topNResults = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + + // Assert + assertNull(topNResults); + } + + @Test + void getNearestMatchesDifferentiatesIdenticalVectorsByKeyAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + for (int i = 0; i < 10; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + } + + // Act + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, topN, 0.75f, true).block(); + Collection topNKeys = + topNResults.stream() + .map(tuple -> tuple.getT1().getKey()) + .sorted() + .collect(Collectors.toList()); + + // Assert + assertEquals(topN, topNResults.size()); + assertEquals(topN, topNKeys.size()); + for (Iterator> iterator = topNResults.iterator(); + iterator.hasNext(); ) { + Tuple2 tuple = iterator.next(); + int compare = Float.compare(tuple.getT2(), 0.75f); + assertTrue(topNKeys.contains(tuple.getT1().getKey())); + assertTrue(compare >= 0); + } + } + + @Test + void itCanBatchUpsertRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + // Act + Collection keys = db.upsertBatchAsync(collection, records).block(); + Collection resultRecords = db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertEquals(numRecords, keys.size()); + assertEquals(numRecords, resultRecords.size()); + } + + @Test + void itCanBatchGetRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + Collection keys = db.upsertBatchAsync(collection, records).block(); + + // Act + Collection results = db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertNotNull(results); + assertEquals(numRecords, results.size()); + } + + @Test + void itCanBatchRemoveRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + List keys = new ArrayList<>(); + for (String key : db.upsertBatchAsync(collection, records).block()) { + keys.add(key); + } + + // Act + db.removeBatchAsync(collection, keys).block(); + + // Assert + for (MemoryRecord result : db.getBatchAsync(collection, keys, true).block()) { + assertNull(result); + } + } + + @Test + void collectionsCanBeDeletedAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(collectionNum, collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Collection collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + int initialSize = collections.size(); + + Flux.fromArray(testCollections) + .concatMap(collection -> db.createCollectionAsync(collection)) + .blockLast(); + collectionNum += numCollections; + + // Act + collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(initialSize + numCollections, collections.size()); + + // Act + for (String collection : collections) { + db.deleteCollectionAsync(collection).block(); + } + + // Assert + collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(0, collections.size()); + } + + @Test + void itThrowsWhenDeletingNonExistentCollectionAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + assertThrows(MemoryException.class, () -> db.deleteCollectionAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnTrueForExistingCollection() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + assertTrue(db.doesCollectionExistAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnFalseForNonExistentCollection() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + assertFalse(db.doesCollectionExistAsync(collection).block()); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLMemoryStoreTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLMemoryStoreTest.java new file mode 100644 index 0000000000..f021ba731a --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLMemoryStoreTest.java @@ -0,0 +1,720 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.mysql; + +import static org.junit.jupiter.api.Assertions.*; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.memory.MemoryException; +import com.microsoft.semantickernel.memory.MemoryRecord; +import com.microsoft.semantickernel.memory.MemoryStore; +import java.io.IOException; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import reactor.core.publisher.Flux; +import reactor.util.function.Tuple2; + +@Testcontainers +public class MySQLMemoryStoreTest { + @Container private static final MySQLContainer CONTAINER = new MySQLContainer(); + private static final String MYSQL_USER = "test"; + private static final String MYSQL_PASSWORD = "test"; + + private static MySQLMemoryStore.Builder builder; + private static MemoryStore db; + private static int collectionNum = 0; + private static final String NULL_ADDITIONAL_METADATA = null; + private static final String NULL_KEY = null; + private static final ZonedDateTime NULL_TIMESTAMP = null; + + @BeforeAll + static void setUp() throws SQLException { + builder = new MySQLMemoryStore.Builder() + .withConnection( + DriverManager.getConnection( + CONTAINER.getJdbcUrl(), MYSQL_USER, MYSQL_PASSWORD)); + db = builder.buildAsync().block(); + } + + private Collection createBatchRecords(int numRecords) { + assertTrue(numRecords % 2 == 0, "Number of records must be even"); + assertTrue(numRecords > 0, "Number of records must be greater than 0"); + + List records = new ArrayList<>(numRecords); + for (int i = 0; i < numRecords / 2; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + for (int i = numRecords / 2; i < numRecords; i++) { + MemoryRecord testRecord = + MemoryRecord.referenceRecord( + "test" + i, + "sourceName" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + return records; + } + + @Test + void initializeDbConnectionSucceeds() { + assertNotNull(db); + } + + @Test + void itDoesNotFailWithExistingTables() { + // Act + db = builder.buildAsync().block(); + + // Assert + assertNotNull(db); + } + + @Test + void itCanCreateAndGetCollectionAsync() throws IOException { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + Collection collections = db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertFalse(collections.isEmpty()); + assertTrue(collections.contains(collection)); + } + + @Test + void itHandlesExceptionsWhenCreatingCollectionAsync() { + // Arrange + String collection = null; + + // Assert + assertThrows( + NullPointerException.class, + () -> db.createCollectionAsync(collection).block(), + "Should not be able to create collection with null name"); + } + + @Test + void itCannotInsertIntoNonExistentCollectionAsync() { + + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Assert + assertThrows( + MemoryException.class, + () -> db.upsertAsync(collection, testRecord).block(), + "Should not be able to insert into a non-existent collection"); + } + + @Test + void getAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actualDefault = db.getAsync(collection, key, false).block(); + MemoryRecord actualWithEmbedding = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actualDefault); + assertNotNull(actualDefault.getEmbedding()); + assertNotNull(actualDefault.getEmbedding().getVector()); + assertTrue(actualDefault.getEmbedding().getVector().isEmpty()); + assertNotNull(actualWithEmbedding); + assertNotNull(actualWithEmbedding.getEmbedding()); + assertNotNull(actualWithEmbedding.getEmbedding().getVector()); + assertFalse(actualWithEmbedding.getEmbedding().getVector().isEmpty()); + assertNotEquals(testRecord, actualDefault); + assertEquals(testRecord.getMetadata(), actualWithEmbedding.getMetadata()); + assertEquals( + testRecord.getEmbedding().getVector(), + actualWithEmbedding.getEmbedding().getVector()); + } + + @Test + void itCanUpsertAndRetrieveARecordWithNoTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord.getMetadata(), actual.getMetadata()); + assertEquals(testRecord.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void itCanUpsertAndRetrieveARecordWithTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + ZonedDateTime.now(ZoneId.of("UTC"))); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord.getMetadata(), actual.getMetadata()); + assertEquals(testRecord.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void upsertReplacesExistingRecordWithSameIdAsync() { + // Arrange + String commonId = "test"; + MemoryRecord testRecord = + MemoryRecord.localRecord( + commonId, + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + MemoryRecord testRecord2 = + MemoryRecord.localRecord( + commonId, + "text2", + "description2", + new Embedding(Arrays.asList(1f, 2f, 4f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + String key2 = db.upsertAsync(collection, testRecord2).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertNotEquals(testRecord2, actual); + assertEquals(key, key2); + assertEquals(testRecord2.getMetadata(), actual.getMetadata()); + assertEquals(testRecord2.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void existingRecordCanBeRemovedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + assertNotNull(key); + db.removeAsync(collection, key).block(); + MemoryRecord actual = db.getAsync(collection, key, false).block(); + + // Assert + assertNull(actual); + } + + @Test + void removingNonExistingRecordDoesNothingAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.removeAsync(collection, "key").block(); + MemoryRecord actual = db.getAsync(collection, "key", false).block(); + + // Assert + assertNull(actual); + } + + @Test + void itCanListAllDatabaseCollectionsAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(collectionNum, collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Collection collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + int initialSize = collections.size(); + + Flux.fromArray(testCollections) + .concatMap(collection -> db.createCollectionAsync(collection)) + .blockLast(); + + // Act + collections = db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertEquals(initialSize + numCollections, collections.size()); + for (String collection : testCollections) { + assertTrue( + collections.contains(collection), + "Collections does not contain the newly-created collection " + collection); + } + } + + private String setUpNearestMatches() { + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + return collection; + } + + @Test + void getNearestMatchesReturnsAllResultsWithNoMinScoreAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, topN, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertEquals(topN, topNResults.size()); + Tuple2[] topNResultsArray = topNResults.toArray(new Tuple2[0]); + for (int j = 0; j < topN - 1; j++) { + int compare = + Double.compare(topNResultsArray[j].getT2(), topNResultsArray[j + 1].getT2()); + assertTrue(compare >= 0); + } + } + + @Test + void getNearestMatchesReturnsLimit() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfLimitZero() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync( + collection, compareEmbedding, Integer.MAX_VALUE, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + + String collection = setUpNearestMatches(); + + // Act + float threshold = 0.75f; + Tuple2 topNResultDefault = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + Tuple2 topNResultWithEmbedding = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, true).block(); + + // Assert + assertNotNull(topNResultDefault); + assertNotNull(topNResultWithEmbedding); + assertNotNull(topNResultDefault.getT1().getEmbedding()); + assertNotNull(topNResultDefault.getT1().getEmbedding().getVector()); + assertTrue(topNResultDefault.getT1().getEmbedding().getVector().isEmpty()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding().getVector()); + assertFalse(topNResultWithEmbedding.getT1().getEmbedding().getVector().isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsExpectedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = setUpNearestMatches(); + + // Act + float threshold = 0.75f; + Tuple2 topNResult = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + + // Assert + assertNotNull(topNResult); + assertEquals("test0", topNResult.getT1().getMetadata().getId()); + assertTrue(topNResult.getT2() >= threshold); + } + + @Test + void getNearestMatcheReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Tuple2 topNResults = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + + // Assert + assertNull(topNResults); + } + + @Test + void getNearestMatchesDifferentiatesIdenticalVectorsByKeyAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + for (int i = 0; i < 10; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + } + + // Act + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, topN, 0.75f, true).block(); + Collection topNKeys = + topNResults.stream() + .map(tuple -> tuple.getT1().getKey()) + .sorted() + .collect(Collectors.toList()); + + // Assert + assertEquals(topN, topNResults.size()); + assertEquals(topN, topNKeys.size()); + for (Iterator> iterator = topNResults.iterator(); + iterator.hasNext(); ) { + Tuple2 tuple = iterator.next(); + int compare = Float.compare(tuple.getT2(), 0.75f); + assertTrue(topNKeys.contains(tuple.getT1().getKey())); + assertTrue(compare >= 0); + } + } + + @Test + void itCanBatchUpsertRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + // Act + Collection keys = db.upsertBatchAsync(collection, records).block(); + Collection resultRecords = db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertEquals(numRecords, keys.size()); + assertEquals(numRecords, resultRecords.size()); + } + + @Test + void itCanBatchGetRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + Collection keys = db.upsertBatchAsync(collection, records).block(); + + // Act + Collection results = db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertNotNull(results); + assertEquals(numRecords, results.size()); + } + + @Test + void itCanBatchRemoveRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + List keys = new ArrayList<>(); + for (String key : db.upsertBatchAsync(collection, records).block()) { + keys.add(key); + } + + // Act + db.removeBatchAsync(collection, keys).block(); + + // Assert + for (MemoryRecord result : db.getBatchAsync(collection, keys, true).block()) { + assertNull(result); + } + } + + @Test + void collectionsCanBeDeletedAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(collectionNum, collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Collection collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + int initialSize = collections.size(); + + Flux.fromArray(testCollections) + .concatMap(collection -> db.createCollectionAsync(collection)) + .blockLast(); + collectionNum += numCollections; + + // Act + collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(initialSize + numCollections, collections.size()); + + // Act + for (String collection : collections) { + db.deleteCollectionAsync(collection).block(); + } + + // Assert + collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(0, collections.size()); + } + + @Test + void itThrowsWhenDeletingNonExistentCollectionAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + assertThrows(MemoryException.class, () -> db.deleteCollectionAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnTrueForExistingCollection() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + assertTrue(db.doesCollectionExistAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnFalseForNonExistentCollection() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + assertFalse(db.doesCollectionExistAsync(collection).block()); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLMemoryStoreTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLMemoryStoreTest.java new file mode 100644 index 0000000000..cea1cd4ec6 --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLMemoryStoreTest.java @@ -0,0 +1,720 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.postgresql; + +import static org.junit.jupiter.api.Assertions.*; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.memory.MemoryException; +import com.microsoft.semantickernel.memory.MemoryRecord; +import com.microsoft.semantickernel.memory.MemoryStore; +import java.io.IOException; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import reactor.core.publisher.Flux; +import reactor.util.function.Tuple2; + +@Testcontainers +public class PostgreSQLMemoryStoreTest { + @Container private static final PostgreSQLContainer CONTAINER = new PostgreSQLContainer(); + private static final String POSTGRES_USER = "test"; + private static final String POSTGRES_PASSWORD = "test"; + + private static PostgreSQLMemoryStore.Builder builder; + private static MemoryStore db; + private static int collectionNum = 0; + private static final String NULL_ADDITIONAL_METADATA = null; + private static final String NULL_KEY = null; + private static final ZonedDateTime NULL_TIMESTAMP = null; + + @BeforeAll + static void setUp() throws SQLException { + builder = new PostgreSQLMemoryStore.Builder() + .withConnection( + DriverManager.getConnection( + CONTAINER.getJdbcUrl(), POSTGRES_USER, POSTGRES_PASSWORD)); + db = builder.buildAsync().block(); + } + + private Collection createBatchRecords(int numRecords) { + assertTrue(numRecords % 2 == 0, "Number of records must be even"); + assertTrue(numRecords > 0, "Number of records must be greater than 0"); + + List records = new ArrayList<>(numRecords); + for (int i = 0; i < numRecords / 2; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + for (int i = numRecords / 2; i < numRecords; i++) { + MemoryRecord testRecord = + MemoryRecord.referenceRecord( + "test" + i, + "sourceName" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + return records; + } + + @Test + void initializeDbConnectionSucceeds() { + assertNotNull(db); + } + + @Test + void itDoesNotFailWithExistingTables() { + // Act + db = builder.buildAsync().block(); + + // Assert + assertNotNull(db); + } + + @Test + void itCanCreateAndGetCollectionAsync() throws IOException { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + Collection collections = db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertFalse(collections.isEmpty()); + assertTrue(collections.contains(collection)); + } + + @Test + void itHandlesExceptionsWhenCreatingCollectionAsync() { + // Arrange + String collection = null; + + // Assert + assertThrows( + NullPointerException.class, + () -> db.createCollectionAsync(collection).block(), + "Should not be able to create collection with null name"); + } + + @Test + void itCannotInsertIntoNonExistentCollectionAsync() { + + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Assert + assertThrows( + MemoryException.class, + () -> db.upsertAsync(collection, testRecord).block(), + "Should not be able to insert into a non-existent collection"); + } + + @Test + void getAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actualDefault = db.getAsync(collection, key, false).block(); + MemoryRecord actualWithEmbedding = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actualDefault); + assertNotNull(actualDefault.getEmbedding()); + assertNotNull(actualDefault.getEmbedding().getVector()); + assertTrue(actualDefault.getEmbedding().getVector().isEmpty()); + assertNotNull(actualWithEmbedding); + assertNotNull(actualWithEmbedding.getEmbedding()); + assertNotNull(actualWithEmbedding.getEmbedding().getVector()); + assertFalse(actualWithEmbedding.getEmbedding().getVector().isEmpty()); + assertNotEquals(testRecord, actualDefault); + assertEquals(testRecord.getMetadata(), actualWithEmbedding.getMetadata()); + assertEquals( + testRecord.getEmbedding().getVector(), + actualWithEmbedding.getEmbedding().getVector()); + } + + @Test + void itCanUpsertAndRetrieveARecordWithNoTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord.getMetadata(), actual.getMetadata()); + assertEquals(testRecord.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void itCanUpsertAndRetrieveARecordWithTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + ZonedDateTime.now(ZoneId.of("UTC"))); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord.getMetadata(), actual.getMetadata()); + assertEquals(testRecord.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void upsertReplacesExistingRecordWithSameIdAsync() { + // Arrange + String commonId = "test"; + MemoryRecord testRecord = + MemoryRecord.localRecord( + commonId, + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + MemoryRecord testRecord2 = + MemoryRecord.localRecord( + commonId, + "text2", + "description2", + new Embedding(Arrays.asList(1f, 2f, 4f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + String key2 = db.upsertAsync(collection, testRecord2).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertNotEquals(testRecord2, actual); + assertEquals(key, key2); + assertEquals(testRecord2.getMetadata(), actual.getMetadata()); + assertEquals(testRecord2.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void existingRecordCanBeRemovedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + assertNotNull(key); + db.removeAsync(collection, key).block(); + MemoryRecord actual = db.getAsync(collection, key, false).block(); + + // Assert + assertNull(actual); + } + + @Test + void removingNonExistingRecordDoesNothingAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.removeAsync(collection, "key").block(); + MemoryRecord actual = db.getAsync(collection, "key", false).block(); + + // Assert + assertNull(actual); + } + + @Test + void itCanListAllDatabaseCollectionsAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(collectionNum, collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Collection collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + int initialSize = collections.size(); + + Flux.fromArray(testCollections) + .concatMap(collection -> db.createCollectionAsync(collection)) + .blockLast(); + + // Act + collections = db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertEquals(initialSize + numCollections, collections.size()); + for (String collection : testCollections) { + assertTrue( + collections.contains(collection), + "Collections does not contain the newly-created collection " + collection); + } + } + + private String setUpNearestMatches() { + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + return collection; + } + + @Test + void getNearestMatchesReturnsAllResultsWithNoMinScoreAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, topN, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertEquals(topN, topNResults.size()); + Tuple2[] topNResultsArray = topNResults.toArray(new Tuple2[0]); + for (int j = 0; j < topN - 1; j++) { + int compare = + Double.compare(topNResultsArray[j].getT2(), topNResultsArray[j + 1].getT2()); + assertTrue(compare >= 0); + } + } + + @Test + void getNearestMatchesReturnsLimit() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfLimitZero() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync( + collection, compareEmbedding, Integer.MAX_VALUE, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + + String collection = setUpNearestMatches(); + + // Act + float threshold = 0.75f; + Tuple2 topNResultDefault = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + Tuple2 topNResultWithEmbedding = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, true).block(); + + // Assert + assertNotNull(topNResultDefault); + assertNotNull(topNResultWithEmbedding); + assertNotNull(topNResultDefault.getT1().getEmbedding()); + assertNotNull(topNResultDefault.getT1().getEmbedding().getVector()); + assertTrue(topNResultDefault.getT1().getEmbedding().getVector().isEmpty()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding().getVector()); + assertFalse(topNResultWithEmbedding.getT1().getEmbedding().getVector().isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsExpectedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = setUpNearestMatches(); + + // Act + float threshold = 0.75f; + Tuple2 topNResult = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + + // Assert + assertNotNull(topNResult); + assertEquals("test0", topNResult.getT1().getMetadata().getId()); + assertTrue(topNResult.getT2() >= threshold); + } + + @Test + void getNearestMatcheReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Tuple2 topNResults = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + + // Assert + assertNull(topNResults); + } + + @Test + void getNearestMatchesDifferentiatesIdenticalVectorsByKeyAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + for (int i = 0; i < 10; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + } + + // Act + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, topN, 0.75f, true).block(); + Collection topNKeys = + topNResults.stream() + .map(tuple -> tuple.getT1().getKey()) + .sorted() + .collect(Collectors.toList()); + + // Assert + assertEquals(topN, topNResults.size()); + assertEquals(topN, topNKeys.size()); + for (Iterator> iterator = topNResults.iterator(); + iterator.hasNext(); ) { + Tuple2 tuple = iterator.next(); + int compare = Float.compare(tuple.getT2(), 0.75f); + assertTrue(topNKeys.contains(tuple.getT1().getKey())); + assertTrue(compare >= 0); + } + } + + @Test + void itCanBatchUpsertRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + // Act + Collection keys = db.upsertBatchAsync(collection, records).block(); + Collection resultRecords = db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertEquals(numRecords, keys.size()); + assertEquals(numRecords, resultRecords.size()); + } + + @Test + void itCanBatchGetRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + Collection keys = db.upsertBatchAsync(collection, records).block(); + + // Act + Collection results = db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertNotNull(results); + assertEquals(numRecords, results.size()); + } + + @Test + void itCanBatchRemoveRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + List keys = new ArrayList<>(); + for (String key : db.upsertBatchAsync(collection, records).block()) { + keys.add(key); + } + + // Act + db.removeBatchAsync(collection, keys).block(); + + // Assert + for (MemoryRecord result : db.getBatchAsync(collection, keys, true).block()) { + assertNull(result); + } + } + + @Test + void collectionsCanBeDeletedAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(collectionNum, collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Collection collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + int initialSize = collections.size(); + + Flux.fromArray(testCollections) + .concatMap(collection -> db.createCollectionAsync(collection)) + .blockLast(); + collectionNum += numCollections; + + // Act + collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(initialSize + numCollections, collections.size()); + + // Act + for (String collection : collections) { + db.deleteCollectionAsync(collection).block(); + } + + // Assert + collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(0, collections.size()); + } + + @Test + void itThrowsWhenDeletingNonExistentCollectionAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + assertThrows(MemoryException.class, () -> db.deleteCollectionAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnTrueForExistingCollection() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + assertTrue(db.doesCollectionExistAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnFalseForNonExistentCollection() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + assertFalse(db.doesCollectionExistAsync(collection).block()); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/sqlite/SQLiteMemoryStoreTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/sqlite/SQLiteMemoryStoreTest.java new file mode 100644 index 0000000000..b1136b41bf --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/connectors/memory/sqlite/SQLiteMemoryStoreTest.java @@ -0,0 +1,711 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.sqlite; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.connectors.memory.jdbc.JDBCMemoryStore; +import com.microsoft.semantickernel.connectors.memory.jdbc.JDBCMemoryStoreTest; +import com.microsoft.semantickernel.memory.MemoryException; +import com.microsoft.semantickernel.memory.MemoryRecord; +import com.microsoft.semantickernel.memory.MemoryStore; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Flux; +import reactor.util.function.Tuple2; + +import java.sql.SQLException; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.*; + +public class SQLiteMemoryStoreTest extends JDBCMemoryStoreTest { + + private static SQLiteMemoryStore.Builder builder; + private static MemoryStore db; + private static int collectionNum = 0; + private static final String NULL_ADDITIONAL_METADATA = null; + private static final String NULL_KEY = null; + private static final ZonedDateTime NULL_TIMESTAMP = null; + + @BeforeAll + static void setUp() throws SQLException { + builder = new SQLiteMemoryStore.Builder().withFilename(":memory:"); + db = builder.buildAsync().block(); + } + + private Collection createBatchRecords(int numRecords) { + assertTrue(numRecords % 2 == 0, "Number of records must be even"); + assertTrue(numRecords > 0, "Number of records must be greater than 0"); + + List records = new ArrayList<>(numRecords); + for (int i = 0; i < numRecords / 2; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + for (int i = numRecords / 2; i < numRecords; i++) { + MemoryRecord testRecord = + MemoryRecord.referenceRecord( + "test" + i, + "sourceName" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + return records; + } + + @Test + void initializeDbConnectionSucceeds() { + assertNotNull(db); + } + + @Test + void itDoesNotFailWithExistingTables() { + // Act + db = builder.buildAsync().block(); + + // Assert + assertNotNull(db); + } + + @Test + void itCanCreateAndGetCollectionAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + Collection collections = db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertFalse(collections.isEmpty()); + assertTrue(collections.contains(collection)); + } + + @Test + void itHandlesExceptionsWhenCreatingCollectionAsync() { + // Arrange + String collection = null; + + // Assert + assertThrows( + NullPointerException.class, + () -> db.createCollectionAsync(collection).block(), + "Should not be able to create collection with null name"); + } + + @Test + void itCannotInsertIntoNonExistentCollectionAsync() { + + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Assert + assertThrows( + MemoryException.class, + () -> db.upsertAsync(collection, testRecord).block(), + "Should not be able to insert into a non-existent collection"); + } + + @Test + void getAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actualDefault = db.getAsync(collection, key, false).block(); + MemoryRecord actualWithEmbedding = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actualDefault); + assertNotNull(actualDefault.getEmbedding()); + assertNotNull(actualDefault.getEmbedding().getVector()); + assertTrue(actualDefault.getEmbedding().getVector().isEmpty()); + assertNotNull(actualWithEmbedding); + assertNotNull(actualWithEmbedding.getEmbedding()); + assertNotNull(actualWithEmbedding.getEmbedding().getVector()); + assertFalse(actualWithEmbedding.getEmbedding().getVector().isEmpty()); + assertNotEquals(testRecord, actualDefault); + assertEquals(testRecord.getMetadata(), actualWithEmbedding.getMetadata()); + assertEquals( + testRecord.getEmbedding().getVector(), + actualWithEmbedding.getEmbedding().getVector()); + } + + @Test + void itCanUpsertAndRetrieveARecordWithNoTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord.getMetadata(), actual.getMetadata()); + assertEquals(testRecord.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void itCanUpsertAndRetrieveARecordWithTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + ZonedDateTime.now(ZoneId.of("UTC"))); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord.getMetadata(), actual.getMetadata()); + assertEquals(testRecord.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void upsertReplacesExistingRecordWithSameIdAsync() { + // Arrange + String commonId = "test"; + MemoryRecord testRecord = + MemoryRecord.localRecord( + commonId, + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + MemoryRecord testRecord2 = + MemoryRecord.localRecord( + commonId, + "text2", + "description2", + new Embedding(Arrays.asList(1f, 2f, 4f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + String key2 = db.upsertAsync(collection, testRecord2).block(); + MemoryRecord actual = db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertNotEquals(testRecord2, actual); + assertEquals(key, key2); + assertEquals(testRecord2.getMetadata(), actual.getMetadata()); + assertEquals(testRecord2.getEmbedding().getVector(), actual.getEmbedding().getVector()); + } + + @Test + void existingRecordCanBeRemovedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.createCollectionAsync(collection).block(); + String key = db.upsertAsync(collection, testRecord).block(); + assertNotNull(key); + db.removeAsync(collection, key).block(); + MemoryRecord actual = db.getAsync(collection, key, false).block(); + + // Assert + assertNull(actual); + } + + @Test + void removingNonExistingRecordDoesNothingAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + db.removeAsync(collection, "key").block(); + MemoryRecord actual = db.getAsync(collection, "key", false).block(); + + // Assert + assertNull(actual); + } + + @Test + void itCanListAllDatabaseCollectionsAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(collectionNum, collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Collection collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + int initialSize = collections.size(); + + Flux.fromArray(testCollections) + .concatMap(collection -> db.createCollectionAsync(collection)) + .blockLast(); + + // Act + collections = db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertEquals(initialSize + numCollections, collections.size()); + for (String collection : testCollections) { + assertTrue( + collections.contains(collection), + "Collections does not contain the newly-created collection " + collection); + } + } + + private String setUpNearestMatches() { + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + + return collection; + } + + @Test + void getNearestMatchesReturnsAllResultsWithNoMinScoreAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = setUpNearestMatches(); + + // Act + float threshold = -1; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, topN, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertEquals(topN, topNResults.size()); + Tuple2[] topNResultsArray = topNResults.toArray(new Tuple2[0]); + for (int j = 0; j < topN - 1; j++) { + int compare = + Double.compare(topNResultsArray[j].getT2(), topNResultsArray[j + 1].getT2()); + assertTrue(compare >= 0); + } + } + + @Test + void getNearestMatchesReturnsLimit() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfLimitZero() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = setUpNearestMatches(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Collection> topNResults = + db.getNearestMatchesAsync( + collection, compareEmbedding, Integer.MAX_VALUE, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + + String collection = setUpNearestMatches(); + + // Act + float threshold = 0.75f; + Tuple2 topNResultDefault = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + Tuple2 topNResultWithEmbedding = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, true).block(); + + // Assert + assertNotNull(topNResultDefault); + assertNotNull(topNResultWithEmbedding); + assertNotNull(topNResultDefault.getT1().getEmbedding()); + assertNotNull(topNResultDefault.getT1().getEmbedding().getVector()); + assertTrue(topNResultDefault.getT1().getEmbedding().getVector().isEmpty()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding().getVector()); + assertFalse(topNResultWithEmbedding.getT1().getEmbedding().getVector().isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsExpectedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = setUpNearestMatches(); + + // Act + float threshold = 0.75f; + Tuple2 topNResult = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + + // Assert + assertNotNull(topNResult); + assertEquals("test0", topNResult.getT1().getMetadata().getId()); + assertTrue(topNResult.getT2() >= threshold); + } + + @Test + void getNearestMatcheReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Tuple2 topNResults = + db.getNearestMatchAsync(collection, compareEmbedding, threshold, false).block(); + + // Assert + assertNull(topNResults); + } + + @Test + void getNearestMatchesDifferentiatesIdenticalVectorsByKeyAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + for (int i = 0; i < 10; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + db.upsertAsync(collection, testRecord).block(); + } + + // Act + Collection> topNResults = + db.getNearestMatchesAsync(collection, compareEmbedding, topN, 0.75f, true).block(); + Collection topNKeys = + topNResults.stream() + .map(tuple -> tuple.getT1().getKey()) + .sorted() + .collect(Collectors.toList()); + + // Assert + assertEquals(topN, topNResults.size()); + assertEquals(topN, topNKeys.size()); + for (Iterator> iterator = topNResults.iterator(); + iterator.hasNext(); ) { + Tuple2 tuple = iterator.next(); + int compare = Float.compare(tuple.getT2(), 0.75f); + assertTrue(topNKeys.contains(tuple.getT1().getKey())); + assertTrue(compare >= 0); + } + } + + @Test + void itCanBatchUpsertRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + // Act + Collection keys = db.upsertBatchAsync(collection, records).block(); + Collection resultRecords = db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertEquals(numRecords, keys.size()); + assertEquals(numRecords, resultRecords.size()); + } + + @Test + void itCanBatchGetRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + Collection keys = db.upsertBatchAsync(collection, records).block(); + + // Act + Collection results = db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertNotNull(results); + assertEquals(numRecords, results.size()); + } + + @Test + void itCanBatchRemoveRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + Collection keys = db.upsertBatchAsync(collection, records).block(); + assertNotNull(keys); + + // Act + db.removeBatchAsync(collection, keys).block(); + + // Assert + Collection results = db.getBatchAsync(collection, keys, false).block(); + assertNotNull(results); + for (MemoryRecord result : results) { + assertNull(result); + } + } + + @Test + void collectionsCanBeDeletedAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(collectionNum, collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Collection collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + int initialSize = collections.size(); + + Flux.fromArray(testCollections) + .concatMap(collection -> db.createCollectionAsync(collection)) + .blockLast(); + collectionNum += numCollections; + + // Act + collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(initialSize + numCollections, collections.size()); + + // Act + for (String collection : collections) { + db.deleteCollectionAsync(collection).block(); + } + + // Assert + collections = db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(0, collections.size()); + } + + @Test + void itThrowsWhenDeletingNonExistentCollectionAsync() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + assertThrows(MemoryException.class, () -> db.deleteCollectionAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnTrueForExistingCollection() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + db.createCollectionAsync(collection).block(); + + // Act + assertTrue(db.doesCollectionExistAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnFalseForNonExistentCollection() { + // Arrange + String collection = "test_collection" + collectionNum; + collectionNum++; + + // Act + assertFalse(db.doesCollectionExistAsync(collection).block()); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/AbstractKernelTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/AbstractKernelTest.java new file mode 100644 index 0000000000..5a71bed8fb --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/AbstractKernelTest.java @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.e2e; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.memory.VolatileMemoryStore; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; +import org.junit.jupiter.api.condition.EnabledIf; + +@EnabledIf("isAzureTestEnabled") +public class AbstractKernelTest { + + public static final String CONF_OPENAI_PROPERTIES = "conf.openai.properties"; + public static final String AZURE_CONF_PROPERTIES = "conf.properties"; + + public static Kernel buildTextCompletionKernel() throws ConfigurationException { + String model = "text-davinci-003"; + final OpenAIAsyncClient openAIClient = getOpenAIClient(); + TextCompletion textCompletion = new OpenAITextCompletion(openAIClient, model); + + return SKBuilders.kernel() + .withDefaultAIService(textCompletion) + .withDefaultAIService( + SKBuilders.textEmbeddingGeneration() + .withOpenAIClient(openAIClient) + .withModelId(model) + .build()) + .withMemoryStorage(new VolatileMemoryStore()) + .build(); + } + + public static OpenAIAsyncClient getOpenAIClient() throws ConfigurationException { + return SamplesConfig.getClient(); + } + + public static String getOpenAIModel() throws IOException { + return getConfigValue(CONF_OPENAI_PROPERTIES, "model"); + } + + public static String getToken(String configName) throws IOException { + return getConfigValue(configName, "token"); + } + + public static String getEndpoint(String configName) throws IOException { + return getConfigValue(configName, "endpoint"); + } + + private static String getConfigValue(String configName, String propertyName) + throws IOException { + String home = new File(System.getProperty("user.home")).getAbsolutePath(); + + try (FileInputStream fis = new FileInputStream(home + "/.oai/" + configName)) { + Properties props = new Properties(); + props.load(fis); + String apiKey = props.getProperty(propertyName); + if (apiKey == null) { + System.err.println("NO PROPERTY " + propertyName); + return ""; + } + return apiKey; + } + } + + public static boolean isOpenAIComTestEnabled() { + return checkConfig(AbstractKernelTest.CONF_OPENAI_PROPERTIES); + } + + public static boolean isAzureTestEnabled() { + return checkConfig(AbstractKernelTest.AZURE_CONF_PROPERTIES); + } + + private static boolean checkConfig(String confOpenaiProperties) { + if (!Boolean.getBoolean("enable_external_tests") + && !System.getProperties().containsKey("intellij.debug.agent")) { + return false; + } + + try { + if (AbstractKernelTest.getEndpoint(confOpenaiProperties) == null) { + System.out.println("Test disabled due to lack of configured azure endpoint"); + return false; + } + + if (AbstractKernelTest.getToken(confOpenaiProperties) == null) { + System.out.println("Test disabled due to lack of configured azure token"); + return false; + } + } catch (IOException e) { + return false; + } + + return true; + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/ContextVariableFunctionTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/ContextVariableFunctionTest.java new file mode 100644 index 0000000000..1de09d2024 --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/ContextVariableFunctionTest.java @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.e2e; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.function.Function; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +public class ContextVariableFunctionTest extends AbstractKernelTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(ContextVariableFunctionTest.class); + + public static void main(String[] args) + throws ExecutionException, + InterruptedException, + TimeoutException, + ConfigurationException { + new ContextVariableFunctionTest().runContextVariableTest(); + } + + @Test + @EnabledIf("isAzureTestEnabled") + public void runContextVariableTest() + throws ExecutionException, + InterruptedException, + TimeoutException, + ConfigurationException { + Kernel kernel = buildTextCompletionKernel(); + + String 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. + + {{$history}} + User: {{$user_input}} + ChatBot:\s"""; + + CompletionSKFunction chat = + kernel.getSemanticFunctionBuilder() + .withPromptTemplate(prompt) + .withFunctionName("ChatBot") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0.7, 0.5, 0, 0, 2000)) + .build(); + + SKContext readOnlySkContext = SKBuilders.context().withKernel(kernel).build(); + + chat("Hi, I'm looking for book suggestions?", chat, readOnlySkContext) + .flatMap( + chat( + "I love history and philosophy, I'd like to learn something new" + + " about Greece, any suggestion?", + chat)) + .flatMap(chat("that sounds interesting, what is it about?", chat)) + .flatMap( + chat( + "if I read that book, what exactly will I learn about Greece" + + " history?", + chat)) + .flatMap( + chat("could you list some more books I could read about this topic?", chat)) + .block(); + } + + private Function> chat(String input, CompletionSKFunction chat) { + return (context) -> { + try { + return chat(input, chat, context); + } catch (ExecutionException | InterruptedException | TimeoutException e) { + return Mono.error(e); + } + }; + } + + private Mono chat(String input, CompletionSKFunction chat, SKContext context) + throws ExecutionException, InterruptedException, TimeoutException { + context = context.setVariable("user_input", input); + + LOGGER.info("User:\n" + input); + + SKContext finalContext = context; + return chat.invokeAsync(context, null) + .map( + result -> { + LOGGER.info("Bot:\n\t\t" + result.getResult()); + + String existingHistoy = finalContext.getVariables().get("history"); + if (existingHistoy == null) { + existingHistoy = ""; + } + existingHistoy += + "\nUser: " + input + "\nChatBot: " + result.getResult() + "\n"; + return finalContext.setVariable("history", existingHistoy); + }); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/FunSkillTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/FunSkillTest.java new file mode 100644 index 0000000000..765bd272a1 --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/FunSkillTest.java @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.e2e; + +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +@EnabledIf("isAzureTestEnabled") +public class FunSkillTest extends AbstractKernelTest { + private static final Logger LOGGER = LoggerFactory.getLogger(FunSkillTest.class); + + @Test + public void tellAJoke() throws ConfigurationException { + Mono result = + buildTextCompletionKernel() + .importSkillFromDirectory("FunSkill", "../../../samples/skills") + .getFunction("joke", CompletionSKFunction.class) + .invokeAsync("time travel to dinosaur age"); + + if (result != null) { + LOGGER.info(result.block().getResult()); + } + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/InlineFunctionTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/InlineFunctionTest.java new file mode 100644 index 0000000000..4e0517ad36 --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/InlineFunctionTest.java @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.e2e; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +public class InlineFunctionTest extends AbstractKernelTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(InlineFunctionTest.class); + + @Test + @EnabledIf("isAzureTestEnabled") + public void executeInlineFunction() throws ConfigurationException { + Kernel kernel = buildTextCompletionKernel(); + String prompt = "{{$input}}\n" + "Summarize the content above."; + + CompletionSKFunction summarize = + kernel.getSemanticFunctionBuilder() + .withPromptTemplate(prompt) + .withFunctionName("summarize") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000)) + .build(); + + String text = + """ + Demo (ancient Greek poet) + From Wikipedia, the free encyclopedia + Demo or Damo (Greek: ΔÎĩÎŧĪŽ, ΔαÎŧĪŽ; fl. c. AD 200) was a Greek woman of the Roman period, known for a single epigram, engraved upon the Colossus of Memnon, which bears her name. She speaks of herself therein as a lyric poetess dedicated to the Muses, but nothing is known of her life.[1] + Identity + Demo was evidently Greek, as her name, a traditional epithet of Demeter, signifies. The name was relatively common in the Hellenistic world, in Egypt and elsewhere, and she cannot be further identified. The date of her visit to the Colossus of Memnon cannot be established with certainty, but internal evidence on the left leg suggests her poem was inscribed there at some point in or after AD 196.[2] + Epigram + There are a number of graffiti inscriptions on the Colossus of Memnon. Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac couplets, entitled and presumably authored by "Demo" or "Damo" (the Greek inscription is difficult to read), is a dedication to the Muses.[2] The poem is traditionally published with the works of Balbilla, though the internal evidence suggests a different author.[1] + In the poem, Demo explains that Memnon has shown her special respect. In return, Demo offers the gift for poetry, as a gift to the hero. At the end of this epigram, she addresses Memnon, highlighting his divine status by recalling his strength and holiness.[2] + Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic dialect. The language indicates she was knowledgeable in Homeric poetry—'bearing a pleasant gift', for example, alludes to the use of that phrase throughout the Iliad and Odyssey.[a][2] + """; + + Mono result = summarize.invokeAsync(text); + + LOGGER.info("Result: " + result.block().getResult()); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/KernelTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/KernelTest.java new file mode 100644 index 0000000000..a2d850e4df --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/KernelTest.java @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.e2e; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.io.IOException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +public class KernelTest extends AbstractKernelTest { + private static final Logger LOGGER = LoggerFactory.getLogger(KernelTest.class); + + private static void executeCompletion(Kernel kernel) { + CompletionSKFunction summarize = + kernel.getSemanticFunctionBuilder() + .withPromptTemplate( + """ + {{$input}} + + One line TLDR with the fewest words.""") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0, 0, 0, 0, 256)) + .build(); + + String text1 = + """ + 1st Law of Thermodynamics - Energy cannot be created or destroyed. + 2nd Law of Thermodynamics - For a spontaneous process, the entropy of the universe increases. + 3rd Law of Thermodynamics - A perfect crystal at zero Kelvin has zero entropy"""; + + Mono mono = summarize.invokeAsync(text1); + SKContext result = mono.block(); + + if (result != null) LOGGER.info("Result: " + result.getResult()); + } + + public static Kernel buildKernel(OpenAIAsyncClient client, String model) { + TextCompletion textCompletion = new OpenAITextCompletion(client, model); + + return SKBuilders.kernel().withDefaultAIService(textCompletion).build(); + } + + @Test + @EnabledIf("isAzureTestEnabled") + public void endToEndTextGenerationTestAzureOpenAI() throws ConfigurationException { + Kernel kernel = buildKernel(getOpenAIClient(), "text-davinci-003"); + executeCompletion(kernel); + } + + @Test + @EnabledIf("isAzureTestEnabled") + public void endToEndTextGenerationTestOpenAI() throws ConfigurationException, IOException { + Kernel kernel = buildKernel(getOpenAIClient(), getOpenAIModel()); + executeCompletion(kernel); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/PlannerTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/PlannerTest.java new file mode 100644 index 0000000000..d2e1a801ca --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/PlannerTest.java @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.e2e; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PlannerTest extends AbstractKernelTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(PlannerTest.class); + + @Test + @EnabledIf("isAzureTestEnabled") + public void executeInlineFunction() throws ConfigurationException { + Kernel kernel = buildTextCompletionKernel(); + kernel.importSkillFromDirectory( + "SummarizeSkill", "../../../samples/skills", "SummarizeSkill"); + kernel.importSkillFromDirectory("WriterSkill", "../../../samples/skills", "WriterSkill"); + + SequentialPlanner planner = new SequentialPlanner(kernel, null, null); + + Plan plan = + planner.createPlanAsync( + "Write a poem about John Doe, then translate it into Italian.") + .block(); + + SKContext result = plan.invokeAsync().block(); + + LOGGER.info("Result: " + result.getResult()); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/TextEmbeddingsTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/TextEmbeddingsTest.java new file mode 100644 index 0000000000..7f3198e299 --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/e2e/TextEmbeddingsTest.java @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.e2e; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration; +import com.microsoft.semantickernel.coreskills.TextMemorySkill; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.memory.MemoryQueryResult; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.memory.VolatileMemoryStore; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TextEmbeddingsTest extends AbstractKernelTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(TextEmbeddingsTest.class); + private static final int EXPECTED_EMBEDDING_SIZE = 1536; + + @Test + @EnabledIf("isAzureTestEnabled") + public void testEmbeddingGenerationOpenAI() throws ConfigurationException { + OpenAIAsyncClient client = getOpenAIClient(); + String model = "text-embedding-ada-002"; + OpenAITextEmbeddingGeneration embeddingGeneration = + new OpenAITextEmbeddingGeneration(client, model); + + List data = new ArrayList<>(); + data.add("This is just"); + // data.add("a test"); + + embeddingGeneration + .generateEmbeddingsAsync(data) + .block() + .forEach( + embedding -> + Assertions.assertEquals( + EXPECTED_EMBEDDING_SIZE, embedding.getVector().size())); + } + + @Test + @EnabledIf("isAzureTestEnabled") + public void testEmbeddingGeneration() throws ConfigurationException { + String model = "text-embedding-ada-002"; + OpenAITextEmbeddingGeneration embeddingGeneration = + new OpenAITextEmbeddingGeneration(getOpenAIClient(), model); + + List data = new ArrayList<>(); + data.add("This is just a test"); + + LOGGER.info(String.valueOf(embeddingGeneration.generateEmbeddingsAsync(data).block())); + } + + @Test + @EnabledIf("isAzureTestEnabled") + public void testMemory() throws ConfigurationException { + + Kernel kernel = buildTextCompletionKernel(); + kernel.importSkill(new TextMemorySkill(), "aboutMe"); + + String skPrompt = + """ + + 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: + {{$history}} + User: {{$userInput}} + ChatBot:\s"""; + + CompletionSKFunction chat = + kernel.getSemanticFunctionBuilder() + .withPromptTemplate(skPrompt) + .withFunctionName("recall") + .withSkillName("aboutMe") + .build(); + + VolatileMemoryStore volatileMemoryStore = new VolatileMemoryStore(); + volatileMemoryStore.createCollectionAsync("aboutMe").block(); + + OpenAITextEmbeddingGeneration embeddingGeneration = + new OpenAITextEmbeddingGeneration(getOpenAIClient(), "text-embedding-ada-002"); + + SemanticTextMemory memory = + SKBuilders.semanticTextMemory() + .withEmbeddingGenerator(embeddingGeneration) + .withStorage(volatileMemoryStore) + .build(); + + SKContext context = + SKBuilders.context() + .withVariables(SKBuilders.variables().build()) + .withMemory(memory) + .withSkills(kernel.getSkills()) + .build(); + + context.getSemanticMemory() + .saveInformationAsync("aboutMe", "My name is Andrea", "fact1", null, null) + .block(); + + context.getSemanticMemory() + .saveInformationAsync( + "aboutMe", "I currently work as a tour guide", "fact2", null, null) + .block(); + + context.getSemanticMemory() + .saveInformationAsync( + "aboutMe", "I've been living in Seattle since 2005", "fact3", null, null) + .block(); + + context.getSemanticMemory() + .saveInformationAsync( + "aboutMe", + "I visited France and Italy five times since 2015", + "fact4", + null, + null) + .block(); + + context.getSemanticMemory() + .saveInformationAsync("aboutMe", "My family is from New York", "fact5", null, null) + .block(); + + String query = "Where are you from originally?"; + List results = + memory.searchAsync("aboutMe", query, 10, .5f, false).block(); + results.forEach( + result -> + System.out.printf( + "%s %s (relevance=%f)%n", + query, result.getMetadata().getText(), result.getRelevance())); + } +} diff --git a/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanTest.java b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanTest.java new file mode 100644 index 0000000000..6191391f05 --- /dev/null +++ b/java/api-test/integration-tests/src/test/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanTest.java @@ -0,0 +1,184 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.sequentialplanner; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class SequentialPlanTest { + + public static class Skills { + @DefineSKFunction(name = "Skill1") + public String skill1(@SKFunctionInputAttribute(description = "an input") String input) { + return input + "::Skill1"; + } + + @DefineSKFunction(name = "Skill2") + public String skill2(@SKFunctionInputAttribute(description = "an input") String input) { + return input + "::Skill2"; + } + + @DefineSKFunction(name = "Skill3") + public String skill3( + @SKFunctionInputAttribute(description = "an input") String input, + @SKFunctionParameters( + description = "a variable to set the result to", + required = true, + name = "secondInput") + String secondInput) { + return input + "::" + secondInput + "::Skill3"; + } + + @DefineSKFunction(name = "Skill4") + public String skill4( + @SKFunctionParameters( + description = "a variable to set the result to", + required = true, + name = "anarg") + String anarg) { + return anarg + "::Skill4"; + } + } + + @Test + public void withDirectInput() { + String planString = + """ + + + + """; + + SKContext result = makePlan(planString).invokeAsync("Foo").block(); + Assertions.assertEquals("John Doe::Skill1", result.getResult()); + } + + @Test + public void withNoInput() { + String planString = + """ + + + + """; + + SKContext result = makePlan(planString).invokeAsync("Foo").block(); + Assertions.assertEquals("Foo::Skill1", result.getResult()); + } + + @Test + public void withChainedInput() { + String planString = + """ + + + + + """; + + SKContext result = makePlan(planString).invokeAsync("Foo").block(); + Assertions.assertEquals("Foo::Skill1::Skill2", result.getResult()); + } + + @Test + public void settingAVariable() { + String planString = + """ + + + + + """; + + SKContext result = makePlan(planString).invokeAsync("Foo").block(); + Assertions.assertEquals("Foo::Skill2", result.getResult()); + Assertions.assertEquals("Foo::Skill1", result.getVariables().get("A")); + } + + @Test + public void usingAVariable() { + String planString = + """ + + + + + """; + + SKContext result = makePlan(planString).invokeAsync("Foo").block(); + Assertions.assertEquals("Foo::Skill1::Skill2", result.getResult()); + Assertions.assertEquals("Foo::Skill1", result.getVariables().get("A")); + } + + @Test + public void withASecondArg() { + String planString = + """ + + + + + + """; + + SKContext result = makePlan(planString).invokeAsync("Foo").block(); + Assertions.assertEquals("Foo::Skill1::Skill2::x::Skill3", result.getResult()); + Assertions.assertEquals("Foo::Skill1", result.getVariables().get("A")); + } + + @Test + public void noInput() { + String planString = + """ + + + + + + + """; + + SKContext result = makePlan(planString).invokeAsync("Foo").block(); + Assertions.assertEquals("Foo::Skill1::Skill4", result.getResult()); + Assertions.assertEquals("Foo::Skill1", result.getVariables().get("A")); + } + + @Test + public void noInput2() { + String planString = + """ + + + + """; + + SKContext result = makePlan(planString).invokeAsync("Foo").block(); + Assertions.assertEquals("foo::Skill4", result.getResult()); + } + + @Test + public void noInput3() { + String planString = + """ + + + + """; + SKContext context = SKBuilders.context().build().setVariable("anarg", "foo"); + SKContext result = makePlan(planString).invokeAsync(context).block(); + Assertions.assertEquals("foo::Skill4", result.getResult()); + } + + private static Plan makePlan(String planString) { + Kernel kernel = SKBuilders.kernel().build(); + kernel.importSkill(new Skills(), "Skills"); + + return SequentialPlanParser.toPlanFromXml(planString.stripIndent(), "", kernel.getSkills()); + } +} diff --git a/java/api-test/integration-tests/src/test/resources/log4j2.xml b/java/api-test/integration-tests/src/test/resources/log4j2.xml new file mode 100644 index 0000000000..50a638f0dc --- /dev/null +++ b/java/api-test/integration-tests/src/test/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/api-test/pom.xml b/java/api-test/pom.xml new file mode 100644 index 0000000000..a3f692a7a7 --- /dev/null +++ b/java/api-test/pom.xml @@ -0,0 +1,54 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../pom.xml + + + com.microsoft.semantic-kernel.test + api-test + pom + + + 3.11.0 + 17 + + + + api-usage-example + integration-tests + + + + + + com.microsoft.semantic-kernel + semantickernel-bom + ${project.version} + import + pom + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler-plugin.version} + + ${maven.compiler.release} + ${maven.compiler.release} + ${maven.compiler.release} + + + + + + \ No newline at end of file diff --git a/java/api-test/spotbugs-exclude.xml b/java/api-test/spotbugs-exclude.xml new file mode 100644 index 0000000000..5fd588b2c4 --- /dev/null +++ b/java/api-test/spotbugs-exclude.xml @@ -0,0 +1,4 @@ + + + + diff --git a/java/connectors/semantickernel-connectors-ai-openai/pom.xml b/java/connectors/semantickernel-connectors-ai-openai/pom.xml new file mode 100644 index 0000000000..be62a3ccc9 --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/pom.xml @@ -0,0 +1,37 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-connectors-ai-openai + + Semantic Kernel OpenAI Connectors + Defines OpenAI connectors to be used with the Semantic Kernel + + + + com.microsoft.semantic-kernel + semantickernel-api + + + jakarta.inject + jakarta.inject-api + + + org.mockito + mockito-core + + + org.junit.jupiter + junit-jupiter + + + + \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/azuresdk/ClientBase.java b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/azuresdk/ClientBase.java new file mode 100644 index 0000000000..447bdd4364 --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/azuresdk/ClientBase.java @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.azuresdk; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.ai.AIException; + +public abstract class ClientBase { + private final String modelId; + private final OpenAIAsyncClient client; + + public ClientBase(OpenAIAsyncClient client, String modelId) { + this.modelId = modelId; + this.client = client; + } + + protected String getModelId() { + return modelId; + } + + protected OpenAIAsyncClient getClient() { + return client; + } + + protected static void validateMaxTokens(int maxTokens) { + if (maxTokens < 1) { + throw new AIException( + AIException.ErrorCodes.INVALID_REQUEST, + "MaxTokens " + + maxTokens + + " is not valid, the value must be greater than zero"); + } + } +} diff --git a/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletion.java b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletion.java new file mode 100644 index 0000000000..acd6085407 --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletion.java @@ -0,0 +1,247 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.chatcompletion; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.ChatChoice; +import com.azure.ai.openai.models.ChatCompletions; +import com.azure.ai.openai.models.ChatCompletionsOptions; +import com.azure.ai.openai.models.ChatMessage; +import com.azure.ai.openai.models.ChatRole; +import com.microsoft.semantickernel.Verify; +import com.microsoft.semantickernel.ai.AIException; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.chatcompletion.ChatRequestSettings; +import com.microsoft.semantickernel.connectors.ai.openai.azuresdk.ClientBase; +import com.microsoft.semantickernel.exceptions.NotSupportedException; +import com.microsoft.semantickernel.exceptions.NotSupportedException.ErrorCodes; +import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings; +import com.microsoft.semantickernel.textcompletion.CompletionType; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.function.BiFunction; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** OpenAI chat completion client. */ +public class OpenAIChatCompletion extends ClientBase implements ChatCompletion { + + private CompletionType defaultCompletionType; + + public OpenAIChatCompletion( + OpenAIAsyncClient client, String modelId, CompletionType defaultCompletionType) { + super(client, modelId); + this.defaultCompletionType = defaultCompletionType; + } + + @Override + public Mono> completeAsync( + @Nonnull String text, @Nonnull CompletionRequestSettings requestSettings) { + ChatRequestSettings chatRequestSettings = new ChatRequestSettings(requestSettings); + return generateMessageAsync(createNewChat(text), chatRequestSettings).map(Arrays::asList); + } + + @Override + public Flux completeStreamAsync( + @Nonnull String text, @Nonnull CompletionRequestSettings requestSettings) { + ChatRequestSettings chatRequestSettings = new ChatRequestSettings(requestSettings); + return generateMessageStream(createNewChat(text), chatRequestSettings); + } + + @Override + public CompletionType defaultCompletionType() { + return defaultCompletionType; + } + + public static class Builder implements ChatCompletion.Builder { + + public Builder() {} + + @Nullable private OpenAIAsyncClient client; + @Nullable private String modelId; + private CompletionType defaultCompletionType = CompletionType.STREAMING; + + public Builder withOpenAIClient(OpenAIAsyncClient client) { + this.client = client; + return this; + } + + public Builder withDefaultCompletionType(CompletionType completionType) { + this.defaultCompletionType = completionType; + return this; + } + + public Builder withModelId(String modelId) { + this.modelId = modelId; + return this; + } + + @Override + public ChatCompletion build() { + if (client == null) { + throw new NotSupportedException(ErrorCodes.NOT_SUPPORTED, "OpenAI client not set"); + } + if (modelId == null) { + throw new NotSupportedException(ErrorCodes.NOT_SUPPORTED, "Model ID not set"); + } + return new OpenAIChatCompletion(client, modelId, defaultCompletionType); + } + } + + /** + * Generate a new chat message + * + * @param chat Chat history + * @param requestSettings AI request settings + * @return The response generated by the request + */ + @Override + public Mono generateMessageAsync( + OpenAIChatHistory chat, @Nullable ChatRequestSettings requestSettings) { + + if (requestSettings == null) { + requestSettings = new ChatRequestSettings(); + } + return this.internalGenerateChatMessageAsync(chat, requestSettings); + } + + /** + * Generate a new chat message + * + * @param chat Chat history + * @param requestSettings AI request settings + * @return The response generated by the request + */ + private Mono internalGenerateChatMessageAsync( + ChatHistory chat, ChatRequestSettings requestSettings) { + Verify.notNull(chat); + Verify.notNull(requestSettings); + + validateMaxTokens(requestSettings.getMaxTokens()); + ChatCompletionsOptions options = createChatCompletionsOptions(requestSettings, chat); + + return getClient() + .getChatCompletions(getModelId(), options) + .flatMap( + response -> { + if (response == null || response.getChoices().isEmpty()) { + return Mono.error( + new AIException( + AIException.ErrorCodes.INVALID_RESPONSE_CONTENT, + "Chat completions not found")); + } else { + return Mono.just( + response.getChoices().get(0).getMessage().getContent()); + } + }); + } + + private static ChatCompletionsOptions createChatCompletionsOptions( + ChatRequestSettings requestSettings, ChatHistory chat) { + List messages = + chat.getMessages().stream() + .map( + it -> + new ChatMessage( + toChatRole(it.getAuthorRoles()), it.getContent())) + .collect(Collectors.toList()); + + ChatCompletionsOptions options = new ChatCompletionsOptions(messages); + + options.setMaxTokens(requestSettings.getMaxTokens()); + options.setTemperature(requestSettings.getTemperature()); + options.setTopP(requestSettings.getTopP()); + options.setFrequencyPenalty(requestSettings.getFrequencyPenalty()); + options.setPresencePenalty(requestSettings.getPresencePenalty()); + options.setLogitBias(new HashMap<>()); + options.setN(requestSettings.getBestOf()); + options.setUser(requestSettings.getUser()); + options.setStop(requestSettings.getStopSequences()); + + return options; + } + + private static ChatRole toChatRole(ChatHistory.AuthorRoles authorRoles) { + switch (authorRoles) { + case System: + return ChatRole.SYSTEM; + case User: + return ChatRole.USER; + case Assistant: + return ChatRole.ASSISTANT; + default: + throw new IllegalArgumentException( + "Invalid chat message author: " + authorRoles.name()); + } + } + + @Override + public OpenAIChatHistory createNewChat(@Nullable String instructions) { + return internalCreateNewChat(instructions); + } + + @Override + public Flux generateMessageStream( + OpenAIChatHistory chat, @Nullable ChatRequestSettings requestSettings) { + return this.getStreamingChatCompletionsAsync(chat, requestSettings) + .groupBy(ChatCompletions::getId) + .concatMap( + chatCompletionResult -> { + return chatCompletionResult + .concatMap( + chatCompletions -> + Flux.fromIterable(chatCompletions.getChoices())) + .reduce("", accumulateString()); + }); + } + + private static BiFunction accumulateString() { + return (newString, chatChoice) -> { + ChatMessage message = chatChoice.getDelta(); + if (message != null && message.getContent() != null) { + return newString + message.getContent(); + } + return newString; + }; + } + + @Override + public Flux getStreamingChatCompletionsAsync( + OpenAIChatHistory chat, ChatRequestSettings requestSettings) { + return internalGetChatStreamingResultsAsync(chat, requestSettings); + } + + private Flux internalGetChatStreamingResultsAsync( + ChatHistory chat, @Nullable ChatRequestSettings requestSettings) { + Verify.notNull(chat); + if (requestSettings == null) { + requestSettings = new ChatRequestSettings(); + } + + ClientBase.validateMaxTokens(requestSettings.getMaxTokens()); + + ChatCompletionsOptions options = createChatCompletionsOptions(requestSettings, chat); + options = options.setStream(true); + + return getClient().getChatCompletionsStream(getModelId(), options); + } + + /** + * Create a new empty chat instance + * + * @param instructions Optional chat instructions for the AI service + * @return Chat object + */ + private static OpenAIChatHistory internalCreateNewChat(@Nullable String instructions) { + if (instructions == null) { + instructions = ""; + } + OpenAIChatHistory history = new OpenAIChatHistory("Assistant is a large language model."); + history.addUserMessage(instructions); + return history; + } +} diff --git a/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatHistory.java b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatHistory.java new file mode 100644 index 0000000000..772166808a --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatHistory.java @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.chatcompletion; + +import com.microsoft.semantickernel.chatcompletion.ChatHistory; +import javax.annotation.Nullable; + +/** OpenAI Chat content */ +public class OpenAIChatHistory extends ChatHistory { + + /** + * Create a new and empty chat history + * + * @param assistantInstructions Optional instructions for the assistant + */ + public OpenAIChatHistory(@Nullable String assistantInstructions) { + super(); + + if (assistantInstructions != null && !assistantInstructions.isEmpty()) { + this.addSystemMessage(assistantInstructions); + } + } + + /** + * Add a system message to the chat history + * + * @param content Message content + */ + public void addSystemMessage(String content) { + this.addMessage(AuthorRoles.System, content); + } + + /** + * Add an assistant message to the chat history + * + * @param content Message content + */ + public void addAssistantMessage(String content) { + this.addMessage(AuthorRoles.Assistant, content); + } + + /** + * Add a user message to the chat history + * + * @param content Message content + */ + public void addUserMessage(String content) { + this.addMessage(AuthorRoles.User, content); + } +} diff --git a/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textcompletion/OpenAITextCompletion.java b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textcompletion/OpenAITextCompletion.java new file mode 100644 index 0000000000..d30e5a565b --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textcompletion/OpenAITextCompletion.java @@ -0,0 +1,169 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.textcompletion; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.Choice; +import com.azure.ai.openai.models.Completions; +import com.azure.ai.openai.models.CompletionsOptions; +import com.microsoft.semantickernel.Verify; +import com.microsoft.semantickernel.ai.AIException; +import com.microsoft.semantickernel.chatcompletion.ChatRequestSettings; +import com.microsoft.semantickernel.connectors.ai.openai.azuresdk.ClientBase; +import com.microsoft.semantickernel.exceptions.NotSupportedException; +import com.microsoft.semantickernel.exceptions.NotSupportedException.ErrorCodes; +import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings; +import com.microsoft.semantickernel.textcompletion.CompletionType; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import jakarta.inject.Inject; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.function.BiFunction; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/// +/// OpenAI text completion service. +/// TODO: forward ETW logging to ILogger, see +// https://learn.microsoft.com/en-us/dotnet/azure/sdk/logging +/// +public class OpenAITextCompletion extends ClientBase implements TextCompletion { + + private final CompletionType defaultCompletionType; + + /// + /// Create an instance of the OpenAI text completion connector + /// + /// Model name + /// OpenAI API Key + /// OpenAI Organization Id (usually optional) + /// Retry handler factory for HTTP + /// requests. + /// Application logger + @Inject + public OpenAITextCompletion(OpenAIAsyncClient client, String modelId) { + super(client, modelId); + defaultCompletionType = CompletionType.STREAMING; + } + + public OpenAITextCompletion( + OpenAIAsyncClient client, String modelId, CompletionType defaultCompletionType) { + super(client, modelId); + + this.defaultCompletionType = defaultCompletionType; + } + + @Override + public Mono> completeAsync( + @Nonnull String text, @Nonnull CompletionRequestSettings requestSettings) { + return this.internalCompleteTextAsync(text, requestSettings); + } + + @Override + public Flux completeStreamAsync( + @Nonnull String text, @Nonnull CompletionRequestSettings requestSettings) { + CompletionsOptions completionsOptions = getCompletionsOptions(text, requestSettings); + + return generateMessageStream(completionsOptions); + } + + @Override + public CompletionType defaultCompletionType() { + return defaultCompletionType; + } + + private Flux generateMessageStream(CompletionsOptions completionsOptions) { + return getClient() + .getCompletionsStream(getModelId(), completionsOptions) + .groupBy(Completions::getId) + .concatMap( + completionResult -> { + return completionResult + .concatMap( + completion -> + Flux.fromIterable(completion.getChoices())) + .reduce("", accumulateString()); + }); + } + + private static BiFunction accumulateString() { + return (newText, choice) -> { + String message = choice.getText(); + if (!Verify.isNullOrEmpty(message)) { + return newText + message; + } + return newText; + }; + } + + protected Mono> internalCompleteTextAsync( + String text, CompletionRequestSettings requestSettings) { + CompletionsOptions completionsOptions = getCompletionsOptions(text, requestSettings); + + return getClient() + .getCompletions(getModelId(), completionsOptions) + .flatMapIterable(Completions::getChoices) + .mapNotNull(Choice::getText) + .collectList(); + } + + private CompletionsOptions getCompletionsOptions( + String text, CompletionRequestSettings requestSettings) { + if (requestSettings.getMaxTokens() < 1) { + throw new AIException(AIException.ErrorCodes.INVALID_REQUEST, "Max tokens must be >0"); + } + + CompletionsOptions options = + new CompletionsOptions(Collections.singletonList(text)) + .setMaxTokens(requestSettings.getMaxTokens()) + .setTemperature(requestSettings.getTemperature()) + .setTopP(requestSettings.getTopP()) + .setFrequencyPenalty(requestSettings.getFrequencyPenalty()) + .setPresencePenalty(requestSettings.getPresencePenalty()) + .setModel(getModelId()) + .setUser(requestSettings.getUser()) + .setBestOf(requestSettings.getBestOf()) + .setLogitBias(new HashMap<>()); + + if (requestSettings instanceof ChatRequestSettings) { + options = options.setStop(requestSettings.getStopSequences()); + } + return options; + } + + public static final class Builder implements TextCompletion.Builder { + + @Nullable private OpenAIAsyncClient client; + @Nullable private String modelId; + private CompletionType defaultCompletionType = CompletionType.STREAMING; + + public Builder withOpenAIClient(OpenAIAsyncClient client) { + this.client = client; + return this; + } + + public Builder withModelId(String modelId) { + this.modelId = modelId; + return this; + } + + @Override + public Builder withDefaultCompletionType(CompletionType completionType) { + this.defaultCompletionType = completionType; + return this; + } + + @Override + public TextCompletion build() { + if (client == null) { + throw new NotSupportedException(ErrorCodes.NOT_SUPPORTED, "OpenAI client not set"); + } + if (modelId == null) { + throw new NotSupportedException(ErrorCodes.NOT_SUPPORTED, "Model ID not set"); + } + return new OpenAITextCompletion(client, modelId, defaultCompletionType); + } + } +} diff --git a/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textembeddings/OpenAITextEmbeddingGeneration.java b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textembeddings/OpenAITextEmbeddingGeneration.java new file mode 100644 index 0000000000..1dbe3679a0 --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/textembeddings/OpenAITextEmbeddingGeneration.java @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.textembeddings; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.EmbeddingItem; +import com.azure.ai.openai.models.Embeddings; +import com.azure.ai.openai.models.EmbeddingsOptions; +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration; +import com.microsoft.semantickernel.connectors.ai.openai.azuresdk.ClientBase; +import com.microsoft.semantickernel.exceptions.NotSupportedException; +import com.microsoft.semantickernel.exceptions.NotSupportedException.ErrorCodes; +import java.util.List; +import java.util.stream.Collectors; +import reactor.core.publisher.Mono; + +public class OpenAITextEmbeddingGeneration extends ClientBase implements TextEmbeddingGeneration { + + public OpenAITextEmbeddingGeneration(OpenAIAsyncClient client, String modelId) { + super(client, modelId); + } + + @Override + public Mono> generateEmbeddingsAsync(List data) { + return this.internalGenerateTextEmbeddingsAsync(data); + } + + protected Mono> internalGenerateTextEmbeddingsAsync(List data) { + EmbeddingsOptions options = + new EmbeddingsOptions(data).setModel(getModelId()).setUser("default"); + + return getClient() + .getEmbeddings(getModelId(), options) + .flatMapIterable(Embeddings::getData) + .mapNotNull(EmbeddingItem::getEmbedding) + .map( + embedding -> + embedding.stream() + .map(Double::floatValue) + .collect(Collectors.toList())) + .mapNotNull(Embedding::new) + .collectList(); + } + + public static class Builder implements TextEmbeddingGeneration.Builder { + private OpenAIAsyncClient client; + private String modelId; + + public Builder withOpenAIClient(OpenAIAsyncClient client) { + this.client = client; + return this; + } + + public Builder withModelId(String modelId) { + this.modelId = modelId; + return this; + } + + @Override + public OpenAITextEmbeddingGeneration build() { + if (client == null) { + throw new NotSupportedException(ErrorCodes.NOT_SUPPORTED, "OpenAI client not set"); + } + if (modelId == null) { + throw new NotSupportedException(ErrorCodes.NOT_SUPPORTED, "Model ID not set"); + } + return new OpenAITextEmbeddingGeneration(client, modelId); + } + } +} diff --git a/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration$Builder b/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration$Builder new file mode 100644 index 0000000000..b2d9b9aab6 --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration$Builder \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.chatcompletion.ChatCompletion$Builder b/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.chatcompletion.ChatCompletion$Builder new file mode 100644 index 0000000000..d3912ddc26 --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.chatcompletion.ChatCompletion$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.connectors.ai.openai.chatcompletion.OpenAIChatCompletion$Builder \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.textcompletion.TextCompletion$Builder b/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.textcompletion.TextCompletion$Builder new file mode 100644 index 0000000000..39bdf4b287 --- /dev/null +++ b/java/connectors/semantickernel-connectors-ai-openai/src/main/resources/META-INF/services/com.microsoft.semantickernel.textcompletion.TextCompletion$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion$Builder \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/pom.xml b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/pom.xml new file mode 100644 index 0000000000..3ab6a1fb58 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/pom.xml @@ -0,0 +1,68 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-connectors-memory-azurecognitivesearch + + Semantic Kernel Azure Cognitive Search Memory Connector + Defines connector for Azure Cognitive Search to be used with the Semantic Kernel + + + + com.microsoft.semantic-kernel + semantickernel-api + + + com.azure + azure-ai-openai + test + + + com.azure + azure-search-documents + + + org.mockito + mockito-core + test + + + org.junit.jupiter + junit-jupiter + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.apache.logging.log4j + log4j-slf4j2-impl + test + + + com.microsoft.semantic-kernel + semantickernel-core + test + + + com.microsoft.semantic-kernel + semantickernel-settings-loader + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + test + + + + diff --git a/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryException.java b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryException.java new file mode 100644 index 0000000000..9456ae93af --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryException.java @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.azurecognitivesearch; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class AzureCognitiveSearchMemoryException extends SKException { + private final ErrorCodes errorCode; + + /** + * Create an exception with a message + * + * @param errorCode The error code + */ + public AzureCognitiveSearchMemoryException(@Nonnull ErrorCodes errorCode) { + this(errorCode, null, null); + } + + /** + * Create an exception with a message + * + * @param message a description of the cause of the exception + */ + public AzureCognitiveSearchMemoryException( + @Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + /** + * Create an exception with a message and a cause + * + * @param errorCode the error code + * @param message a description of the cause of the exception + * @param cause the cause of the exception + */ + public AzureCognitiveSearchMemoryException( + @Nonnull ErrorCodes errorCode, @Nullable String message, @Nullable Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + + public ErrorCodes getErrorCode() { + return errorCode; + } + + public enum ErrorCodes { + UNKNOWN_ERROR("Unknown error"), + INVALID_EMBEDDING_SIZE("Invalid embedding size"), + INVALID_INDEX_NAME("Invalid index name"), + READ_FAILURE("Read failure"), + WRITE_FAILURE("Write failure"); + + final String message; + + ErrorCodes(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } +} diff --git a/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryRecord.java b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryRecord.java new file mode 100644 index 0000000000..2d1e57f280 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryRecord.java @@ -0,0 +1,179 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.azurecognitivesearch; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.memory.MemoryRecord; +import com.microsoft.semantickernel.memory.MemoryRecordMetadata; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; + +/** + * Azure Cognitive Search record and index definition. Note: once defined, index cannot be modified. + */ +public final class AzureCognitiveSearchMemoryRecord { + + static final String ID = "Id"; + static final String TEXT = "Text"; + static final String DESCRIPTION = "Description"; + static final String ADDITIONAL_METADATA = "AdditionalMetadata"; + static final String EMBEDDING = "Embedding"; + static final String EXTERNAL_SOURCE_NAME = "ExternalSourceName"; + static final String IS_REFERENCE = "Reference"; + + private final String id; + + private final String text; + + private final String description; + + private final String additionalMetadata; + + private final List embedding; + + private final String externalSourceName; + + private final boolean isReference; + + @JsonCreator + public AzureCognitiveSearchMemoryRecord( + @JsonProperty(ID) String id, + @JsonProperty(TEXT) String text, + @JsonProperty(DESCRIPTION) String description, + @JsonProperty(ADDITIONAL_METADATA) String additionalMetadata, + @JsonProperty(EMBEDDING) List embedding, + @JsonProperty(EXTERNAL_SOURCE_NAME) String externalSourceName, + @JsonProperty(IS_REFERENCE) boolean isReference) { + this.id = id; + this.text = text; + this.description = description; + this.additionalMetadata = additionalMetadata; + this.embedding = embedding != null ? embedding : Collections.emptyList(); + this.externalSourceName = externalSourceName; + this.isReference = isReference; + } + + /** + * Record ID. The record is not filterable to save quota, also SK uses only semantic search. + * + * @return Record ID. + */ + public String getId() { + return id; + } + + /** + * Content is stored here. + * + * @return Content is stored here, {@code null} if not set. + */ + public String getText() { + return text; + } + + /** + * Optional description of the content, e.g. a title. This can be useful when indexing external + * data without pulling in the entire content. + * + * @return Optional description of the content, {@code null} if not set. + */ + public String getDescription() { + return description; + } + + /** + * Additional metadata. Currently, this is a String where you could store serialized data as + * JSON. In future the design might change to allow storing named values and leverage filters. + * + * @return Additional metadata, {@code null} if not set. + */ + public String getAdditionalMetadata() { + return additionalMetadata; + } + + /** + * Embedding vector. + * + * @return Embedding vector. + */ + public List getEmbedding() { + return embedding; + } + + /** + * Name of the external source, in cases where the content and the Id are referenced to external + * information. + * + * @return Name of the external source, in cases where the content and the Id are referenced to + * external information, {@code null} if not set. + */ + public String getExternalSourceName() { + return externalSourceName; + } + + /** + * Whether the record references external information. + * + * @return {@code true} if the record references external information, {@code false} otherwise. + */ + public boolean isReference() { + return isReference; + } + + public MemoryRecordMetadata toMemoryRecordMetadata() { + return new MemoryRecordMetadata( + this.isReference, + decodeId(this.id), + this.text, + this.description, + this.externalSourceName, + this.additionalMetadata); + } + + public static AzureCognitiveSearchMemoryRecord fromMemoryRecord(MemoryRecord record) { + return new AzureCognitiveSearchMemoryRecord( + record.getMetadata().getId(), + record.getMetadata().getText(), + record.getMetadata().getDescription(), + record.getMetadata().getAdditionalMetadata(), + record.getEmbedding().getVector(), + record.getMetadata().getExternalSourceName(), + record.getMetadata().isReference()); + } + + public MemoryRecord toMemoryRecord() { + return toMemoryRecord(true); + } + + public MemoryRecord toMemoryRecord(boolean withEmbeddings) { + return new MemoryRecord( + this.toMemoryRecordMetadata(), + new Embedding(withEmbeddings ? this.embedding : Collections.emptyList()), + this.id, + null); + } + + // ACS keys can contain only letters, digits, underscore, dash, equal sign, recommending + // to encode values with a URL-safe algorithm. + // Original Id + // Encoded id + static String encodeId(@Nullable String realId) { + if (realId == null) { + return ""; + } + byte[] bytes = Base64.getUrlEncoder().encode(realId.getBytes(StandardCharsets.UTF_8)); + return new String(bytes, StandardCharsets.UTF_8); + } + + static String decodeId(@Nullable String encodedId) { + if (encodedId == null) { + return ""; + } + byte[] bytes = Base64.getUrlDecoder().decode(encodedId.getBytes(StandardCharsets.UTF_8)); + return new String(bytes, StandardCharsets.UTF_8); + } +} diff --git a/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryStore.java b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryStore.java new file mode 100644 index 0000000000..bec59d97e0 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/main/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryStore.java @@ -0,0 +1,510 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.azurecognitivesearch; + +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.TokenCredential; +import com.azure.core.http.rest.Response; +import com.azure.core.util.ClientOptions; +import com.azure.core.util.MetricsOptions; +import com.azure.core.util.TracingOptions; +import com.azure.search.documents.SearchAsyncClient; +import com.azure.search.documents.SearchDocument; +import com.azure.search.documents.indexes.SearchIndexAsyncClient; +import com.azure.search.documents.indexes.SearchIndexClientBuilder; +import com.azure.search.documents.indexes.models.HnswParameters; +import com.azure.search.documents.indexes.models.HnswVectorSearchAlgorithmConfiguration; +import com.azure.search.documents.indexes.models.LexicalAnalyzerName; +import com.azure.search.documents.indexes.models.SearchField; +import com.azure.search.documents.indexes.models.SearchFieldDataType; +import com.azure.search.documents.indexes.models.SearchIndex; +import com.azure.search.documents.indexes.models.VectorSearch; +import com.azure.search.documents.indexes.models.VectorSearchAlgorithmMetric; +import com.azure.search.documents.models.IndexDocumentsOptions; +import com.azure.search.documents.models.IndexingResult; +import com.azure.search.documents.models.SearchOptions; +import com.azure.search.documents.models.SearchQueryVector; +import com.microsoft.semantickernel.SemanticKernelHttpSettings; +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.connectors.memory.azurecognitivesearch.AzureCognitiveSearchMemoryException.ErrorCodes; +import com.microsoft.semantickernel.memory.MemoryRecord; +import com.microsoft.semantickernel.memory.MemoryStore; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; +import reactor.util.function.Tuples; + +/** + * Semantic Memory implementation using Azure Cognitive Search. For more information about Azure + * Cognitive Search {@see https://learn.microsoft.com/azure/search/search-what-is-azure-search} + */ +public class AzureCognitiveSearchMemoryStore implements MemoryStore { + private static final String SEARCH_CONFIG_NAME = "searchConfig"; + + private final SearchIndexAsyncClient _adminClient; + + private final Map _clientsByIndex = new ConcurrentHashMap<>(); + private final Function memoryRecordMapper; + + /// + /// Create a new instance of memory storage using Azure Cognitive Search. + /// + /// Azure Cognitive Search URI, e.g. + // "https://contoso.search.windows.net" + /// API Key + + /** + * Create a new instance of memory storage using Azure Cognitive Search. + * + * @param endpoint Azure Cognitive Search URI, e.g. "https://contoso.search.windows.net" + * @param apiKey Azure API Key + */ + public AzureCognitiveSearchMemoryStore(@Nonnull String endpoint, @Nonnull String apiKey) { + this( + new SearchIndexClientBuilder() + .endpoint(endpoint) + .credential(new AzureKeyCredential(apiKey)) + .clientOptions(clientOptions()) + .buildAsyncClient(), + null); + } + + /** + * Create a new instance of memory storage using Azure Cognitive Search. + * + * @param endpoint Azure Cognitive Search URI, e.g. "https://contoso.search.windows.net" + * @param credentials Azure service credentials + */ + public AzureCognitiveSearchMemoryStore( + @Nonnull String endpoint, @Nonnull TokenCredential credentials) { + this( + new SearchIndexClientBuilder() + .endpoint(endpoint) + .credential(credentials) + .clientOptions(clientOptions()) + .buildAsyncClient(), + null); + } + + /** + * Create a new instance of memory storage using Azure Cognitive Search. + * + * @param searchIndexAsyncClient the Azure search documents index client to use + */ + public AzureCognitiveSearchMemoryStore( + @Nonnull SearchIndexAsyncClient searchIndexAsyncClient, + @Nullable Function memoryRecordMapper) { + this._adminClient = searchIndexAsyncClient; + this.memoryRecordMapper = memoryRecordMapper; + } + + @Override + public Mono createCollectionAsync(@Nonnull String collectionName) { + // Indexes are created when sending a record. The creation requires the size of the + // embeddings. + return Mono.empty(); + } + + @Override + public Mono> getCollectionsAsync() { + return this.getIndexesAsync(); + } + + @Override + public Mono doesCollectionExistAsync(@Nonnull String collectionName) { + String normalizedIndexName = normalizeIndexName(collectionName); + return getIndexesAsync() + .map( + list -> + list.stream() + .anyMatch( + name -> + name.equalsIgnoreCase(collectionName) + || name.equalsIgnoreCase( + normalizedIndexName))); + } + + @Override + public Mono deleteCollectionAsync(@Nonnull String collectionName) { + collectionName = normalizeIndexName(collectionName); + return _adminClient.deleteIndex(collectionName); + } + + @Override + public Mono upsertAsync(@Nonnull String collectionName, @Nonnull MemoryRecord record) { + collectionName = normalizeIndexName(collectionName); + return this.upsertRecordAsync( + collectionName, AzureCognitiveSearchMemoryRecord.fromMemoryRecord(record)); + } + + @Override + public Mono> upsertBatchAsync( + @Nonnull String collectionName, Collection records) { + if (records == null || records.isEmpty()) { + return Mono.just(Collections.emptyList()); + } + + collectionName = normalizeIndexName(collectionName); + List searchRecords = + records.stream() + .map(AzureCognitiveSearchMemoryRecord::fromMemoryRecord) + .collect(Collectors.toList()); + return upsertBatchAsync(collectionName, searchRecords); + } + + @Override + public Mono getAsync( + @Nonnull String collectionName, @Nonnull String key, boolean withEmbedding) { + collectionName = normalizeIndexName(collectionName); + key = AzureCognitiveSearchMemoryRecord.encodeId(key); + SearchAsyncClient client = this.getSearchClient(collectionName); + + return client.getDocumentWithResponse(key, AzureCognitiveSearchMemoryRecord.class, null) + .map( + response -> { + if (response.getStatusCode() == 404) { + throw new AzureCognitiveSearchMemoryException( + ErrorCodes.READ_FAILURE, "Index not found"); + } + return response.getValue().toMemoryRecord(withEmbedding); + }); + } + + @Override + public Mono> getBatchAsync( + @Nonnull String collectionName, + @Nonnull Collection keys, + boolean withEmbedding) { + // TODO: there _must_ be a better way than one request per key! + return Flux.fromIterable(keys) + .flatMap(key -> getAsync(collectionName, key, withEmbedding)) + .collect(Collectors.toList()); + } + + @Override + public Mono> getNearestMatchAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + float minRelevanceScore, + boolean withEmbedding) { + return getNearestMatchesAsync( + collectionName, embedding, 1, minRelevanceScore, withEmbedding) + .map(matches -> matches.iterator().next()); + } + + @Override + public Mono>> getNearestMatchesAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + int limit, + float minRelevanceScore, + boolean withEmbedding) { + return getNearestMatchesAsync( + collectionName, + embedding, + limit, + minRelevanceScore, + withEmbedding, + memoryRecordMapper); + } + + /** + * Gets the nearest matches to the {@link Embedding} of type {@code Float}. Does not guarantee + * that the collection exists. + * + *

If a memoryRecordMapper is provided this overrides any mapper provided when constructing + * this memory store. + * + * @param collectionName The name associated with a collection of embeddings. + * @param embedding The {@link Embedding} to compare the collection's embeddings with. + * @param limit The maximum number of similarity results to return. + * @param minRelevanceScore The minimum relevance threshold for returned results. + * @param withEmbedding If true, the embeddings will be returned in the memory records. + * @param memoryRecordMapper a mapper that controls how to map the search document to a memory + * record + * @return A collection of tuples where item1 is a {@link MemoryRecord} and item2 is its + * similarity score as a {@code Float}. + */ + public Mono>> getNearestMatchesAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + int limit, + float minRelevanceScore, + boolean withEmbedding, + @Nullable Function memoryRecordMapper) { + collectionName = normalizeIndexName(collectionName); + SearchAsyncClient client = getSearchClient(collectionName); + + SearchQueryVector searchVector = + new SearchQueryVector() + .setKNearestNeighborsCount(limit) + .setFields(AzureCognitiveSearchMemoryRecord.EMBEDDING) + .setValue(embedding.getVector()); + + SearchOptions searchOptions = new SearchOptions().setVectors(searchVector); + + return client.search(null, searchOptions) + .filter(result -> (double) minRelevanceScore <= result.getScore()) + .map( + result -> { + MemoryRecord memoryRecord; + if (memoryRecordMapper != null) { + SearchDocument doc = result.getDocument(SearchDocument.class); + memoryRecord = memoryRecordMapper.apply(doc); + } else { + AzureCognitiveSearchMemoryRecord doc = + result.getDocument(AzureCognitiveSearchMemoryRecord.class); + memoryRecord = doc.toMemoryRecord(withEmbedding); + } + float score = (float) result.getScore(); + return Tuples.of(memoryRecord, score); + }) + .collect(Collectors.toList()); + } + + @Override + public Mono removeAsync(@Nonnull String collectionName, @Nonnull String key) { + return removeBatchAsync(collectionName, Collections.singleton(key)); + } + + @Override + public Mono removeBatchAsync( + @Nonnull String collectionName, @Nonnull Collection keys) { + collectionName = normalizeIndexName(collectionName); + SearchAsyncClient client = this.getSearchClient(collectionName); + + List documents = + keys.stream() + .map(AzureCognitiveSearchMemoryRecord::encodeId) + .map( + key -> { + SearchDocument searchDocument = new SearchDocument(); + searchDocument.put("Id", key); // TODO: Id should be a constant + return searchDocument; + }) + .collect(Collectors.toList()); + + return client.deleteDocuments(documents).then(); + } + + static List searchFields(String configName, int embeddingSize) { + return Arrays.asList( + new SearchField(AzureCognitiveSearchMemoryRecord.ID, SearchFieldDataType.STRING) + .setKey(true) + .setFilterable(false), + new SearchField( + AzureCognitiveSearchMemoryRecord.EMBEDDING, + SearchFieldDataType.collection(SearchFieldDataType.SINGLE)) + .setSearchable(true) + .setVectorSearchDimensions(embeddingSize) + .setVectorSearchConfiguration(configName), + new SearchField(AzureCognitiveSearchMemoryRecord.TEXT, SearchFieldDataType.STRING) + .setSearchable(true) + .setFacetable(true) + .setAnalyzerName(LexicalAnalyzerName.EN_LUCENE), + new SearchField( + AzureCognitiveSearchMemoryRecord.DESCRIPTION, + SearchFieldDataType.STRING) + .setSearchable(true) + .setFacetable(true) + .setAnalyzerName(LexicalAnalyzerName.EN_LUCENE), + new SearchField( + AzureCognitiveSearchMemoryRecord.ADDITIONAL_METADATA, + SearchFieldDataType.STRING) + .setSearchable(true) + .setFacetable(true) + .setAnalyzerName(LexicalAnalyzerName.EN_LUCENE), + new SearchField( + AzureCognitiveSearchMemoryRecord.EXTERNAL_SOURCE_NAME, + SearchFieldDataType.STRING) + .setSearchable(true) + .setFacetable(true) + .setAnalyzerName(LexicalAnalyzerName.EN_LUCENE), + new SearchField( + AzureCognitiveSearchMemoryRecord.IS_REFERENCE, + SearchFieldDataType.BOOLEAN) + .setFilterable(true) + .setFacetable(true)); + } + + /** + * Create a new search index. + * + * @param indexName Index name + * @param embeddingSize Size of the embedding vector + * @return A Mono that completes when the index is created + */ + private Mono> createIndexAsync( + @Nonnull String indexName, int embeddingSize) { + if (embeddingSize < 1) { + throw new AzureCognitiveSearchMemoryException( + ErrorCodes.INVALID_EMBEDDING_SIZE, "the value must be greater than zero"); + } + + String normalizedIndexName = normalizeIndexName(indexName); + + VectorSearch vectorSearch = + new VectorSearch() + .setAlgorithmConfigurations( + Collections.singletonList( + new HnswVectorSearchAlgorithmConfiguration( + SEARCH_CONFIG_NAME) + .setParameters( + new HnswParameters() + .setMetric( + VectorSearchAlgorithmMetric + .COSINE)))); + + SearchIndex newIndex = + new SearchIndex(normalizedIndexName) + .setFields(searchFields(SEARCH_CONFIG_NAME, embeddingSize)) + .setVectorSearch(vectorSearch); + + return _adminClient.createIndexWithResponse(newIndex); + } + + private Mono> getIndexesAsync() { + return _adminClient.listIndexes().map(SearchIndex::getName).collect(Collectors.toList()); + } + + private Mono upsertRecordAsync( + @Nonnull String indexName, @Nonnull AzureCognitiveSearchMemoryRecord record) { + return upsertBatchAsync(indexName, Collections.singletonList(record)) + .map(Collection::iterator) + .map(Iterator::next); + } + + private Mono> upsertBatchAsync( + @Nonnull String indexName, @Nonnull List records) { + + if (records.isEmpty()) { + return Mono.just(Collections.emptyList()); + } + + List documents = + records.stream() + .map( + record -> { + SearchDocument searchDocument = new SearchDocument(); + searchDocument.put( + AzureCognitiveSearchMemoryRecord.ID, + AzureCognitiveSearchMemoryRecord.encodeId( + record.getId())); + searchDocument.put( + AzureCognitiveSearchMemoryRecord.TEXT, + record.getText()); + searchDocument.put( + AzureCognitiveSearchMemoryRecord.DESCRIPTION, + record.getDescription()); + searchDocument.put( + AzureCognitiveSearchMemoryRecord.EMBEDDING, + record.getEmbedding()); + searchDocument.put( + AzureCognitiveSearchMemoryRecord.ADDITIONAL_METADATA, + record.getAdditionalMetadata()); + searchDocument.put( + AzureCognitiveSearchMemoryRecord.EXTERNAL_SOURCE_NAME, + record.getExternalSourceName()); + searchDocument.put( + AzureCognitiveSearchMemoryRecord.IS_REFERENCE, + record.isReference()); + return searchDocument; + }) + .collect(Collectors.toList()); + + IndexDocumentsOptions options = new IndexDocumentsOptions().setThrowOnAnyError(true); + + int embeddingSize = + records.stream() + .map(AzureCognitiveSearchMemoryRecord::getEmbedding) + .map(List::size) + .max(Integer::compareTo) + .orElse(0); + + String normalizedIndexName = normalizeIndexName(indexName); + SearchAsyncClient client = this.getSearchClient(normalizedIndexName); + + return client.uploadDocumentsWithResponse(documents, options) + .map( + response -> { + if (response.getStatusCode() == 404) { + throw new AzureCognitiveSearchMemoryException( + ErrorCodes.INVALID_INDEX_NAME); + } + return response; + }) + .onErrorResume( + e -> + createIndexAsync(normalizedIndexName, embeddingSize) + .then( + client.uploadDocumentsWithResponse( + documents, options))) + .map( + response -> + response.getValue().getResults().stream() + .map(IndexingResult::getKey) + .collect(Collectors.toList())); + } + + /** + * Get a search client for the index specified. Note: the index might not exist, but we avoid + * checking everytime and the extra latency. + * + * @param indexName Index name + * @return Search client ready to read/write + */ + protected SearchAsyncClient getSearchClient(@Nonnull String indexName) { + String normalizedIndexName = normalizeIndexName(indexName); + return _clientsByIndex.computeIfAbsent( + normalizedIndexName, _adminClient::getSearchAsyncClient); + } + + ///

+ /// Options used by the Azure Cognitive Search client, e.g. User Agent. + /// See also + // https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/DiagnosticsOptions.cs + /// + private static ClientOptions clientOptions() { + return SemanticKernelHttpSettings.getUserAgent() + .setTracingOptions(new TracingOptions()) + .setMetricsOptions(new MetricsOptions()); + } + + // Index names cannot contain special chars. We use this rule to replace a few common ones + // with an underscore and reduce the chance of errors. If other special chars are used, we leave + // it + // to the service to throw an error. + // Note: + // - replacing chars introduces a small chance of conflicts, e.g. "the-user" and "the_user". + // - we should consider whether making this optional and leave it to the developer to handle. + // + // Java 8 does not support \s for whitespace, so we have to list them all. + private static final String whitespace = " |\\t|\\n|\\x0B|\\f|\\r"; + private static final String s_replaceIndexNameSymbolsRegex = "[" + whitespace + "|\\|/|.|_|:]"; + + // Normalize index name to match ACS rules. + // See https://learn.microsoft.com/en-us/rest/api/searchservice/Create-Index + // The method doesn't handle all the error scenarios, leaving it to the service + // to throw an error for edge cases not handled locally. + // Value to normalize + // Normalized name + private static String normalizeIndexName(String indexName) { + if (indexName.length() > 128) { + throw new IllegalArgumentException("The collection name cannot exceed 128 chars"); + } + + indexName = indexName.toLowerCase(Locale.ROOT); + return indexName.replaceAll(s_replaceIndexNameSymbolsRegex, "-"); + } +} diff --git a/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/test/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryTests.java b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/test/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryTests.java new file mode 100644 index 0000000000..e1d081c828 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-azurecognitivesearch/src/test/java/com/microsoft/semantickernel/connectors/memory/azurecognitivesearch/AzureCognitiveSearchMemoryTests.java @@ -0,0 +1,434 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.azurecognitivesearch; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.azure.core.http.HttpHeaders; +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.HttpRequest; +import com.azure.core.http.HttpResponse; +import com.azure.core.http.rest.Response; +import com.azure.core.util.Context; +import com.azure.core.util.tracing.Tracer; +import com.azure.search.documents.SearchAsyncClient; +import com.azure.search.documents.SearchDocument; +import com.azure.search.documents.indexes.SearchIndexAsyncClient; +import com.azure.search.documents.models.SearchResult; +import com.azure.search.documents.util.SearchPagedFlux; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration; +import com.microsoft.semantickernel.memory.MemoryQueryResult; +import com.microsoft.semantickernel.memory.MemoryRecord; +import com.microsoft.semantickernel.memory.MemoryRecordMetadata; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.function.Function; +import javax.annotation.Nullable; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +class AzureCognitiveSearchMemoryTests { + + // com.azure.core.implementation.http.rest.RestProxyBase.RestProxyBase + // expects a non-null tracer. There is a TracerProvider in the Azure SDK + // that can be used to create a tracer, but it has some ceremony around + // it. We create a simple no-op tracer instead. + private static class NoOpTracer implements Tracer { + + @Override + public Context start(String methodName, Context context) { + return context; + } + + @Override + public void end(String errorMessage, Throwable throwable, Context context) {} + + @Override + public void setAttribute(String key, String value, Context context) {} + + @Override + public boolean isEnabled() { + // we could also set a property to disable tracing, but this is simpler. + return false; + } + } + + // Kernel is configured with a real AzureCognitiveSearchMemoryStore which is backed + // by a mocked HttpPipeline. The HttpPipeline is mocked to return a mocked + // HttpResponse whose body and status code are configured by the test. + Kernel kernel; + + // + // A test may generate more than one HttpRequest. This function + // can be set in the test to return the appropriate response body + // for each request. + // + // A good place to set a breakpoint for debugging exceptions in + // deserializing the response body is: + // com.azure.search.documents.implementation.util.MappingUtils#exceptionMapper + // + Function responseBody; + + // + // A test may generate more than one HttpRequest. This function + // can be set in the test to return the appropriate HTTP status + // code for each request. + // + Function responseStatusCode; + + @BeforeEach + void setUp() { + kernel = buildKernel(null); + } + + private Kernel buildKernel( + @Nullable Function memoryRecordMapper) { + SearchAsyncClient searchAsyncClient = Mockito.mock(SearchAsyncClient.class); + SearchIndexAsyncClient searchIndexAsyncClient = Mockito.mock(SearchIndexAsyncClient.class); + Response response = Mockito.mock(Response.class); + AzureCognitiveSearchMemoryRecord azureCognitiveSearchMemoryRecord = + Mockito.mock(AzureCognitiveSearchMemoryRecord.class); + MemoryRecord memoryRecord = Mockito.mock(MemoryRecord.class); + SearchPagedFlux searchPagedFlux = Mockito.mock(SearchPagedFlux.class); + SearchResult searchResult = Mockito.mock(SearchResult.class); + + Mockito.when(searchResult.getDocument(Mockito.any())).thenReturn(new SearchDocument()); + Mockito.when(searchIndexAsyncClient.getSearchAsyncClient(Mockito.any())) + .thenReturn(searchAsyncClient); + + Mockito.when(searchPagedFlux.filter(Mockito.any())).thenReturn(Flux.just(searchResult)); + + Mockito.when( + searchAsyncClient.getDocumentWithResponse( + Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Mono.just(response)); + + Mockito.when(searchAsyncClient.search(Mockito.any(), Mockito.any())) + .thenReturn(searchPagedFlux); + Mockito.when(response.getValue()).thenReturn(azureCognitiveSearchMemoryRecord); + Mockito.when(azureCognitiveSearchMemoryRecord.toMemoryRecord(Mockito.anyBoolean())) + .thenReturn(memoryRecord); + + EmbeddingGeneration embeddingGeneration = + new EmbeddingGeneration() { + /* + new SearchIndexClientBuilder() + .endpoint("https://fake-random-test-host/fake-path") + .credential(new AzureKeyCredential(apiKey)) + .pipeline(pipeline) + .httpLogOptions( + new HttpLogOptions() + .setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) + .buildAsyncClient(); + + */ + + List embeddings = new ArrayList<>(); + + { + embeddings.add(new Embedding(Arrays.asList(1.0f, 2.0f, 3.0f))); + } + + @Override + public Mono> generateEmbeddingsAsync(List data) { + return Mono.just(embeddings); + } + }; + + return SKBuilders.kernel() + .withMemoryStorage( + new AzureCognitiveSearchMemoryStore( + searchIndexAsyncClient, memoryRecordMapper)) + .withDefaultAIService(embeddingGeneration) + .build(); + } + + private HttpPipeline setUpHttpPipeline() { + + HttpPipeline pipeline = Mockito.mock(HttpPipeline.class); + + Tracer tracer = new NoOpTracer(); + Mockito.when(pipeline.getTracer()).thenReturn(tracer); + + Mockito.when(pipeline.send(Mockito.any(HttpRequest.class), Mockito.any(Context.class))) + .thenAnswer(this::answerHttpRequest); + + return pipeline; + } + + private Mono answerHttpRequest(InvocationOnMock invocation) { + HttpRequest request = invocation.getArgument(0); + + String query = request.getUrl().getQuery(); + int offset = query.indexOf("api-version"); + assertTrue(offset >= 0); + // HttpResponse is based on this api-version + assertEquals("api-version=2023-07-01-Preview", query.substring(offset)); + + // System.err.println(request.getHttpMethod() + " " + request.getUrl() + "\n\t" + + // request.getHeaders()); + byte[] body = responseBody.apply(request).getBytes(StandardCharsets.UTF_8); + int statusCode = responseStatusCode.apply(request); + HttpHeaders httpHeaders = + new HttpHeaders().add("Content-Type", "application/json; charset=utf-8"); + + HttpResponse httpResponse = Mockito.mock(HttpResponse.class); + Mockito.when(httpResponse.getRequest()).thenReturn(request); + Mockito.when(httpResponse.getHeaders()).thenReturn(httpHeaders); + Mockito.when(httpResponse.getBodyAsByteArray()).thenReturn(Mono.just(body)); + Mockito.when(httpResponse.getStatusCode()).thenReturn(statusCode); + return Mono.just(httpResponse); + } + + @Disabled("Pending https://github.com/microsoft/semantic-kernel/issues/1797") + @Test + void azureCognitiveSearchMemoryStoreShouldBeProperlyInitialized() { + // Arrange + responseBody = httpRequest -> "{\"value\": [{\"name\": \"fake-index\"}]}"; + responseStatusCode = httpResponse -> 200; + + // Act + // This call triggers a subsequent call to Azure Cognitive Search Memory store. + List collections = kernel.getMemory().getCollectionsAsync().block(); + + // Assert + assertTrue(collections.contains("fake-index")); + } + + @Disabled("Pending https://github.com/microsoft/semantic-kernel/issues/1797") + @Test + void azureCognitiveSearchMemoryStoreCanSaveReferenceAsync() { + // Arrange + responseBody = + httpRequest -> + "{\"value\": [" + + " {" + + " \"key\": \"fake-key\"," + + " \"status\": true," + + " \"errorMessage\": null," + + " \"statusCode\": 200" + + " }" + + " ]" + + "}"; + + responseStatusCode = httpRequest -> 200; + + // Act + String key = + kernel.getMemory() + .saveReferenceAsync( + "fake-index", + "fake-text", + "fake-externalId", + "fake-externalSourceName", + "fake-description", + "fake-additionalMetadata") + .block(); + + // Assert + assertEquals("fake-key", key); + } + + @Disabled("Pending https://github.com/microsoft/semantic-kernel/issues/1797") + @Test + void azureCognitiveSearchMemoryStoreCanSaveInformationAsync() { + // Arrange + responseBody = + httpRequest -> + "{\"value\": [" + + " {" + + " \"key\": \"fake-key\"," + + " \"status\": true," + + " \"errorMessage\": null," + + " \"statusCode\": 200" + + " }" + + " ]" + + "}"; + + responseStatusCode = httpRequest -> 200; + + // Act + String key = + kernel.getMemory() + .saveInformationAsync( + "fake-index", + "fake-text", + "fake-externalId", + "fake-description", + "fake-additionalMetadata") + .block(); + + // Assert + assertEquals("fake-key", key); + } + + @Disabled("Pending https://github.com/microsoft/semantic-kernel/issues/1797") + @Test + void azureCognitiveSearchMemoryStoreGetAsync() { + // Arrange + String key = "fake-key"; + String base64EncodedKey = + new String( + Base64.getUrlEncoder().encode("fake-key".getBytes(StandardCharsets.UTF_8))); + + responseBody = + httpRequest -> + "{" + + " \"Id\": \"" + + base64EncodedKey + + "\"," + + " \"Text\": \"fake-text\"," + + " \"Description\": \"fake-description\"," + + " \"AdditionalMetadata\": \"fake-additionalmetadata\"," + + " \"ExternalSourceName\": \"fake-externalsourcename\"," + + " \"Reference\": false" + + "}"; + + responseStatusCode = httpRequest -> 200; + + // Act + MemoryQueryResult result = kernel.getMemory().getAsync("fake-index", key, false).block(); + + // Assert + assertEquals(key, result.getMetadata().getId()); + } + + @Disabled("Pending https://github.com/microsoft/semantic-kernel/issues/1797") + @Test + void azureCognitiveSearchMemoryStoreRemoveAsync() { + // Arrange + String key = "fake-key"; + String base64EncodedKey = + new String( + Base64.getUrlEncoder().encode("fake-key".getBytes(StandardCharsets.UTF_8))); + + responseBody = + httpRequest -> + "{\"value\": [" + + " {" + + " \"key\": \"" + + base64EncodedKey + + "\"," + + " \"status\": true," + + " \"errorMessage\": null," + + " \"statusCode\": 200" + + " }" + + " ]" + + "}"; + ; + + responseStatusCode = httpRequest -> 200; + + // Act + kernel.getMemory().removeAsync("fake-index", key).block(); + + // Assert + } + + @Disabled("Pending https://github.com/microsoft/semantic-kernel/issues/1797") + @Test + void azureCognitiveSearchMemoryStoreSearchAsync() { + // Arrange + String key = "fake-key"; + String base64EncodedKey = + new String( + Base64.getUrlEncoder().encode("fake-key".getBytes(StandardCharsets.UTF_8))); + + responseBody = + httpRequest -> + "{\"value\": [" + + "{" + + " \"@search.score\": 1," + + " \"@search.highlights\": {" + + " \"Text\": [\"It was a dark and stormy night\"]" + + " }," + + " \"@search.features\": {" + + " \"Text\": {" + + " \"uniqueTokenMatches\": 1," + + " \"similarityScore\": 0.8," + + " \"termFrequency\": 0.99" + + " }" + + " }," + + " \"Id\": \"" + + base64EncodedKey + + "\"," + + " \"Text\": \"fake-text\"," + + " \"Description\": \"fake-description\"," + + " \"AdditionalMetadata\": \"fake-additionalmetadata\"," + + " \"ExternalSourceName\": \"fake-externalsourcename\"," + + " \"Reference\": false" + + "}" + + "]}"; + + responseStatusCode = httpRequest -> 200; + + // Act + List results = + kernel.getMemory().searchAsync("fake-index", "fake-query", 1, 0.5f, false).block(); + + // Assert + assertEquals(1, results.size()); + assertEquals(key, results.get(0).getMetadata().getId()); + } + + @Test + void azureCognitiveSearchMemoryStoreGetAsyncWithCustomMapping() { + // Do not convert to lambda, it will break mockito + Function transform = + Mockito.spy( + new Function() { + @Override + public MemoryRecord apply(SearchDocument searchDocument) { + return new MemoryRecord( + new MemoryRecordMetadata( + false, + "an-id", + "fake-text", + "fake-description", + "fake-additionalmetadata", + "fake-externalsourcename"), + new Embedding(Arrays.asList(1.0f, 2.0f, 3.0f)), + "an-id", + null); + } + }); + + kernel = buildKernel(transform); + // Arrange + String key = "fake-key"; + String base64EncodedKey = + new String( + Base64.getUrlEncoder().encode("fake-key".getBytes(StandardCharsets.UTF_8))); + + responseBody = + httpRequest -> + "{" + + " \"Id\": \"" + + base64EncodedKey + + "\"," + + " \"Text\": \"fake-text\"," + + " \"Description\": \"fake-description\"," + + " \"AdditionalMetadata\": \"fake-additionalmetadata\"," + + " \"ExternalSourceName\": \"fake-externalsourcename\"," + + " \"Reference\": false" + + "}"; + + responseStatusCode = httpRequest -> 200; + + // Act + kernel.getMemory().searchAsync("fake-index", "a-query", 1, 0.0f, false).block(); + + Mockito.verify(transform, Mockito.atLeastOnce()).apply(Mockito.any()); + } +} diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/pom.xml b/java/connectors/semantickernel-connectors-memory-jdbc/pom.xml new file mode 100644 index 0000000000..eaa692e290 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-connectors-memory-jdbc + Semantic Kernel JDBC Memory Connector + + + + com.fasterxml.jackson.core + jackson-core + compile + + + com.fasterxml.jackson.core + jackson-databind + compile + + + + com.microsoft.semantic-kernel + semantickernel-api + + + org.mockito + mockito-core + + + org.junit.jupiter + junit-jupiter + + + org.apache.logging.log4j + log4j-api + test + + + org.apache.logging.log4j + log4j-core + test + + + com.microsoft.semantic-kernel + semantickernel-api + + + + + + \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/semantickernel-connectors-memory-jdbc.iml b/java/connectors/semantickernel-connectors-memory-jdbc/semantickernel-connectors-memory-jdbc.iml new file mode 100644 index 0000000000..224fc7d9a8 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/semantickernel-connectors-memory-jdbc.iml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/DatabaseEntry.java b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/DatabaseEntry.java new file mode 100644 index 0000000000..05941fdc01 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/DatabaseEntry.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.jdbc; + +import com.microsoft.semantickernel.memory.DataEntryBase; +import java.time.ZonedDateTime; + +/** Represents an entry in the Semantic Kernel Memory Table. */ +public class DatabaseEntry extends DataEntryBase { + private final String embedding; // JSON with the embedding information + private final String metadata; // JSON with the metadata associated + + /** + * Creates a new instance of DatabaseEntry. + * + * @param key The key identifying the entry. + * @param metadata The metadata associated. + * @param embedding The embedding information associated. + * @param timestamp The timestamp indicating when the entry was created or modified. + */ + public DatabaseEntry(String key, String metadata, String embedding, ZonedDateTime timestamp) { + super(key, timestamp); + this.metadata = metadata; + this.embedding = embedding; + } + + /** + * Gets the metadata associated with the entry. + * + * @return The metadata associated with the entry. + */ + public String getMetadata() { + return metadata; + } + + /** + * Gets the embedding information associated with the entry. + * + * @return The embedding information associated with the entry. + */ + public String getEmbedding() { + return embedding; + } +} diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCConnector.java b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCConnector.java new file mode 100644 index 0000000000..c16922048a --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCConnector.java @@ -0,0 +1,495 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.jdbc; + +import com.microsoft.semantickernel.memory.MemoryException; +import com.microsoft.semantickernel.memory.MemoryException.ErrorCodes; +import java.io.Closeable; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +public class JDBCConnector implements SQLConnector, Closeable { + protected final Connection connection; + + public JDBCConnector(Connection connection) { + this.connection = connection; + } + + // Convenience method to format a ZonedDateTime in a format acceptable to SQL + protected static String formatDatetime(@Nullable ZonedDateTime datetime) { + if (datetime == null) return ""; + return datetime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + // Convenience method to parse a SQL datetime string into a ZonedDateTime + protected static ZonedDateTime parseDatetime(@Nullable String datetime) { + if (datetime == null || datetime.isEmpty()) return null; + return ZonedDateTime.parse(datetime, DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + protected static final String COLLECTIONS_TABLE_NAME = "SKCollectionTable"; + protected static final String TABLE_NAME = "SKMemoryTable"; + protected static final String INDEX_NAME = "SKMemoryIndex"; + + /** + * Returns the name of the table that stores the collection names. + * + * @return The name of the table that stores the collection names. + */ + protected static String DEFAULT_COLLECTIONS_TABLE_NAME() { + return COLLECTIONS_TABLE_NAME; + } + + /** + * Returns the name of the Semantic Kernel table. + * + * @return The name of the Semantic Kernel table. + */ + protected static String DEFAULT_TABLE_NAME() { + return TABLE_NAME; + } + + /** + * Returns the name of the index on the Semantic Kernel table. + * + * @return The name of the index on the Semantic Kernel table. + */ + protected static String DEFAULT_INDEX_NAME() { + return INDEX_NAME; + } + + public Mono createTableAsync() { + return Mono.fromRunnable( + () -> { + String createCollectionKeyTable = + "CREATE TABLE IF NOT EXISTS " + + COLLECTIONS_TABLE_NAME + + " (" + + "id TEXT PRIMARY KEY" + + " )"; + + String createSKMemoryTable = + "CREATE TABLE IF NOT EXISTS " + + TABLE_NAME + + " (" + + "collection TEXT NOT NULL, " + + "key TEXT NOT NULL, " + + "metadata TEXT, " + + "embedding TEXT, " + + "timestamp TEXT, " + + "PRIMARY KEY (collection, key), " + + "FOREIGN KEY (collection) REFERENCES " + + COLLECTIONS_TABLE_NAME + + "(id)" + + " )"; + + String createIndex = + "CREATE INDEX IF NOT EXISTS " + + INDEX_NAME + + " ON " + + TABLE_NAME + + "(collection)"; + + try (Statement statement = this.connection.createStatement()) { + statement.addBatch(createCollectionKeyTable); + statement.addBatch(createSKMemoryTable); + statement.addBatch(createIndex); + statement.executeBatch(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"CREATE TABLE\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + public Mono createCollectionAsync(String collectionName) { + return Mono.fromRunnable( + () -> { + String query = + "INSERT INTO " + COLLECTIONS_TABLE_NAME + " (id) VALUES (?)"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"INSERT INTO\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + public Mono upsertAsync( + String collection, + String key, + String metadata, + String embedding, + ZonedDateTime timestamp) { + return Mono.fromRunnable( + () -> { + String query = + "INSERT OR REPLACE INTO " + + TABLE_NAME + + " (collection, key, metadata, embedding, timestamp)" + + " VALUES (?, ?, ?, ?, ?)"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collection); + statement.setString(2, key); + statement.setString(3, metadata != null ? metadata : ""); + statement.setString(4, embedding != null ? embedding : ""); + statement.setString(5, formatDatetime(timestamp)); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"INSERT OR REPLACE INTO\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .thenReturn(key); + } + + @Override + public Mono> upsertBatchAsync( + String collection, Collection records) { + Collection keys = new ArrayList<>(); + return Mono.fromRunnable( + () -> { + String query = + "INSERT OR REPLACE INTO " + + TABLE_NAME + + " (collection, key, metadata, embedding, timestamp)" + + " VALUES (?, ?, ?, ?, ?)"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + for (DatabaseEntry entry : records) { + statement.setString(1, collection); + statement.setString(2, entry.getKey()); + statement.setString( + 3, + entry.getMetadata() != null ? entry.getMetadata() : ""); + statement.setString( + 4, + entry.getEmbedding() != null + ? entry.getEmbedding() + : ""); + statement.setString(5, formatDatetime(entry.getTimestamp())); + statement.addBatch(); + keys.add(entry.getKey()); + } + + statement.executeBatch(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"INSERT OR REPLACE INTO\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .thenReturn(keys); + } + + public Mono doesCollectionExistsAsync(String collectionName) { + return Mono.fromCallable(() -> doesCollectionExists(collectionName)) + .subscribeOn(Schedulers.boundedElastic()); + } + + private boolean doesCollectionExists(String collectionName) throws SQLException { + String query = "SELECT id FROM " + COLLECTIONS_TABLE_NAME + " WHERE id = ?"; + try (PreparedStatement statement = this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + ResultSet resultSet = statement.executeQuery(); + return resultSet.next(); + } + } + + public Mono> getCollectionsAsync() { + return Mono.defer( + () -> { + List collections = new ArrayList<>(); + String query = "SELECT id FROM " + COLLECTIONS_TABLE_NAME; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + String collection = resultSet.getString("id"); + collections.add(collection); + } + } catch (SQLException e) { + return Mono.error( + new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"SELECT\" failed", + e)); + } + return Mono.just(collections); + }) + .subscribeOn(Schedulers.boundedElastic()); + } + + public Mono> readAllAsync(String collectionName) { + return Mono.defer( + () -> { + List entries = new ArrayList<>(); + String query = "SELECT * FROM " + TABLE_NAME + " WHERE collection = ?"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + String key = resultSet.getString("key"); + String metadata = resultSet.getString("metadata"); + String embedding = resultSet.getString("embedding"); + String timestamp = resultSet.getString("timestamp"); + ZonedDateTime zonedDateTime = parseDatetime(timestamp); + entries.add( + new DatabaseEntry( + key, metadata, embedding, zonedDateTime)); + } + } catch (SQLException e) { + return Mono.error( + new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"SELECT * FROM\" failed", + e)); + } + return Mono.just(entries); + }) + .subscribeOn(Schedulers.boundedElastic()); + } + + public Mono readAsync(String collectionName, String key) { + return Mono.defer( + () -> { + String query = + "SELECT * FROM " + + TABLE_NAME + + " WHERE collection = ?" + + " AND key = ?"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + statement.setString(2, key != null && !key.isEmpty() ? key : null); + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + String metadata = resultSet.getString("metadata"); + String embedding = resultSet.getString("embedding"); + String timestamp = resultSet.getString("timestamp"); + ZonedDateTime zonedDateTime = parseDatetime(timestamp); + return Mono.just( + new DatabaseEntry( + key, metadata, embedding, zonedDateTime)); + } + } catch (SQLException e) { + return Mono.error( + new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"SELECT * FROM\" failed", + e)); + } + return Mono.empty(); + }) + .subscribeOn(Schedulers.boundedElastic()); + } + + protected enum BatchOperation { + SELECT, + DELETE + } + + protected String batchQuery(BatchOperation operation, Collection keys) { + String queryPrefix; + switch (operation) { + case SELECT: + queryPrefix = "SELECT * FROM " + TABLE_NAME + " WHERE collection = ?"; + break; + case DELETE: + queryPrefix = "DELETE FROM " + TABLE_NAME + " WHERE collection = ?"; + break; + default: + throw new IllegalArgumentException("Invalid batch operation"); + } + StringBuilder queryBuilder = new StringBuilder(queryPrefix); + queryBuilder.append(" AND key IN ("); + + // Add placeholders for each key + for (int i = 0; i < keys.size(); i++) { + queryBuilder.append("?"); + if (i < keys.size() - 1) { + queryBuilder.append(","); + } + } + + queryBuilder.append(")"); + return queryBuilder.toString(); + } + + @Override + public Mono> readBatchAsync( + String collectionName, Collection keys) { + return Mono.defer( + () -> { + Collection entries = new ArrayList<>(); + String query = batchQuery(BatchOperation.SELECT, keys); + + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + int index = 2; + for (String key : keys) { + statement.setString(index++, key); + } + ResultSet resultSet = statement.executeQuery(); + + while (resultSet.next()) { + String key = resultSet.getString("key"); + String metadata = resultSet.getString("metadata"); + String embedding = resultSet.getString("embedding"); + String timestamp = resultSet.getString("timestamp"); + ZonedDateTime zonedDateTime = parseDatetime(timestamp); + entries.add( + new DatabaseEntry( + key, metadata, embedding, zonedDateTime)); + } + } catch (SQLException e) { + return Mono.error( + new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"SELECT * FROM\" failed", + e)); + } + return Mono.just(entries); + }) + .subscribeOn(Schedulers.boundedElastic()); + } + + public Mono deleteCollectionAsync(String collectionName) { + return Mono.fromRunnable( + () -> { + String query1 = "DELETE FROM " + TABLE_NAME + " WHERE collection = ?"; + String query2 = + "DELETE FROM " + COLLECTIONS_TABLE_NAME + " WHERE id = ?"; + try (PreparedStatement statement = + this.connection.prepareStatement(query1); + PreparedStatement statement2 = + this.connection.prepareStatement(query2)) { + statement.setString(1, collectionName); + statement.executeUpdate(); + statement2.setString(1, collectionName); + if (statement2.executeUpdate() == 0) { + throw new MemoryException( + ErrorCodes.ATTEMPTED_TO_ACCESS_NONEXISTENT_COLLECTION); + } + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"DELETE FROM\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + public Mono deleteAsync(String collectionName, String key) { + return Mono.fromRunnable( + () -> { + String query = + "DELETE FROM " + + TABLE_NAME + + " WHERE collection = ?" + + " AND key = ?"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + statement.setString(2, key != null && !key.isEmpty() ? key : null); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"DELETE FROM\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + public Mono deleteBatchAsync(String collectionName, Collection keys) { + return Mono.fromRunnable( + () -> { + String query = batchQuery(BatchOperation.DELETE, keys); + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + int index = 2; + for (String key : keys) { + statement.setString(index++, key); + } + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"DELETE FROM\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + public Mono deleteEmptyAsync(String collectionName) { + return Mono.fromRunnable( + () -> { + String query = + "DELETE FROM " + + TABLE_NAME + + " WHERE collection = ?" + + " AND key is NULL"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"DELETE FROM\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + @Override + public void close() { + try { + this.connection.close(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "Database access error while closing connection", + e); + } + } +} diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCMemoryStore.java b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCMemoryStore.java new file mode 100644 index 0000000000..9c25486d8d --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCMemoryStore.java @@ -0,0 +1,316 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.jdbc; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.memory.MemoryException; +import com.microsoft.semantickernel.memory.MemoryException.ErrorCodes; +import com.microsoft.semantickernel.memory.MemoryRecord; +import java.sql.Connection; +import java.util.*; +import java.util.stream.Collectors; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; +import reactor.util.function.Tuples; + +public class JDBCMemoryStore implements SQLMemoryStore { + protected final SQLConnector dbConnector; + + protected JDBCMemoryStore(SQLConnector connector) { + this.dbConnector = connector; + } + + @Override + public Mono createCollectionAsync(@Nonnull String collectionName) { + Objects.requireNonNull(collectionName); + return this.dbConnector.createCollectionAsync(collectionName); + } + + @Override + public Mono> getCollectionsAsync() { + return this.dbConnector.getCollectionsAsync(); + } + + @Override + public Mono doesCollectionExistAsync(@Nonnull String collectionName) { + Objects.requireNonNull(collectionName); + return this.dbConnector.doesCollectionExistsAsync(collectionName); + } + + @Override + public Mono deleteCollectionAsync(@Nonnull String collectionName) { + Objects.requireNonNull(collectionName); + return this.dbConnector.deleteCollectionAsync(collectionName); + } + + @Override + public Mono upsertAsync(@Nonnull String collectionName, @Nonnull MemoryRecord record) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(record); + return doesCollectionExistAsync(collectionName) + .handle( + (exists, sink) -> { + if (!exists) { + sink.error( + new MemoryException( + ErrorCodes + .ATTEMPTED_TO_ACCESS_NONEXISTENT_COLLECTION, + collectionName)); + return; + } + sink.next(exists); + }) + .then(internalUpsertAsync(collectionName, record)); + } + + protected DatabaseEntry memoryRecordToDatabaseEntry(MemoryRecord record) { + try { + return new DatabaseEntry( + record.getMetadata().getId(), + record.getSerializedMetadata(), + record.getSerializedEmbedding(), + record.getTimestamp()); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + protected MemoryRecord databaseEntryToMemoryRecord(DatabaseEntry entry, boolean withEmbedding) { + try { + Embedding embedding = + withEmbedding + ? new ObjectMapper().readValue(entry.getEmbedding(), Embedding.class) + : Embedding.empty(); + return MemoryRecord.fromJsonMetadata( + entry.getMetadata(), embedding, entry.getKey(), entry.getTimestamp()); + } catch (JsonProcessingException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "Error deserializing database entry", + e); + } + } + + private Mono internalUpsertAsync(String collectionName, MemoryRecord record) { + try { + return this.dbConnector.upsertAsync( + collectionName, + record.getMetadata().getId(), + record.getSerializedMetadata(), + record.getSerializedEmbedding(), + record.getTimestamp()); + } catch (JsonProcessingException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "Error serializing MemoryRecord", + e); + } + } + + @Override + public Mono> upsertBatchAsync( + @Nonnull String collectionName, @Nonnull Collection records) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(records); + return doesCollectionExistAsync(collectionName) + .handle( + (exists, sink) -> { + if (!exists) { + sink.error( + new MemoryException( + ErrorCodes + .ATTEMPTED_TO_ACCESS_NONEXISTENT_COLLECTION, + collectionName)); + return; + } + sink.next(exists); + }) + .then( + dbConnector.upsertBatchAsync( + collectionName, + records.stream() + .map(this::memoryRecordToDatabaseEntry) + .collect(Collectors.toList()))); + } + + @Override + public Mono getAsync( + @Nonnull String collectionName, @Nonnull String key, boolean withEmbedding) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(key); + return this.internalGetAsync(collectionName, key, withEmbedding); + } + + private Mono internalGetAsync( + String collectionName, String key, boolean withEmbedding) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(key); + Mono entry = this.dbConnector.readAsync(collectionName, key); + + return entry.hasElement() + .flatMap( + hasElement -> { + if (!hasElement) { + return Mono.empty(); + } + + return entry.map( + databaseEntry -> + databaseEntryToMemoryRecord( + databaseEntry, withEmbedding)); + }); + } + + @Override + public Mono> getBatchAsync( + @Nonnull String collectionName, + @Nonnull Collection keys, + boolean withEmbeddings) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(keys); + return this.dbConnector + .readBatchAsync(collectionName, keys) + .flatMap( + databaseEntries -> { + List records = new ArrayList<>(); + for (DatabaseEntry entry : databaseEntries) { + records.add(databaseEntryToMemoryRecord(entry, withEmbeddings)); + } + return Mono.just(records); + }); + } + + @Override + public Mono removeAsync(@Nonnull String collectionName, @Nonnull String key) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(key); + return this.dbConnector.deleteAsync(collectionName, key); + } + + @Override + public Mono removeBatchAsync( + @Nonnull String collectionName, @Nonnull Collection keys) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(keys); + return this.dbConnector.deleteBatchAsync(collectionName, keys); + } + + @Override + public Mono>> getNearestMatchesAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + int limit, + float minRelevanceScore, + boolean withEmbeddings) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(embedding); + Mono> entries = this.dbConnector.readAllAsync(collectionName); + + return entries.flatMap( + databaseEntries -> { + List> nearestMatches = new ArrayList<>(); + for (DatabaseEntry entry : databaseEntries) { + if (entry.getEmbedding() == null || entry.getEmbedding().isEmpty()) { + continue; + } + try { + Embedding recordEmbedding = + new ObjectMapper() + .readValue(entry.getEmbedding(), Embedding.class); + float similarity = embedding.cosineSimilarity(recordEmbedding); + if (similarity >= (float) minRelevanceScore) { + MemoryRecord record = + MemoryRecord.fromJsonMetadata( + entry.getMetadata(), + withEmbeddings ? recordEmbedding : null, + entry.getKey(), + entry.getTimestamp()); + nearestMatches.add(Tuples.of(record, similarity)); + } + } catch (JsonProcessingException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "Error deserializing database entry", + e); + } + } + List> results = + nearestMatches.stream() + .sorted( + Comparator.comparing( + Tuple2::getT2, (a, b) -> Float.compare(b, a))) + .limit(limit) + .collect(Collectors.toList()); + + return Mono.just(results); + }); + } + + @Override + public Mono> getNearestMatchAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + float minRelevanceScore, + boolean withEmbedding) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(embedding); + return getNearestMatchesAsync( + collectionName, embedding, 1, minRelevanceScore, withEmbedding) + .flatMap( + nearestMatches -> { + if (nearestMatches.isEmpty()) { + return Mono.empty(); + } + return Mono.just(nearestMatches.iterator().next()); + }); + } + + /** Builds a JDBCMemoryStore. */ + public static class Builder implements SQLMemoryStore.Builder { + private Connection connection; + + /** + * Builds and returns a JDBCMemoryStore instance with the specified database connection. The + * build process will connect to the database and create the required tables. + * + * @return A JDBCMemoryStore instance configured with the provided database connection. + * @deprecated Use {@link #buildAsync()} instead. + */ + @Override + @Deprecated + public JDBCMemoryStore build() { + return this.buildAsync().block(); + } + + /** + * Asynchronously builds and returns a JDBCMemoryStore instance with the specified database + * connection. + * + * @return A Mono with a JDBCMemoryStore instance configured with the provided database + * connection. + */ + @Override + @CheckReturnValue + public Mono buildAsync() { + JDBCConnector connector = new JDBCConnector(connection); + JDBCMemoryStore memoryStore = new JDBCMemoryStore(connector); + return connector.createTableAsync().thenReturn(memoryStore); + } + + /** + * Sets the database connection to be used by the memory store being built. + * + * @param connection The Connection object representing the database connection. + * @return The updated Builder instance to continue the building process for a + * JDBCMemoryStore. + */ + @Override + public Builder withConnection(Connection connection) { + this.connection = connection; + return this; + } + } +} diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLConnector.java b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLConnector.java new file mode 100644 index 0000000000..453ed1fad1 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLConnector.java @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.jdbc; + +import java.time.ZonedDateTime; +import java.util.Collection; +import java.util.List; +import reactor.core.publisher.Mono; + +public interface SQLConnector { + + /** + * Asynchronously creates a table in the database. + * + * @return A Mono representing the completion of the table creation operation. + */ + Mono createTableAsync(); + + /** + * Asynchronously creates a collection within the database. + * + * @param collectionName The name of the collection to be created. + * @return A Mono representing the completion of the collection creation operation. + */ + Mono createCollectionAsync(String collectionName); + + /** + * Asynchronously inserts or updates an entry. + * + * @param collection The name of the collection to insert the entry into. + * @param key The key identifying the entry. + * @param metadata The metadata associated with the entry. + * @param embedding The embedding data associated with the entry. + * @param timestamp The timestamp of the insertion. + * @return A Mono representing the completion of the insertion operation. + */ + Mono upsertAsync( + String collection, + String key, + String metadata, + String embedding, + ZonedDateTime timestamp); + + /** + * Asynchronously inserts or updates a batch of entries. + * + * @param records + * @return A Mono emitting a list of keys identifying the entries. + */ + Mono> upsertBatchAsync(String collection, Collection records); + + /** + * Asynchronously checks if a collection exists. + * + * @param collectionName The name of the collection to check. + * @return A Mono emitting a boolean value indicating whether the collection exists. + */ + Mono doesCollectionExistsAsync(String collectionName); + + /** + * Asynchronously retrieves a list of collection names. + * + * @return A Mono emitting a list of collection names. + */ + Mono> getCollectionsAsync(); + + /** + * Asynchronously reads all entries within a collection. + * + * @param collectionName The name of the collection to read from. + * @return A Mono emitting a list of DatabaseEntry objects representing the entries. + */ + Mono> readAllAsync(String collectionName); + + /** + * Asynchronously reads a specific entry within a collection. + * + * @param collectionName The name of the collection to read from. + * @param key The key identifying the entry to read. + * @return A Mono emitting a DatabaseEntry object representing the entry. + */ + Mono readAsync(String collectionName, String key); + + /** + * Asynchronously reads a batch of entries within a collection. + * + * @param collectionName The name of the collection to read from. + * @param keys The keys identifying the entries to read. + * @return A Mono emitting a list of DatabaseEntry objects representing the entries. + */ + Mono> readBatchAsync(String collectionName, Collection keys); + + /** + * Asynchronously deletes a collection. + * + * @param collectionName The name of the collection to delete. + * @return A Mono representing the completion of the collection deletion operation. + */ + Mono deleteCollectionAsync(String collectionName); + + /** + * Asynchronously deletes an entry within a collection. + * + * @param collectionName The name of the collection to delete the entry from. + * @param key The key identifying the entry to delete. + * @return A Mono representing the completion of the entry deletion operation. + */ + Mono deleteAsync(String collectionName, String key); + + /** + * Asynchronously deletes a batch of entries within a collection. + * + * @param collectionName The name of the collection to delete the entries from. + * @param keys The keys identifying the entries to delete. + * @return A Mono representing the completion of the entry deletion operation. + */ + Mono deleteBatchAsync(String collectionName, Collection keys); + + /** + * Asynchronously deletes all empty entries within a collection. + * + * @param collectionName The name of the collection to delete empty entries from. + * @return A Mono representing the completion of the empty entry deletion operation. + */ + Mono deleteEmptyAsync(String collectionName); +} diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLConnectorException.java b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLConnectorException.java new file mode 100644 index 0000000000..45574e1756 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLConnectorException.java @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.jdbc; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Exception thrown by the SQL connector. */ +public class SQLConnectorException extends SKException { + + private final ErrorCodes errorCode; + + /** + * Create an exception with a message + * + * @param errorCode The error code + */ + public SQLConnectorException(@Nonnull ErrorCodes errorCode) { + this(errorCode, null, null); + } + + /** + * Create an exception with a message + * + * @param message a description of the cause of the exception + */ + public SQLConnectorException(@Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + /** + * Create an exception with a message and a cause + * + * @param errorCode the error code + * @param message a description of the cause of the exception + * @param cause the cause of the exception + */ + public SQLConnectorException( + @Nonnull ErrorCodes errorCode, @Nullable String message, @Nullable Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + + public ErrorCodes getErrorCode() { + return errorCode; + } + + public enum ErrorCodes { + SQL_ERROR("SQL error"); + + final String message; + + ErrorCodes(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } +} diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLMemoryStore.java b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLMemoryStore.java new file mode 100644 index 0000000000..ab14f849cb --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/src/main/java/com/microsoft/semantickernel/connectors/memory/jdbc/SQLMemoryStore.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.jdbc; + +import com.microsoft.semantickernel.memory.MemoryStore; +import java.sql.Connection; +import reactor.core.publisher.Mono; + +public interface SQLMemoryStore extends MemoryStore { + interface Builder extends MemoryStore.Builder { + /** + * Asynchronously builds the SQLMemoryStore. + * + * @return A Mono with the SQLMemoryStore. + */ + Mono buildAsync(); + + /** + * Sets the database connection to be used by the SQL memory store. + * + * @param connection The Connection object representing the database connection. + * @return The updated SQLMemoryStoreBuilder instance. + */ + Builder withConnection(Connection connection); + } +} diff --git a/java/connectors/semantickernel-connectors-memory-jdbc/src/test/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCConnectorTest.java b/java/connectors/semantickernel-connectors-memory-jdbc/src/test/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCConnectorTest.java new file mode 100644 index 0000000000..f1a20dce7a --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-jdbc/src/test/java/com/microsoft/semantickernel/connectors/memory/jdbc/JDBCConnectorTest.java @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.jdbc; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collection; +import org.junit.jupiter.api.Test; + +public class JDBCConnectorTest { + @Test + void testBatchQuery() { + Collection keys = new ArrayList<>(); + keys.add("key1"); + keys.add("key2"); + keys.add("key3"); + + JDBCConnector connector = new JDBCConnector(null); + String read = connector.batchQuery(JDBCConnector.BatchOperation.SELECT, keys); + String delete = connector.batchQuery(JDBCConnector.BatchOperation.DELETE, keys); + + assertNotNull(read); + assertNotNull(delete); + assertEquals( + "SELECT * FROM " + + JDBCConnector.TABLE_NAME + + " WHERE collection = ? AND key IN (?,?,?)", + read); + assertEquals( + "DELETE FROM " + + JDBCConnector.TABLE_NAME + + " WHERE collection = ? AND key IN (?,?,?)", + delete); + } +} diff --git a/java/connectors/semantickernel-connectors-memory-mysql/pom.xml b/java/connectors/semantickernel-connectors-memory-mysql/pom.xml new file mode 100644 index 0000000000..5e77701e59 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-mysql/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-connectors-memory-mysql + Semantic Kernel MySQL Memory Connector + + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-jdbc + + + io.projectreactor + reactor-core + + + org.junit.jupiter + junit-jupiter-api + + + + com.mysql + mysql-connector-j + 8.0.33 + + + \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-memory-mysql/src/main/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLConnector.java b/java/connectors/semantickernel-connectors-memory-mysql/src/main/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLConnector.java new file mode 100644 index 0000000000..c382ee7ac4 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-mysql/src/main/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLConnector.java @@ -0,0 +1,370 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.mysql; + +import com.microsoft.semantickernel.connectors.memory.jdbc.DatabaseEntry; +import com.microsoft.semantickernel.connectors.memory.jdbc.JDBCConnector; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLConnector; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLConnectorException; +import java.sql.*; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +public class MySQLConnector extends JDBCConnector implements SQLConnector { + public MySQLConnector(Connection connection) { + super(connection); + } + + @Override + public Mono createTableAsync() { + return Mono.fromRunnable( + () -> { + try (Statement statement = connection.createStatement()) { + String createCollectionKeyTable = + "CREATE TABLE IF NOT EXISTS " + + COLLECTIONS_TABLE_NAME + + " (id VARCHAR(255) PRIMARY KEY);"; + + String createSKMemoryTable = + "CREATE TABLE IF NOT EXISTS " + + TABLE_NAME + + " (" + + "collection VARCHAR(255) NOT NULL, " + + "id VARCHAR(255) NOT NULL, " + + "metadata TEXT, " + + "embedding TEXT, " + + "timestamp TEXT, " + + "PRIMARY KEY (collection, id), " + + "FOREIGN KEY (collection) REFERENCES " + + COLLECTIONS_TABLE_NAME + + "(id));"; + + statement.addBatch(createCollectionKeyTable); + statement.addBatch(createSKMemoryTable); + + boolean indexExists = doesIndexExist(); + + if (!indexExists) { + String createIndex = + "CREATE INDEX " + + INDEX_NAME + + " ON " + + TABLE_NAME + + "(collection)"; + statement.addBatch(createIndex); + } + + statement.executeBatch(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"CREATE TABLE\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + private boolean doesIndexExist() throws SQLException { + DatabaseMetaData meta = connection.getMetaData(); + try (ResultSet indexes = meta.getIndexInfo(null, null, TABLE_NAME, false, false)) { + while (indexes.next()) { + String existingIndexName = indexes.getString("INDEX_NAME"); + if (existingIndexName != null && existingIndexName.equalsIgnoreCase(INDEX_NAME)) { + return true; + } + } + } + return false; + } + + @Override + public Mono createCollectionAsync(String collectionName) { + return Mono.fromRunnable( + () -> { + String query = + "INSERT INTO " + COLLECTIONS_TABLE_NAME + " (id) VALUES (?)"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"INSERT INTO\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + @Override + public Mono upsertAsync( + String collection, + String key, + String metadata, + String embedding, + ZonedDateTime timestamp) { + return Mono.fromRunnable( + () -> { + String query = + "INSERT INTO " + + TABLE_NAME + + " (collection, id, metadata, embedding, timestamp)" + + " VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE" + + " metadata = VALUES(metadata), embedding =" + + " VALUES(embedding), timestamp = VALUES(timestamp)"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + String metadataString = metadata != null ? metadata : ""; + String embeddingString = embedding != null ? embedding : ""; + String timestampString = formatDatetime(timestamp); + statement.setString(1, collection); + statement.setString(2, key); + statement.setString(3, metadataString); + statement.setString(4, embeddingString); + statement.setString(5, timestampString); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"INSERT INTO\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .thenReturn(key); + } + + @Override + public Mono> upsertBatchAsync( + String collection, Collection records) { + Collection keys = new ArrayList<>(); + return Mono.fromRunnable( + () -> { + String query = + "INSERT INTO " + + TABLE_NAME + + " (collection, id, metadata, embedding, timestamp)" + + " VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE" + + " metadata = VALUES(metadata), embedding =" + + " VALUES(embedding), timestamp = VALUES(timestamp)"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + for (DatabaseEntry entry : records) { + String metadataString = + entry.getMetadata() != null ? entry.getMetadata() : ""; + String embeddingString = + entry.getEmbedding() != null + ? entry.getEmbedding() + : ""; + String timestampString = formatDatetime(entry.getTimestamp()); + statement.setString(1, collection); + statement.setString(2, entry.getKey()); + statement.setString(3, metadataString); + statement.setString(4, embeddingString); + statement.setString(5, timestampString); + statement.addBatch(); + keys.add(entry.getKey()); + } + + statement.executeBatch(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"INSERT INTO\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .thenReturn(keys); + } + + @Override + public Mono> readAllAsync(String collectionName) { + return Mono.defer( + () -> { + List entries = new ArrayList<>(); + String query = "SELECT * FROM " + TABLE_NAME + " WHERE collection = ?"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + String key = resultSet.getString("id"); + String metadata = resultSet.getString("metadata"); + String embedding = resultSet.getString("embedding"); + String timestamp = resultSet.getString("timestamp"); + ZonedDateTime zonedDateTime = parseDatetime(timestamp); + entries.add( + new DatabaseEntry( + key, metadata, embedding, zonedDateTime)); + } + } catch (SQLException e) { + return Mono.error( + new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"SELECT * FROM\" failed", + e)); + } + return Mono.just(entries); + }) + .subscribeOn(Schedulers.boundedElastic()); + } + + @Override + public Mono readAsync(String collectionName, String key) { + return Mono.defer( + () -> { + String query = + "SELECT * FROM " + + TABLE_NAME + + " WHERE collection = ?" + + " AND id = ?"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + statement.setString(2, key != null && !key.isEmpty() ? key : null); + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + String metadata = resultSet.getString("metadata"); + String embedding = resultSet.getString("embedding"); + String timestamp = resultSet.getString("timestamp"); + ZonedDateTime zonedDateTime = parseDatetime(timestamp); + return Mono.just( + new DatabaseEntry( + key, metadata, embedding, zonedDateTime)); + } + } catch (SQLException e) { + return Mono.error( + new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"SELECT * FROM\" failed", + e)); + } + return Mono.empty(); + }) + .subscribeOn(Schedulers.boundedElastic()); + } + + @Override + protected String batchQuery(JDBCConnector.BatchOperation operation, Collection keys) { + String queryPrefix; + switch (operation) { + case SELECT: + queryPrefix = "SELECT * FROM " + TABLE_NAME + " WHERE collection = ?"; + break; + case DELETE: + queryPrefix = "DELETE FROM " + TABLE_NAME + " WHERE collection = ?"; + break; + default: + throw new IllegalArgumentException("Invalid batch operation"); + } + StringBuilder queryBuilder = new StringBuilder(queryPrefix); + queryBuilder.append(" AND id IN ("); + + // Add placeholders for each key + for (int i = 0; i < keys.size(); i++) { + queryBuilder.append("?"); + if (i < keys.size() - 1) { + queryBuilder.append(","); + } + } + + queryBuilder.append(")"); + return queryBuilder.toString(); + } + + @Override + public Mono> readBatchAsync( + String collectionName, Collection keys) { + return Mono.defer( + () -> { + Collection entries = new ArrayList<>(); + String query = batchQuery(JDBCConnector.BatchOperation.SELECT, keys); + + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + int index = 2; + for (String key : keys) { + statement.setString(index++, key); + } + ResultSet resultSet = statement.executeQuery(); + + while (resultSet.next()) { + String key = resultSet.getString("id"); + String metadata = resultSet.getString("metadata"); + String embedding = resultSet.getString("embedding"); + String timestamp = resultSet.getString("timestamp"); + ZonedDateTime zonedDateTime = parseDatetime(timestamp); + entries.add( + new DatabaseEntry( + key, metadata, embedding, zonedDateTime)); + } + } catch (SQLException e) { + return Mono.error( + new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"SELECT * FROM\" failed", + e)); + } + return Mono.just(entries); + }) + .subscribeOn(Schedulers.boundedElastic()); + } + + @Override + public Mono deleteAsync(String collectionName, String key) { + return Mono.fromRunnable( + () -> { + String query = + "DELETE FROM " + + TABLE_NAME + + " WHERE collection = ?" + + " AND id = ?"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + statement.setString(2, key != null && !key.isEmpty() ? key : null); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"DELETE FROM\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + @Override + public Mono deleteEmptyAsync(String collectionName) { + return Mono.fromRunnable( + () -> { + String query = + "DELETE FROM " + + TABLE_NAME + + " WHERE collection = ?" + + " AND id is NULL"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + statement.setString(1, collectionName); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"DELETE FROM\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } +} diff --git a/java/connectors/semantickernel-connectors-memory-mysql/src/main/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLMemoryStore.java b/java/connectors/semantickernel-connectors-memory-mysql/src/main/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLMemoryStore.java new file mode 100644 index 0000000000..85b1e47440 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-mysql/src/main/java/com/microsoft/semantickernel/connectors/memory/mysql/MySQLMemoryStore.java @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.mysql; + +import com.microsoft.semantickernel.connectors.memory.jdbc.JDBCMemoryStore; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLConnector; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLMemoryStore; +import java.sql.Connection; +import javax.annotation.CheckReturnValue; +import reactor.core.publisher.Mono; + +public class MySQLMemoryStore extends JDBCMemoryStore { + private MySQLMemoryStore(SQLConnector connector) { + super(connector); + } + + /** Builds a MySQLMemoryStore. */ + public static class Builder implements SQLMemoryStore.Builder { + private Connection connection; + + /** + * Builds and returns a MySQLMemoryStore instance with the specified database connection. + * The build process will connect to the database and create the required tables. + * + * @return A MySQLMemoryStore instance configured with the provided database connection. + * @deprecated Use {@link #buildAsync()} instead. + */ + @Override + @Deprecated + public MySQLMemoryStore build() { + return this.buildAsync().block(); + } + + /** + * Asynchronously builds and returns a MySQLMemoryStore instance with the specified database + * connection. + * + * @return A Mono with a MySQLMemoryStore instance configured with the provided database + * connection. + */ + @Override + @CheckReturnValue + public Mono buildAsync() { + MySQLConnector connector = new MySQLConnector(connection); + MySQLMemoryStore memoryStore = new MySQLMemoryStore(connector); + return connector.createTableAsync().thenReturn(memoryStore); + } + + /** + * Sets the MySQL database connection to be used by the MySQL memory store being built. + * + * @param connection The Connection object representing the MySQL database connection. + * @return The updated Builder instance to continue the building process for a + * MySQLMemoryStore. + */ + @Override + public Builder withConnection(Connection connection) { + this.connection = connection; + return this; + } + } +} diff --git a/java/connectors/semantickernel-connectors-memory-postgresql/pom.xml b/java/connectors/semantickernel-connectors-memory-postgresql/pom.xml new file mode 100644 index 0000000000..972627035f --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-postgresql/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-connectors-memory-postgresql + Semantic Kernel PostgreSQL Memory Connector + + + + com.fasterxml.jackson.core + jackson-core + compile + + + com.fasterxml.jackson.core + jackson-databind + compile + + + com.microsoft.semantic-kernel + semantickernel-api + + + org.mockito + mockito-core + + + org.junit.jupiter + junit-jupiter + + + + org.postgresql + postgresql + + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-jdbc + ${project.version} + compile + + + \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-memory-postgresql/semantickernel-connectors-memory-postgresql.iml b/java/connectors/semantickernel-connectors-memory-postgresql/semantickernel-connectors-memory-postgresql.iml new file mode 100644 index 0000000000..224fc7d9a8 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-postgresql/semantickernel-connectors-memory-postgresql.iml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-memory-postgresql/src/main/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLConnector.java b/java/connectors/semantickernel-connectors-memory-postgresql/src/main/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLConnector.java new file mode 100644 index 0000000000..1db010bb6d --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-postgresql/src/main/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLConnector.java @@ -0,0 +1,155 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.postgresql; + +import com.microsoft.semantickernel.connectors.memory.jdbc.DatabaseEntry; +import com.microsoft.semantickernel.connectors.memory.jdbc.JDBCConnector; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLConnector; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLConnectorException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Collection; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +public class PostgreSQLConnector extends JDBCConnector implements SQLConnector { + public PostgreSQLConnector(Connection connection) { + super(connection); + } + + @Override + public Mono createTableAsync() { + return Mono.fromRunnable( + () -> { + String createCollectionKeyTable = + "CREATE TABLE IF NOT EXISTS " + + COLLECTIONS_TABLE_NAME + + " (" + + "id TEXT PRIMARY KEY" + + " )"; + + String createSKMemoryTable = + "CREATE TABLE IF NOT EXISTS " + + TABLE_NAME + + " (" + + "collection TEXT NOT NULL, " + + "key TEXT NOT NULL, " + + "metadata TEXT, " + + "embedding TEXT, " + + "timestamp TEXT, " + + "PRIMARY KEY (collection, key), " + + "FOREIGN KEY (collection) REFERENCES " + + COLLECTIONS_TABLE_NAME + + "(id)" + + " )"; + + String createIndex = + "CREATE INDEX IF NOT EXISTS " + + INDEX_NAME + + " ON " + + TABLE_NAME + + "(collection)"; + + try (Statement statement = this.connection.createStatement()) { + statement.addBatch(createCollectionKeyTable); + statement.addBatch(createSKMemoryTable); + statement.addBatch(createIndex); + statement.executeBatch(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"CREATE TABLE\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .then(); + } + + @Override + public Mono upsertAsync( + String collection, + String key, + String metadata, + String embedding, + ZonedDateTime timestamp) { + return Mono.fromRunnable( + () -> { + String query = + "INSERT INTO " + + TABLE_NAME + + " (collection, key, metadata, embedding, timestamp)" + + " VALUES (?, ?, ?, ?, ?) ON CONFLICT (collection," + + " key) DO UPDATE SET metadata = EXCLUDED.metadata," + + " embedding = EXCLUDED.embedding, timestamp =" + + " EXCLUDED.timestamp"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + String metadataString = metadata != null ? metadata : ""; + String embeddingString = embedding != null ? embedding : ""; + String timestampString = formatDatetime(timestamp); + statement.setString(1, collection); + statement.setString(2, key); + statement.setString(3, metadataString); + statement.setString(4, embeddingString); + statement.setString(5, timestampString); + statement.executeUpdate(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"INSERT INTO\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .thenReturn(key); + } + + @Override + public Mono> upsertBatchAsync( + String collection, Collection records) { + Collection keys = new ArrayList<>(); + return Mono.fromRunnable( + () -> { + String query = + "INSERT INTO " + + TABLE_NAME + + " (collection, key, metadata, embedding, timestamp)" + + " VALUES (?, ?, ?, ?, ?) ON CONFLICT (collection," + + " key) DO UPDATE SET metadata = EXCLUDED.metadata," + + " embedding = EXCLUDED.embedding, timestamp =" + + " EXCLUDED.timestamp"; + try (PreparedStatement statement = + this.connection.prepareStatement(query)) { + for (DatabaseEntry entry : records) { + String metadataString = + entry.getMetadata() != null ? entry.getMetadata() : ""; + String embeddingString = + entry.getEmbedding() != null + ? entry.getEmbedding() + : ""; + String timestampString = formatDatetime(entry.getTimestamp()); + statement.setString(1, collection); + statement.setString(2, entry.getKey()); + statement.setString(3, metadataString); + statement.setString(4, embeddingString); + statement.setString(5, timestampString); + statement.addBatch(); + keys.add(entry.getKey()); + } + + statement.executeBatch(); + } catch (SQLException e) { + throw new SQLConnectorException( + SQLConnectorException.ErrorCodes.SQL_ERROR, + "\"INSERT INTO\" failed", + e); + } + }) + .subscribeOn(Schedulers.boundedElastic()) + .thenReturn(keys); + } +} diff --git a/java/connectors/semantickernel-connectors-memory-postgresql/src/main/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLMemoryStore.java b/java/connectors/semantickernel-connectors-memory-postgresql/src/main/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLMemoryStore.java new file mode 100644 index 0000000000..081763be82 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-postgresql/src/main/java/com/microsoft/semantickernel/connectors/memory/postgresql/PostgreSQLMemoryStore.java @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.postgresql; + +import com.microsoft.semantickernel.connectors.memory.jdbc.JDBCMemoryStore; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLConnector; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLMemoryStore; +import java.sql.Connection; +import javax.annotation.CheckReturnValue; +import reactor.core.publisher.Mono; + +public class PostgreSQLMemoryStore extends JDBCMemoryStore { + private PostgreSQLMemoryStore(SQLConnector connector) { + super(connector); + } + + /** Builds a PostgreSQLMemoryStore. */ + public static class Builder implements SQLMemoryStore.Builder { + private Connection connection; + + /** + * Builds and returns a PostgreSQLMemoryStore instance with the specified database + * connection. The build process will connect to the database and create the required + * tables. + * + * @return A PostgreSQLMemoryStore instance configured with the provided database + * connection. + * @deprecated Use {@link #buildAsync()} instead. + */ + @Override + @Deprecated + public PostgreSQLMemoryStore build() { + return this.buildAsync().block(); + } + + /** + * Asynchronously builds and returns a PostgreSQLMemoryStore instance with the specified + * database connection. + * + * @return A Mono with a PostgreSQLMemoryStore instance configured with the provided + * database connection. + */ + @Override + @CheckReturnValue + public Mono buildAsync() { + PostgreSQLConnector connector = new PostgreSQLConnector(connection); + PostgreSQLMemoryStore memoryStore = new PostgreSQLMemoryStore(connector); + return connector.createTableAsync().thenReturn(memoryStore); + } + + /** + * Sets the PostgreSQL database connection to be used by the PostgreSQL memory store being + * built. + * + * @param connection The Connection object representing the PostgreSQL database connection. + * @return The updated Builder instance to continue the building process for a + * PostgreSQLMemoryStore. + */ + @Override + public Builder withConnection(Connection connection) { + this.connection = connection; + return this; + } + } +} diff --git a/java/connectors/semantickernel-connectors-memory-sqlite/pom.xml b/java/connectors/semantickernel-connectors-memory-sqlite/pom.xml new file mode 100644 index 0000000000..4d07d7355c --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-sqlite/pom.xml @@ -0,0 +1,56 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-connectors-memory-sqlite + + Semantic Kernel SQLite Memory Connector + Defines connector for SQLite to be used with the Semantic Kernel + + + + com.fasterxml.jackson.core + jackson-core + compile + + + com.fasterxml.jackson.core + jackson-databind + compile + + + com.microsoft.semantic-kernel + semantickernel-api + + + org.mockito + mockito-core + + + org.junit.jupiter + junit-jupiter + + + + org.xerial + sqlite-jdbc + + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-jdbc + ${project.version} + compile + + + + + \ No newline at end of file diff --git a/java/connectors/semantickernel-connectors-memory-sqlite/src/main/java/com/microsoft/semantickernel/connectors/memory/sqlite/SQLiteMemoryStore.java b/java/connectors/semantickernel-connectors-memory-sqlite/src/main/java/com/microsoft/semantickernel/connectors/memory/sqlite/SQLiteMemoryStore.java new file mode 100644 index 0000000000..e7ed0154c9 --- /dev/null +++ b/java/connectors/semantickernel-connectors-memory-sqlite/src/main/java/com/microsoft/semantickernel/connectors/memory/sqlite/SQLiteMemoryStore.java @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.memory.sqlite; + +import com.microsoft.semantickernel.connectors.memory.jdbc.JDBCConnector; +import com.microsoft.semantickernel.connectors.memory.jdbc.JDBCMemoryStore; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLConnector; +import com.microsoft.semantickernel.connectors.memory.jdbc.SQLMemoryStore; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import javax.annotation.CheckReturnValue; +import reactor.core.publisher.Mono; + +public class SQLiteMemoryStore extends JDBCMemoryStore { + private SQLiteMemoryStore(SQLConnector connector) { + super(connector); + } + + /** Builds a SQLiteMemoryStore. */ + public static class Builder implements SQLMemoryStore.Builder { + private Connection connection; + + /** + * Builds and returns an SQLiteMemoryStore instance with the specified database connection. + * The build process will connect to the database and create the required tables. + * + * @return An SQLiteMemoryStore instance configured with the provided database connection. + * @deprecated Use {@link #buildAsync()} instead. + */ + @Override + @Deprecated + public SQLiteMemoryStore build() { + return this.buildAsync().block(); + } + + /** + * Asynchronously builds and returns an SQLiteMemoryStore instance with the specified + * database connection. + * + * @return A Mono with an SQLiteMemoryStore instance configured with the provided SQLite + * database connection. + */ + @Override + @CheckReturnValue + public Mono buildAsync() { + JDBCConnector connector = new JDBCConnector(connection); + SQLiteMemoryStore memoryStore = new SQLiteMemoryStore(connector); + return connector.createTableAsync().thenReturn(memoryStore); + } + + /** + * Sets the SQLite database connection to be used by the SQLite memory store being built. + * + * @param connection The Connection object representing the SQLite database connection. + * @return The updated Builder instance to continue the building process for an + * SQLiteMemoryStore. + */ + @Override + public Builder withConnection(Connection connection) { + this.connection = connection; + return this; + } + + /** + * Creates and sets an SQLite database connection using the specified filename. This will + * overwrite any previously set connection. + * + * @param filename The filename of the SQLite database. + * @return The updated Builder instance with the SQLite database connection set. + * @throws SQLException If there is an issue with establishing the database connection. + */ + public Builder withFilename(String filename) throws SQLException { + return withConnection(DriverManager.getConnection("jdbc:sqlite:" + filename)); + } + } +} diff --git a/java/extensions/semantickernel-gpt3-tokenizer/pom.xml b/java/extensions/semantickernel-gpt3-tokenizer/pom.xml new file mode 100644 index 0000000000..4a8cbad977 --- /dev/null +++ b/java/extensions/semantickernel-gpt3-tokenizer/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + Semantic Kernel GPT3 Tokenizer Extension + GPT3 Tokenizer for Semantic Kernel + semantickernel-gpt3-tokenizer + + + + io.projectreactor + reactor-core + + + com.fasterxml.jackson.core + jackson-core + compile + + + com.fasterxml.jackson.core + jackson-databind + compile + + + com.microsoft.semantic-kernel + semantickernel-api + + + org.junit.jupiter + junit-jupiter + test + + + + \ No newline at end of file diff --git a/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/GPT3Tokenizer.java b/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/GPT3Tokenizer.java new file mode 100644 index 0000000000..7f0ff58047 --- /dev/null +++ b/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/GPT3Tokenizer.java @@ -0,0 +1,302 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.microsoft.semantickernel.settings.GPT3Settings; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import reactor.util.function.Tuple2; +import reactor.util.function.Tuples; + +public class GPT3Tokenizer { + /** + * Port of GPT3 Javascript tokenizer recommended by OpenAI. See GPT3 tokernizer and What + * are tokens and how to count them + */ + private static final char[] bytesToUnicode = + new char[] { + (char) 0x0100, (char) 0x0101, (char) 0x0102, (char) 0x0103, (char) 0x0104, + (char) 0x0105, (char) 0x0106, (char) 0x0107, + (char) 0x0108, (char) 0x0109, (char) 0x010A, (char) 0x010B, (char) 0x010C, + (char) 0x010D, (char) 0x010E, (char) 0x010F, + (char) 0x0110, (char) 0x0111, (char) 0x0112, (char) 0x0113, (char) 0x0114, + (char) 0x0115, (char) 0x0116, (char) 0x0117, + (char) 0x0118, (char) 0x0119, (char) 0x011A, (char) 0x011B, (char) 0x011C, + (char) 0x011D, (char) 0x011E, (char) 0x011F, + (char) 0x0120, (char) 0x0021, (char) 0x0022, (char) 0x0023, (char) 0x0024, + (char) 0x0025, (char) 0x0026, (char) 0x0027, + (char) 0x0028, (char) 0x0029, (char) 0x002A, (char) 0x002B, (char) 0x002C, + (char) 0x002D, (char) 0x002E, (char) 0x002F, + (char) 0x0030, (char) 0x0031, (char) 0x0032, (char) 0x0033, (char) 0x0034, + (char) 0x0035, (char) 0x0036, (char) 0x0037, + (char) 0x0038, (char) 0x0039, (char) 0x003A, (char) 0x003B, (char) 0x003C, + (char) 0x003D, (char) 0x003E, (char) 0x003F, + (char) 0x0040, (char) 0x0041, (char) 0x0042, (char) 0x0043, (char) 0x0044, + (char) 0x0045, (char) 0x0046, (char) 0x0047, + (char) 0x0048, (char) 0x0049, (char) 0x004A, (char) 0x004B, (char) 0x004C, + (char) 0x004D, (char) 0x004E, (char) 0x004F, + (char) 0x0050, (char) 0x0051, (char) 0x0052, (char) 0x0053, (char) 0x0054, + (char) 0x0055, (char) 0x0056, (char) 0x0057, + (char) 0x0058, (char) 0x0059, (char) 0x005A, (char) 0x005B, (char) 0x005C, + (char) 0x005D, (char) 0x005E, (char) 0x005F, + (char) 0x0060, (char) 0x0061, (char) 0x0062, (char) 0x0063, (char) 0x0064, + (char) 0x0065, (char) 0x0066, (char) 0x0067, + (char) 0x0068, (char) 0x0069, (char) 0x006A, (char) 0x006B, (char) 0x006C, + (char) 0x006D, (char) 0x006E, (char) 0x006F, + (char) 0x0070, (char) 0x0071, (char) 0x0072, (char) 0x0073, (char) 0x0074, + (char) 0x0075, (char) 0x0076, (char) 0x0077, + (char) 0x0078, (char) 0x0079, (char) 0x007A, (char) 0x007B, (char) 0x007C, + (char) 0x007D, (char) 0x007E, (char) 0x0121, + (char) 0x0122, (char) 0x0123, (char) 0x0124, (char) 0x0125, (char) 0x0126, + (char) 0x0127, (char) 0x0128, (char) 0x0129, + (char) 0x012A, (char) 0x012B, (char) 0x012C, (char) 0x012D, (char) 0x012E, + (char) 0x012F, (char) 0x0130, (char) 0x0131, + (char) 0x0132, (char) 0x0133, (char) 0x0134, (char) 0x0135, (char) 0x0136, + (char) 0x0137, (char) 0x0138, (char) 0x0139, + (char) 0x013A, (char) 0x013B, (char) 0x013C, (char) 0x013D, (char) 0x013E, + (char) 0x013F, (char) 0x0140, (char) 0x0141, + (char) 0x0142, (char) 0x00A1, (char) 0x00A2, (char) 0x00A3, (char) 0x00A4, + (char) 0x00A5, (char) 0x00A6, (char) 0x00A7, + (char) 0x00A8, (char) 0x00A9, (char) 0x00AA, (char) 0x00AB, (char) 0x00AC, + (char) 0x0143, (char) 0x00AE, (char) 0x00AF, + (char) 0x00B0, (char) 0x00B1, (char) 0x00B2, (char) 0x00B3, (char) 0x00B4, + (char) 0x00B5, (char) 0x00B6, (char) 0x00B7, + (char) 0x00B8, (char) 0x00B9, (char) 0x00BA, (char) 0x00BB, (char) 0x00BC, + (char) 0x00BD, (char) 0x00BE, (char) 0x00BF, + (char) 0x00C0, (char) 0x00C1, (char) 0x00C2, (char) 0x00C3, (char) 0x00C4, + (char) 0x00C5, (char) 0x00C6, (char) 0x00C7, + (char) 0x00C8, (char) 0x00C9, (char) 0x00CA, (char) 0x00CB, (char) 0x00CC, + (char) 0x00CD, (char) 0x00CE, (char) 0x00CF, + (char) 0x00D0, (char) 0x00D1, (char) 0x00D2, (char) 0x00D3, (char) 0x00D4, + (char) 0x00D5, (char) 0x00D6, (char) 0x00D7, + (char) 0x00D8, (char) 0x00D9, (char) 0x00DA, (char) 0x00DB, (char) 0x00DC, + (char) 0x00DD, (char) 0x00DE, (char) 0x00DF, + (char) 0x00E0, (char) 0x00E1, (char) 0x00E2, (char) 0x00E3, (char) 0x00E4, + (char) 0x00E5, (char) 0x00E6, (char) 0x00E7, + (char) 0x00E8, (char) 0x00E9, (char) 0x00EA, (char) 0x00EB, (char) 0x00EC, + (char) 0x00ED, (char) 0x00EE, (char) 0x00EF, + (char) 0x00F0, (char) 0x00F1, (char) 0x00F2, (char) 0x00F3, (char) 0x00F4, + (char) 0x00F5, (char) 0x00F6, (char) 0x00F7, + (char) 0x00F8, (char) 0x00F9, (char) 0x00FA, (char) 0x00FB, (char) 0x00FC, + (char) 0x00FD, (char) 0x00FE, (char) 0x00FF + }; + + // Regex for English contractions, e.g. "he's", "we'll", "I'm" etc. + private static final Pattern encodingRegex = + Pattern.compile( + "'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+|" + + " ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+"); + + private static final Map> bpeCache; + private static final String MAX_TOKENIZER_CACHE_SIZE_KEY = "MAX_TOKENIZER_CACHE_SIZE"; + private static final String MAX_TOKENIZER_CACHE_SIZE_DEFAULT = "100000"; + + static { + // Limit the maximum cache size + int cacheSize = + Integer.parseInt( + System.getProperty( + MAX_TOKENIZER_CACHE_SIZE_KEY, MAX_TOKENIZER_CACHE_SIZE_DEFAULT)); + bpeCache = + new LinkedHashMap>() { + @Override + protected boolean removeEldestEntry(Map.Entry> eldest) { + return size() > cacheSize; + } + }; + } + + /** + * The tokenizer uses a byte-pair encoding (BPE) algorithm to split words into sub-words based + * on frequency and merges rules. It can handle out-of-vocabulary words, punctuation, and + * special tokens. + * + * @param text Text to tokenize + * @return List of token IDs + */ + public static List encode(String text) { + List bpeTokens = new ArrayList<>(); + + if (text != null && !text.isEmpty()) { + // Find all the matches. + Matcher matcher = encodingRegex.matcher(text); + + // Determine the maximum number of UTF8 bytes that any match value could require. + int maxUtf8Length = 0; + while (matcher.find()) { + String matchValue = matcher.group(); + int utf8Length = encodingUtf8GetByteCount(matchValue); + if (utf8Length > maxUtf8Length) { + maxUtf8Length = utf8Length; + } + } + + // Ensure we have a sufficient char array to accommodate maxUtf8Length chars. + // The byte-to-char mapping scheme employed is 1:1, so we'll end up needing 1 char + // for every 1 UTF8 byte. + char[] chars = new char[maxUtf8Length]; + + // Rather than using separate space for the UTF8 bytes, we just reinterpret the char + // array as a byte array. Since our mapping is 1:1, + // the space required for the bytes will always be half of the space required for + // the chars. We can UTF8-encode into the first half, + // and then walk backwards through the bytes, using the byte-to-char mapping + // scheme to populate the chars from the back to the front. By going in reverse, + // we guarantee we won't overwrite any bytes we haven't yet seen. + byte[] bytes = new byte[maxUtf8Length]; + + // Now that our space is created, do the actual encoding. + matcher.reset(); + while (matcher.find()) { + String matchValue = matcher.group(); + + // Encode the UTF8 bytes. + int bytesWritten = encodingUtf8GetBytes(matchValue, bytes); + + // Translate those bytes into chars. + for (int i = bytesWritten - 1; i >= 0; i--) { + chars[i] = bytesToUnicode[bytes[i] & 0xFF]; + } + + // Evaluate the BPE for the encoded chars. + for (String encoding : bytePairEncoding(new String(chars, 0, bytesWritten))) { + bpeTokens.add(GPT3Settings.encoder.get(encoding)); + } + } + } + + return bpeTokens; + } + + public static List encode(StringBuilder stringBuilder) { + if (stringBuilder != null) { + return encode(stringBuilder.toString()); + } else { + return Collections.emptyList(); + } + } + + public static List encode(char[] chars) { + if (chars != null) { + return encode(new String(chars)); + } else { + return Collections.emptyList(); + } + } + + public static List encode(Iterable chars) { + if (chars != null) { + StringBuilder sb = new StringBuilder(); + for (Character c : chars) { + sb.append(c); + } + return encode(sb.toString()); + } else { + return Collections.emptyList(); + } + } + + private static int encodingUtf8GetByteCount(String str) { + return str.getBytes(StandardCharsets.UTF_8).length; + } + + private static int encodingUtf8GetBytes(String str, byte[] bytes) { + assert str != null; + assert bytes != null; + + byte[] strBytes = str.getBytes(StandardCharsets.UTF_8); + System.arraycopy(strBytes, 0, bytes, 0, strBytes.length); + return strBytes.length; + } + + private static List bytePairEncoding(String token) { + if (bpeCache.containsKey(token)) { + return bpeCache.get(token); + } + + if (token.length() <= 1) { + List list = new ArrayList<>(1); + list.add(token); + bpeCache.put(token, list); + return list; + } + + List word = new ArrayList<>(token.length()); + for (char c : token.toCharArray()) { + word.add(String.valueOf(c)); + } + + long smallestRank = Long.MAX_VALUE; + Tuple2 smallestPair = Tuples.of("", ""); + List newWord; + + while (word.size() >= 2) { + for (int pairIndex = 0; pairIndex < word.size() - 1; pairIndex++) { + Tuple2 pair = + Tuples.of(word.get(pairIndex), word.get(pairIndex + 1)); + + long pairRank = + GPT3Settings.bpeRanks.containsKey(pair) + ? GPT3Settings.bpeRanks.get(pair) + : 100_000_000_000L; + + if (pairRank <= smallestRank) { + smallestRank = pairRank; + smallestPair = pair; + } + } + + if (!GPT3Settings.bpeRanks.containsKey(smallestPair)) { + break; + } + + String first = smallestPair.getT1(); + String second = smallestPair.getT2(); + + newWord = new ArrayList<>(word.size()); + for (int i = 0; i < word.size(); i++) { + int j = word.subList(i, word.size()).indexOf(first); + + // Adjust j as sublist was used + if (j >= 0) { + j += i; + } + + int limit = j < 0 ? word.size() : j; + for (int copy = i; copy < limit; copy++) { + newWord.add(word.get(copy)); + } + + if (j < 0) { + break; + } + + i = j; + + if (i < (word.size() - 1) + && word.get(i).equals(first) + && word.get(i + 1).equals(second)) { + newWord.add(first + second); + i++; + } else { + newWord.add(word.get(i)); + } + } + + // Swap the new word in for the old + List temp = word; + word = newWord; + newWord = temp; + + // And reset state for the next go-around + newWord.clear(); + smallestRank = Long.MAX_VALUE; + } + + bpeCache.put(token, word); + return word; + } +} diff --git a/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/settings/EmbeddedResource.java b/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/settings/EmbeddedResource.java new file mode 100644 index 0000000000..145efb3879 --- /dev/null +++ b/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/settings/EmbeddedResource.java @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.settings; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +public class EmbeddedResource { + /** + * Return content of BPE file. + * + * @return BPE file content + */ + public static String readBytePairEncodingTable() throws IOException { + return readFile("vocab.bpe"); + } + + /** + * Return content of encoding table file. + * + * @return Encoding table string + */ + public static String readEncodingTable() throws IOException { + return readFile("encoder.json"); + } + + /** + * Read a content file embedded in the project. Files are read from disk, not from the classpath + * or the JAR file, to avoid inflating the JAR size. + * + * @param fileName Filename to read + * @return File content + * @throws FileNotFoundException Error in case the file doesn't exist + */ + private static String readFile(String fileName) throws IOException { + ClassLoader classLoader = EmbeddedResource.class.getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream(fileName); + + if (inputStream == null) { + throw new FileNotFoundException("File not found: " + fileName); + } + + try (InputStreamReader streamReader = + new InputStreamReader(inputStream, StandardCharsets.UTF_8); + BufferedReader reader = new BufferedReader(streamReader)) { + + String line; + StringBuilder builder = new StringBuilder(); + while ((line = reader.readLine()) != null) { + builder.append(line); + builder.append(System.lineSeparator()); + } + + return builder.toString(); + } + } +} diff --git a/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/settings/GPT3Settings.java b/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/settings/GPT3Settings.java new file mode 100644 index 0000000000..de3ae72df2 --- /dev/null +++ b/java/extensions/semantickernel-gpt3-tokenizer/src/main/java/com/microsoft/semantickernel/settings/GPT3Settings.java @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.settings; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.semantickernel.ai.AIException; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import reactor.util.function.Tuple2; +import reactor.util.function.Tuples; + +public class GPT3Settings { + + public static final Map encoder; + public static final Map, Integer> bpeRanks; + + static { + try { + encoder = getEncoder(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + try { + bpeRanks = getBpeRanks(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + // Gets the cached encoding table (encoder.json). + private static Map getEncoder() throws IOException { + try { + String encodingTableJson = EmbeddedResource.readEncodingTable(); + + // Read the JSON file and convert it to a Map + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue( + encodingTableJson, new TypeReference>() {}); + } catch (IOException e) { + System.out.println(e.getMessage()); + + throw new AIException( + AIException.ErrorCodes.INVALID_CONFIGURATION, + "Encoding table deserialization returned NULL"); + } + } + + // Gets the cached byte pair encoding table (vocab.bpe). + + private static Map, Integer> getBpeRanks() throws IOException { + String table = EmbeddedResource.readBytePairEncodingTable(); + + // Skip past the header line + int pos = table.indexOf('\n') + 1; + + // For each line, split on the first space and add the pair to the map as a key with the + // value being the entry number. + Map, Integer> result = new HashMap<>(); + int nextPos; + while ((nextPos = table.indexOf('\n', pos)) >= 0) { + String line = table.substring(pos, nextPos).trim(); + pos = line.indexOf(' '); + if (pos >= 0) { + String first = line.substring(0, pos); + String second = line.substring(pos + 1); + result.put(Tuples.of(first, second), result.size()); + } + pos = nextPos + 1; + } + + return result; + } +} diff --git a/java/extensions/semantickernel-gpt3-tokenizer/src/main/resources/encoder.json b/java/extensions/semantickernel-gpt3-tokenizer/src/main/resources/encoder.json new file mode 100644 index 0000000000..1f1d9aaca3 --- /dev/null +++ b/java/extensions/semantickernel-gpt3-tokenizer/src/main/resources/encoder.json @@ -0,0 +1 @@ +{"!": 0, "\"": 1, "#": 2, "$": 3, "%": 4, "&": 5, "'": 6, "(": 7, ")": 8, "*": 9, "+": 10, ",": 11, "-": 12, ".": 13, "/": 14, "0": 15, "1": 16, "2": 17, "3": 18, "4": 19, "5": 20, "6": 21, "7": 22, "8": 23, "9": 24, ":": 25, ";": 26, "<": 27, "=": 28, ">": 29, "?": 30, "@": 31, "A": 32, "B": 33, "C": 34, "D": 35, "E": 36, "F": 37, "G": 38, "H": 39, "I": 40, "J": 41, "K": 42, "L": 43, "M": 44, "N": 45, "O": 46, "P": 47, "Q": 48, "R": 49, "S": 50, "T": 51, "U": 52, "V": 53, "W": 54, "X": 55, "Y": 56, "Z": 57, "[": 58, "\\": 59, "]": 60, "^": 61, "_": 62, "`": 63, "a": 64, "b": 65, "c": 66, "d": 67, "e": 68, "f": 69, "g": 70, "h": 71, "i": 72, "j": 73, "k": 74, "l": 75, "m": 76, "n": 77, "o": 78, "p": 79, "q": 80, "r": 81, "s": 82, "t": 83, "u": 84, "v": 85, "w": 86, "x": 87, "y": 88, "z": 89, "{": 90, "|": 91, "}": 92, "~": 93, "\u00a1": 94, "\u00a2": 95, "\u00a3": 96, "\u00a4": 97, "\u00a5": 98, "\u00a6": 99, "\u00a7": 100, "\u00a8": 101, "\u00a9": 102, "\u00aa": 103, "\u00ab": 104, "\u00ac": 105, "\u00ae": 106, "\u00af": 107, "\u00b0": 108, "\u00b1": 109, "\u00b2": 110, "\u00b3": 111, "\u00b4": 112, "\u00b5": 113, "\u00b6": 114, "\u00b7": 115, "\u00b8": 116, "\u00b9": 117, "\u00ba": 118, "\u00bb": 119, "\u00bc": 120, "\u00bd": 121, "\u00be": 122, "\u00bf": 123, "\u00c0": 124, "\u00c1": 125, "\u00c2": 126, "\u00c3": 127, "\u00c4": 128, "\u00c5": 129, "\u00c6": 130, "\u00c7": 131, "\u00c8": 132, "\u00c9": 133, "\u00ca": 134, "\u00cb": 135, "\u00cc": 136, "\u00cd": 137, "\u00ce": 138, "\u00cf": 139, "\u00d0": 140, "\u00d1": 141, "\u00d2": 142, "\u00d3": 143, "\u00d4": 144, "\u00d5": 145, "\u00d6": 146, "\u00d7": 147, "\u00d8": 148, "\u00d9": 149, "\u00da": 150, "\u00db": 151, "\u00dc": 152, "\u00dd": 153, "\u00de": 154, "\u00df": 155, "\u00e0": 156, "\u00e1": 157, "\u00e2": 158, "\u00e3": 159, "\u00e4": 160, "\u00e5": 161, "\u00e6": 162, "\u00e7": 163, "\u00e8": 164, "\u00e9": 165, "\u00ea": 166, "\u00eb": 167, "\u00ec": 168, "\u00ed": 169, "\u00ee": 170, "\u00ef": 171, "\u00f0": 172, "\u00f1": 173, "\u00f2": 174, "\u00f3": 175, "\u00f4": 176, "\u00f5": 177, "\u00f6": 178, "\u00f7": 179, "\u00f8": 180, "\u00f9": 181, "\u00fa": 182, "\u00fb": 183, "\u00fc": 184, "\u00fd": 185, "\u00fe": 186, "\u00ff": 187, "\u0100": 188, "\u0101": 189, "\u0102": 190, "\u0103": 191, "\u0104": 192, "\u0105": 193, "\u0106": 194, "\u0107": 195, "\u0108": 196, "\u0109": 197, "\u010a": 198, "\u010b": 199, "\u010c": 200, "\u010d": 201, "\u010e": 202, "\u010f": 203, "\u0110": 204, "\u0111": 205, "\u0112": 206, "\u0113": 207, "\u0114": 208, "\u0115": 209, "\u0116": 210, "\u0117": 211, "\u0118": 212, "\u0119": 213, "\u011a": 214, "\u011b": 215, "\u011c": 216, "\u011d": 217, "\u011e": 218, "\u011f": 219, "\u0120": 220, "\u0121": 221, "\u0122": 222, "\u0123": 223, "\u0124": 224, "\u0125": 225, "\u0126": 226, "\u0127": 227, "\u0128": 228, "\u0129": 229, "\u012a": 230, "\u012b": 231, "\u012c": 232, "\u012d": 233, "\u012e": 234, "\u012f": 235, "\u0130": 236, "\u0131": 237, "\u0132": 238, "\u0133": 239, "\u0134": 240, "\u0135": 241, "\u0136": 242, "\u0137": 243, "\u0138": 244, "\u0139": 245, "\u013a": 246, "\u013b": 247, "\u013c": 248, "\u013d": 249, "\u013e": 250, "\u013f": 251, "\u0140": 252, "\u0141": 253, "\u0142": 254, "\u0143": 255, "\u0120t": 256, "\u0120a": 257, "he": 258, "in": 259, "re": 260, "on": 261, "\u0120the": 262, "er": 263, "\u0120s": 264, "at": 265, "\u0120w": 266, "\u0120o": 267, "en": 268, "\u0120c": 269, "it": 270, "is": 271, "an": 272, "or": 273, "es": 274, "\u0120b": 275, "ed": 276, "\u0120f": 277, "ing": 278, "\u0120p": 279, "ou": 280, "\u0120an": 281, "al": 282, "ar": 283, "\u0120to": 284, "\u0120m": 285, "\u0120of": 286, "\u0120in": 287, "\u0120d": 288, "\u0120h": 289, "\u0120and": 290, "ic": 291, "as": 292, "le": 293, "\u0120th": 294, "ion": 295, "om": 296, "ll": 297, "ent": 298, "\u0120n": 299, "\u0120l": 300, "st": 301, "\u0120re": 302, "ve": 303, "\u0120e": 304, "ro": 305, "ly": 306, "\u0120be": 307, "\u0120g": 308, "\u0120T": 309, "ct": 310, "\u0120S": 311, "id": 312, "ot": 313, "\u0120I": 314, "ut": 315, "et": 316, "\u0120A": 317, "\u0120is": 318, "\u0120on": 319, "im": 320, "am": 321, "ow": 322, "ay": 323, "ad": 324, "se": 325, "\u0120that": 326, "\u0120C": 327, "ig": 328, "\u0120for": 329, "ac": 330, "\u0120y": 331, "ver": 332, "ur": 333, "\u0120u": 334, "ld": 335, "\u0120st": 336, "\u0120M": 337, "'s": 338, "\u0120he": 339, "\u0120it": 340, "ation": 341, "ith": 342, "ir": 343, "ce": 344, "\u0120you": 345, "il": 346, "\u0120B": 347, "\u0120wh": 348, "ol": 349, "\u0120P": 350, "\u0120with": 351, "\u01201": 352, "ter": 353, "ch": 354, "\u0120as": 355, "\u0120we": 356, "\u0120(": 357, "nd": 358, "ill": 359, "\u0120D": 360, "if": 361, "\u01202": 362, "ag": 363, "ers": 364, "ke": 365, "\u0120\"": 366, "\u0120H": 367, "em": 368, "\u0120con": 369, "\u0120W": 370, "\u0120R": 371, "her": 372, "\u0120was": 373, "\u0120r": 374, "od": 375, "\u0120F": 376, "ul": 377, "ate": 378, "\u0120at": 379, "ri": 380, "pp": 381, "ore": 382, "\u0120The": 383, "\u0120se": 384, "us": 385, "\u0120pro": 386, "\u0120ha": 387, "um": 388, "\u0120are": 389, "\u0120de": 390, "ain": 391, "and": 392, "\u0120or": 393, "igh": 394, "est": 395, "ist": 396, "ab": 397, "rom": 398, "\u0120N": 399, "th": 400, "\u0120com": 401, "\u0120G": 402, "un": 403, "op": 404, "00": 405, "\u0120L": 406, "\u0120not": 407, "ess": 408, "\u0120ex": 409, "\u0120v": 410, "res": 411, "\u0120E": 412, "ew": 413, "ity": 414, "ant": 415, "\u0120by": 416, "el": 417, "os": 418, "ort": 419, "oc": 420, "qu": 421, "\u0120from": 422, "\u0120have": 423, "\u0120su": 424, "ive": 425, "ould": 426, "\u0120sh": 427, "\u0120this": 428, "nt": 429, "ra": 430, "pe": 431, "ight": 432, "art": 433, "ment": 434, "\u0120al": 435, "ust": 436, "end": 437, "--": 438, "all": 439, "\u0120O": 440, "ack": 441, "\u0120ch": 442, "\u0120le": 443, "ies": 444, "red": 445, "ard": 446, "\u00e2\u0122": 447, "out": 448, "\u0120J": 449, "\u0120ab": 450, "ear": 451, "iv": 452, "ally": 453, "our": 454, "ost": 455, "gh": 456, "pt": 457, "\u0120pl": 458, "ast": 459, "\u0120can": 460, "ak": 461, "ome": 462, "ud": 463, "The": 464, "\u0120his": 465, "\u0120do": 466, "\u0120go": 467, "\u0120has": 468, "ge": 469, "'t": 470, "\u0120U": 471, "rou": 472, "\u0120sa": 473, "\u0120j": 474, "\u0120but": 475, "\u0120wor": 476, "\u0120all": 477, "ect": 478, "\u0120k": 479, "ame": 480, "\u0120will": 481, "ok": 482, "\u0120whe": 483, "\u0120they": 484, "ide": 485, "01": 486, "ff": 487, "ich": 488, "pl": 489, "ther": 490, "\u0120tr": 491, "..": 492, "\u0120int": 493, "ie": 494, "ure": 495, "age": 496, "\u0120ne": 497, "ial": 498, "ap": 499, "ine": 500, "ice": 501, "\u0120me": 502, "\u0120out": 503, "ans": 504, "one": 505, "ong": 506, "ions": 507, "\u0120who": 508, "\u0120K": 509, "\u0120up": 510, "\u0120their": 511, "\u0120ad": 512, "\u01203": 513, "\u0120us": 514, "ated": 515, "ous": 516, "\u0120more": 517, "ue": 518, "og": 519, "\u0120St": 520, "ind": 521, "ike": 522, "\u0120so": 523, "ime": 524, "per": 525, ".\"": 526, "ber": 527, "iz": 528, "act": 529, "\u0120one": 530, "\u0120said": 531, "\u0120-": 532, "are": 533, "\u0120your": 534, "cc": 535, "\u0120Th": 536, "\u0120cl": 537, "ep": 538, "ake": 539, "able": 540, "ip": 541, "\u0120cont": 542, "\u0120which": 543, "ia": 544, "\u0120im": 545, "\u0120about": 546, "\u0120were": 547, "very": 548, "ub": 549, "\u0120had": 550, "\u0120en": 551, "\u0120comp": 552, ",\"": 553, "\u0120In": 554, "\u0120un": 555, "\u0120ag": 556, "ire": 557, "ace": 558, "au": 559, "ary": 560, "\u0120would": 561, "ass": 562, "ry": 563, "\u0120\u00e2\u0122": 564, "cl": 565, "ook": 566, "ere": 567, "so": 568, "\u0120V": 569, "ign": 570, "ib": 571, "\u0120off": 572, "\u0120te": 573, "ven": 574, "\u0120Y": 575, "ile": 576, "ose": 577, "ite": 578, "orm": 579, "\u0120201": 580, "\u0120res": 581, "\u0120man": 582, "\u0120per": 583, "\u0120other": 584, "ord": 585, "ult": 586, "\u0120been": 587, "\u0120like": 588, "ase": 589, "ance": 590, "ks": 591, "ays": 592, "own": 593, "ence": 594, "\u0120dis": 595, "ction": 596, "\u0120any": 597, "\u0120app": 598, "\u0120sp": 599, "int": 600, "ress": 601, "ations": 602, "ail": 603, "\u01204": 604, "ical": 605, "\u0120them": 606, "\u0120her": 607, "ount": 608, "\u0120Ch": 609, "\u0120ar": 610, "\u0120if": 611, "\u0120there": 612, "\u0120pe": 613, "\u0120year": 614, "av": 615, "\u0120my": 616, "\u0120some": 617, "\u0120when": 618, "ough": 619, "ach": 620, "\u0120than": 621, "ru": 622, "ond": 623, "ick": 624, "\u0120over": 625, "vel": 626, "\u0120qu": 627, "\u010a\u010a": 628, "\u0120sc": 629, "reat": 630, "ree": 631, "\u0120It": 632, "ound": 633, "port": 634, "\u0120also": 635, "\u0120part": 636, "fter": 637, "\u0120kn": 638, "\u0120bec": 639, "\u0120time": 640, "ens": 641, "\u01205": 642, "ople": 643, "\u0120what": 644, "\u0120no": 645, "du": 646, "mer": 647, "ang": 648, "\u0120new": 649, "----": 650, "\u0120get": 651, "ory": 652, "ition": 653, "ings": 654, "\u0120just": 655, "\u0120into": 656, "\u01200": 657, "ents": 658, "ove": 659, "te": 660, "\u0120people": 661, "\u0120pre": 662, "\u0120its": 663, "\u0120rec": 664, "\u0120tw": 665, "ian": 666, "irst": 667, "ark": 668, "ors": 669, "\u0120work": 670, "ade": 671, "ob": 672, "\u0120she": 673, "\u0120our": 674, "wn": 675, "ink": 676, "lic": 677, "\u012019": 678, "\u0120He": 679, "ish": 680, "nder": 681, "ause": 682, "\u0120him": 683, "ons": 684, "\u0120[": 685, "\u0120ro": 686, "form": 687, "ild": 688, "ates": 689, "vers": 690, "\u0120only": 691, "oll": 692, "\u0120spe": 693, "ck": 694, "ell": 695, "amp": 696, "\u0120acc": 697, "\u0120bl": 698, "ious": 699, "urn": 700, "ft": 701, "ood": 702, "\u0120how": 703, "hed": 704, "\u0120'": 705, "\u0120after": 706, "aw": 707, "\u0120att": 708, "ov": 709, "ne": 710, "\u0120play": 711, "erv": 712, "ict": 713, "\u0120could": 714, "itt": 715, "\u0120am": 716, "\u0120first": 717, "\u01206": 718, "\u0120act": 719, "\u0120$": 720, "ec": 721, "hing": 722, "ual": 723, "ull": 724, "\u0120comm": 725, "oy": 726, "old": 727, "ces": 728, "ater": 729, "\u0120fe": 730, "\u0120bet": 731, "we": 732, "iff": 733, "\u0120two": 734, "ock": 735, "\u0120back": 736, ").": 737, "ident": 738, "\u0120under": 739, "rough": 740, "sel": 741, "xt": 742, "\u0120may": 743, "round": 744, "\u0120po": 745, "ph": 746, "iss": 747, "\u0120des": 748, "\u0120most": 749, "\u0120did": 750, "\u0120add": 751, "ject": 752, "\u0120inc": 753, "fore": 754, "\u0120pol": 755, "ont": 756, "\u0120again": 757, "clud": 758, "tern": 759, "\u0120know": 760, "\u0120need": 761, "\u0120cons": 762, "\u0120co": 763, "\u0120.": 764, "\u0120want": 765, "\u0120see": 766, "\u01207": 767, "ning": 768, "iew": 769, "\u0120This": 770, "ced": 771, "\u0120even": 772, "\u0120ind": 773, "ty": 774, "\u0120We": 775, "ath": 776, "\u0120these": 777, "\u0120pr": 778, "\u0120use": 779, "\u0120because": 780, "\u0120fl": 781, "ng": 782, "\u0120now": 783, "\u0120\u00e2\u0122\u0135": 784, "com": 785, "ise": 786, "\u0120make": 787, "\u0120then": 788, "ower": 789, "\u0120every": 790, "\u0120Un": 791, "\u0120sec": 792, "oss": 793, "uch": 794, "\u0120em": 795, "\u0120=": 796, "\u0120Re": 797, "ied": 798, "rit": 799, "\u0120inv": 800, "lect": 801, "\u0120supp": 802, "ating": 803, "\u0120look": 804, "man": 805, "pect": 806, "\u01208": 807, "row": 808, "\u0120bu": 809, "\u0120where": 810, "ific": 811, "\u0120years": 812, "ily": 813, "\u0120diff": 814, "\u0120should": 815, "\u0120rem": 816, "Th": 817, "In": 818, "\u0120ev": 819, "day": 820, "'re": 821, "rib": 822, "\u0120rel": 823, "ss": 824, "\u0120def": 825, "\u0120right": 826, "\u0120sy": 827, "),": 828, "les": 829, "000": 830, "hen": 831, "\u0120through": 832, "\u0120Tr": 833, "__": 834, "\u0120way": 835, "\u0120don": 836, "\u0120,": 837, "\u012010": 838, "ased": 839, "\u0120ass": 840, "ublic": 841, "\u0120reg": 842, "\u0120And": 843, "ix": 844, "\u0120very": 845, "\u0120includ": 846, "other": 847, "\u0120imp": 848, "oth": 849, "\u0120sub": 850, "\u0120\u00e2\u0122\u0136": 851, "\u0120being": 852, "arg": 853, "\u0120Wh": 854, "==": 855, "ible": 856, "\u0120does": 857, "ange": 858, "ram": 859, "\u01209": 860, "ert": 861, "ps": 862, "ited": 863, "ational": 864, "\u0120br": 865, "\u0120down": 866, "\u0120many": 867, "aking": 868, "\u0120call": 869, "uring": 870, "ities": 871, "\u0120ph": 872, "ics": 873, "als": 874, "\u0120dec": 875, "ative": 876, "ener": 877, "\u0120before": 878, "ility": 879, "\u0120well": 880, "\u0120much": 881, "erson": 882, "\u0120those": 883, "\u0120such": 884, "\u0120ke": 885, "\u0120end": 886, "\u0120But": 887, "ason": 888, "ting": 889, "\u0120long": 890, "ef": 891, "\u0120think": 892, "ys": 893, "\u0120bel": 894, "\u0120sm": 895, "its": 896, "ax": 897, "\u0120own": 898, "\u0120prov": 899, "\u0120set": 900, "ife": 901, "ments": 902, "ble": 903, "ward": 904, "\u0120show": 905, "\u0120pres": 906, "ms": 907, "omet": 908, "\u0120ob": 909, "\u0120say": 910, "\u0120Sh": 911, "ts": 912, "ful": 913, "\u0120eff": 914, "\u0120gu": 915, "\u0120inst": 916, "und": 917, "ren": 918, "cess": 919, "\u0120ent": 920, "\u0120You": 921, "\u0120good": 922, "\u0120start": 923, "ince": 924, "\u0120made": 925, "tt": 926, "stem": 927, "olog": 928, "up": 929, "\u0120|": 930, "ump": 931, "\u0120hel": 932, "vern": 933, "ular": 934, "ually": 935, "\u0120ac": 936, "\u0120mon": 937, "\u0120last": 938, "\u0120200": 939, "10": 940, "\u0120stud": 941, "ures": 942, "\u0120Ar": 943, "self": 944, "ars": 945, "meric": 946, "ues": 947, "cy": 948, "\u0120min": 949, "ollow": 950, "\u0120col": 951, "io": 952, "\u0120mod": 953, "\u0120count": 954, "\u0120Com": 955, "hes": 956, "\u0120fin": 957, "air": 958, "ier": 959, "\u00e2\u0122\u0136": 960, "read": 961, "ank": 962, "atch": 963, "ever": 964, "\u0120str": 965, "\u0120point": 966, "ork": 967, "\u0120New": 968, "\u0120sur": 969, "ool": 970, "alk": 971, "ement": 972, "\u0120used": 973, "ract": 974, "ween": 975, "\u0120same": 976, "oun": 977, "\u0120Al": 978, "ci": 979, "\u0120differe": 980, "\u0120while": 981, "--------": 982, "\u0120game": 983, "cept": 984, "\u0120sim": 985, "...": 986, "\u0120inter": 987, "ek": 988, "\u0120report": 989, "\u0120produ": 990, "\u0120still": 991, "led": 992, "ah": 993, "\u0120here": 994, "\u0120world": 995, "\u0120though": 996, "\u0120num": 997, "arch": 998, "imes": 999, "ale": 1000, "\u0120Se": 1001, "\u0120If": 1002, "//": 1003, "\u0120Le": 1004, "\u0120ret": 1005, "\u0120ref": 1006, "\u0120trans": 1007, "ner": 1008, "ution": 1009, "ters": 1010, "\u0120take": 1011, "\u0120Cl": 1012, "\u0120conf": 1013, "way": 1014, "ave": 1015, "\u0120going": 1016, "\u0120sl": 1017, "ug": 1018, "\u0120Americ": 1019, "\u0120spec": 1020, "\u0120hand": 1021, "\u0120between": 1022, "ists": 1023, "\u0120De": 1024, "oot": 1025, "It": 1026, "\u0120ear": 1027, "\u0120against": 1028, "\u0120high": 1029, "gan": 1030, "az": 1031, "ather": 1032, "\u0120exp": 1033, "\u0120op": 1034, "\u0120ins": 1035, "\u0120gr": 1036, "\u0120help": 1037, "\u0120requ": 1038, "ets": 1039, "ins": 1040, "\u0120Pro": 1041, "ism": 1042, "\u0120found": 1043, "land": 1044, "ata": 1045, "uss": 1046, "ames": 1047, "\u0120person": 1048, "\u0120great": 1049, "pr": 1050, "\u0120sign": 1051, "\u0120An": 1052, "'ve": 1053, "\u0120somet": 1054, "\u0120ser": 1055, "hip": 1056, "\u0120run": 1057, "\u0120:": 1058, "\u0120ter": 1059, "irect": 1060, "\u0120follow": 1061, "\u0120det": 1062, "ices": 1063, "\u0120find": 1064, "12": 1065, "\u0120mem": 1066, "\u0120cr": 1067, "ered": 1068, "ex": 1069, "\u0120ext": 1070, "uth": 1071, "ense": 1072, "co": 1073, "\u0120team": 1074, "ving": 1075, "ouse": 1076, "ash": 1077, "att": 1078, "ved": 1079, "\u0120system": 1080, "\u0120As": 1081, "der": 1082, "ives": 1083, "min": 1084, "\u0120lead": 1085, "\u0120Bl": 1086, "cent": 1087, "\u0120around": 1088, "\u0120govern": 1089, "\u0120cur": 1090, "velop": 1091, "any": 1092, "\u0120cour": 1093, "alth": 1094, "ages": 1095, "ize": 1096, "\u0120car": 1097, "ode": 1098, "\u0120law": 1099, "\u0120read": 1100, "'m": 1101, "con": 1102, "\u0120real": 1103, "\u0120support": 1104, "\u012012": 1105, "....": 1106, "\u0120really": 1107, "ness": 1108, "\u0120fact": 1109, "\u0120day": 1110, "\u0120both": 1111, "ying": 1112, "\u0120serv": 1113, "\u0120For": 1114, "\u0120three": 1115, "\u0120wom": 1116, "\u0120med": 1117, "ody": 1118, "\u0120They": 1119, "50": 1120, "\u0120exper": 1121, "ton": 1122, "\u0120each": 1123, "akes": 1124, "\u0120che": 1125, "\u0120cre": 1126, "ines": 1127, "\u0120rep": 1128, "19": 1129, "gg": 1130, "illion": 1131, "\u0120grou": 1132, "ute": 1133, "ik": 1134, "We": 1135, "get": 1136, "ER": 1137, "\u0120met": 1138, "\u0120says": 1139, "ox": 1140, "\u0120during": 1141, "ern": 1142, "ized": 1143, "ared": 1144, "\u0120fam": 1145, "ically": 1146, "\u0120happ": 1147, "\u0120Is": 1148, "\u0120char": 1149, "med": 1150, "vent": 1151, "\u0120gener": 1152, "ient": 1153, "ple": 1154, "iet": 1155, "rent": 1156, "11": 1157, "ves": 1158, "ption": 1159, "\u012020": 1160, "formation": 1161, "\u0120cor": 1162, "\u0120offic": 1163, "ield": 1164, "\u0120too": 1165, "ision": 1166, "\u0120inf": 1167, "\u0120Z": 1168, "the": 1169, "oad": 1170, "\u0120public": 1171, "\u0120prog": 1172, "ric": 1173, "**": 1174, "\u0120war": 1175, "\u0120power": 1176, "view": 1177, "\u0120few": 1178, "\u0120loc": 1179, "\u0120different": 1180, "\u0120state": 1181, "\u0120head": 1182, "'ll": 1183, "\u0120poss": 1184, "\u0120stat": 1185, "ret": 1186, "ants": 1187, "\u0120val": 1188, "\u0120iss": 1189, "\u0120cle": 1190, "ivers": 1191, "anc": 1192, "\u0120expl": 1193, "\u0120another": 1194, "\u0120Q": 1195, "\u0120av": 1196, "thing": 1197, "nce": 1198, "Wh": 1199, "\u0120child": 1200, "\u0120since": 1201, "ired": 1202, "less": 1203, "\u0120life": 1204, "\u0120develop": 1205, "ittle": 1206, "\u0120dep": 1207, "\u0120pass": 1208, "\u00e3\u0125": 1209, "\u0120turn": 1210, "orn": 1211, "This": 1212, "bers": 1213, "ross": 1214, "\u0120Ad": 1215, "\u0120fr": 1216, "\u0120resp": 1217, "\u0120second": 1218, "oh": 1219, "\u0120/": 1220, "\u0120disc": 1221, "\u0120&": 1222, "\u0120something": 1223, "\u0120comple": 1224, "\u0120ed": 1225, "\u0120fil": 1226, "\u0120month": 1227, "aj": 1228, "uc": 1229, "\u0120government": 1230, "\u0120without": 1231, "\u0120leg": 1232, "\u0120dist": 1233, "\u0120put": 1234, "\u0120quest": 1235, "ann": 1236, "\u0120prot": 1237, "20": 1238, "\u0120never": 1239, "ience": 1240, "\u0120level": 1241, "\u0120art": 1242, "\u0120things": 1243, "\u0120might": 1244, "\u0120effect": 1245, "\u0120contro": 1246, "\u0120cent": 1247, "\u012018": 1248, "\u0120allow": 1249, "\u0120belie": 1250, "chool": 1251, "ott": 1252, "\u0120incre": 1253, "\u0120feel": 1254, "\u0120result": 1255, "\u0120lot": 1256, "\u0120fun": 1257, "ote": 1258, "\u0120ty": 1259, "erest": 1260, "\u0120contin": 1261, "\u0120using": 1262, "\u0120big": 1263, "201": 1264, "\u0120ask": 1265, "\u0120best": 1266, "\u0120)": 1267, "IN": 1268, "\u0120opp": 1269, "30": 1270, "\u0120number": 1271, "iness": 1272, "St": 1273, "lease": 1274, "\u0120ca": 1275, "\u0120must": 1276, "\u0120direct": 1277, "\u0120gl": 1278, "\u0120<": 1279, "\u0120open": 1280, "\u0120post": 1281, "\u0120come": 1282, "\u0120seem": 1283, "ording": 1284, "\u0120week": 1285, "ately": 1286, "ital": 1287, "\u0120el": 1288, "riend": 1289, "\u0120far": 1290, "\u0120tra": 1291, "inal": 1292, "\u0120pri": 1293, "\u0120US": 1294, "\u0120place": 1295, "\u0120form": 1296, "\u0120told": 1297, "\":": 1298, "ains": 1299, "ature": 1300, "\u0120Trump": 1301, "\u0120stand": 1302, "\u0120#": 1303, "ider": 1304, "\u0120Fr": 1305, "\u0120next": 1306, "\u0120soc": 1307, "\u0120pur": 1308, "\u0120let": 1309, "\u0120little": 1310, "\u0120hum": 1311, "\u0120i": 1312, "ron": 1313, "15": 1314, "\u012015": 1315, "\u0120commun": 1316, "\u0120mark": 1317, "\u0120There": 1318, "\u0120wr": 1319, "\u0120That": 1320, "\u0120information": 1321, "ways": 1322, "\u0120bus": 1323, "app": 1324, "\u0120invest": 1325, "me": 1326, "\u0120hard": 1327, "ained": 1328, "ead": 1329, "\u0120import": 1330, "\u0120appro": 1331, "\u0120test": 1332, "\u0120tri": 1333, "\u0120rest": 1334, "osed": 1335, "\u0120full": 1336, "\u0120care": 1337, "\u0120Sp": 1338, "\u0120case": 1339, "ON": 1340, "\u0120sk": 1341, "\u0120less": 1342, "\u0120+": 1343, "\u0120partic": 1344, "\u0120Pl": 1345, "ably": 1346, "uck": 1347, "ished": 1348, "chn": 1349, "be": 1350, "\u0120list": 1351, "ator": 1352, "\u0120top": 1353, "\u0120adv": 1354, "\u0120Be": 1355, "ruct": 1356, "\u0120dem": 1357, "ration": 1358, "ling": 1359, "gy": 1360, "reen": 1361, "ger": 1362, "\u0120home": 1363, "\u0120left": 1364, "\u0120better": 1365, "\u0120data": 1366, "\u012011": 1367, "\u0120attack": 1368, "\u0120proble": 1369, "line": 1370, "ards": 1371, "\u0120beh": 1372, "ral": 1373, "\u0120How": 1374, "\u0120She": 1375, "arge": 1376, "\u0120--": 1377, "://": 1378, "\u0120bro": 1379, "\u0120Ph": 1380, "ats": 1381, "\u0120build": 1382, "ww": 1383, "ided": 1384, "aim": 1385, "ases": 1386, "ency": 1387, "\u0120main": 1388, "ined": 1389, "\u0120including": 1390, "\u0120{": 1391, "\u0120got": 1392, "\u0120interest": 1393, "\u0120keep": 1394, "\u0120X": 1395, "\u0120eas": 1396, "aining": 1397, "\u0120class": 1398, "\u00e2\u0122\u00a6": 1399, "\u0120No": 1400, "\u0120var": 1401, "\u0120small": 1402, "ample": 1403, "AT": 1404, "\u0120ide": 1405, "\u0120So": 1406, "\u0120rece": 1407, "\u0120polit": 1408, "\u0120mov": 1409, "\u0120plan": 1410, "\u0120percent": 1411, "iving": 1412, "\u0120camp": 1413, "\u0120pay": 1414, "14": 1415, "sc": 1416, "ised": 1417, "\u0120unt": 1418, "oney": 1419, "ploy": 1420, "====": 1421, "\u0120didn": 1422, "\u0120Ind": 1423, "els": 1424, "ertain": 1425, "\u0120pos": 1426, "____": 1427, "iver": 1428, "\u0120process": 1429, "\u0120program": 1430, "ified": 1431, "\u0120Rep": 1432, "16": 1433, "uro": 1434, "ology": 1435, "atter": 1436, "ina": 1437, "\u0120name": 1438, "\u0120All": 1439, "\u0120four": 1440, "\u0120return": 1441, "vious": 1442, "bs": 1443, "\u0120called": 1444, "\u0120move": 1445, "\u0120Sc": 1446, "ird": 1447, "\u0120group": 1448, "\u0120bre": 1449, "\u0120men": 1450, "\u0120cap": 1451, "ten": 1452, "ee": 1453, "\u0120dri": 1454, "leg": 1455, "here": 1456, "uthor": 1457, "\u0120pat": 1458, "\u0120current": 1459, "ides": 1460, "\u0120pop": 1461, "to": 1462, "ention": 1463, "\u0120always": 1464, "\u0120mil": 1465, "\u0120women": 1466, "\u012016": 1467, "\u0120old": 1468, "iven": 1469, "raph": 1470, "\u0120Or": 1471, "ror": 1472, "ently": 1473, "\u0120near": 1474, "\u0120Ex": 1475, "ream": 1476, "sh": 1477, "\u012014": 1478, "\u0120free": 1479, "ission": 1480, "stand": 1481, "\u0120Con": 1482, "ality": 1483, "used": 1484, "13": 1485, "\u0120design": 1486, "\u0120change": 1487, "\u0120chang": 1488, "\u0120bo": 1489, "\u0120vis": 1490, "ember": 1491, "\u0120book": 1492, "ready": 1493, "\u0120kill": 1494, "25": 1495, "pped": 1496, "\u0120away": 1497, "\u0120able": 1498, "\u0120country": 1499, "\u0120const": 1500, "arn": 1501, "\u0120order": 1502, "AR": 1503, "ior": 1504, "ium": 1505, "orth": 1506, "18": 1507, "ailable": 1508, "\u0120sw": 1509, "\u0120million": 1510, "\u012013": 1511, "atic": 1512, "ted": 1513, "\u0120Go": 1514, "\u0120oper": 1515, "eng": 1516, "\u0120thing": 1517, "ajor": 1518, "conom": 1519, "\u0120Comm": 1520, "\u0120why": 1521, "ured": 1522, "ural": 1523, "\u0120school": 1524, "by": 1525, "\u0120Mar": 1526, "\u0120aff": 1527, "\u0120days": 1528, "\u0120ann": 1529, "ush": 1530, "ane": 1531, "If": 1532, "eg": 1533, "\u0120prof": 1534, "\u0120health": 1535, "outh": 1536, "But": 1537, "ional": 1538, ".,": 1539, "\u0120sol": 1540, "\u0120already": 1541, "\u012030": 1542, "\u0120charact": 1543, "He": 1544, "\u0120friend": 1545, "ES": 1546, "ians": 1547, "icle": 1548, "'d": 1549, "\u0120On": 1550, "\u0120least": 1551, "\u0120prom": 1552, "\u0120dr": 1553, "\u0120hist": 1554, "ither": 1555, "\u0120est": 1556, "iqu": 1557, "17": 1558, "son": 1559, "\u0120tell": 1560, "\u0120talk": 1561, "ohn": 1562, "oint": 1563, "lection": 1564, "AN": 1565, "\u0120until": 1566, "augh": 1567, "\u0120later": 1568, "\u0120ve": 1569, "\u0120view": 1570, "ending": 1571, "ived": 1572, "\u0120word": 1573, "ware": 1574, "\u0120cost": 1575, "\u0120enough": 1576, "\u0120give": 1577, "\u0120United": 1578, "\u0120techn": 1579, "arent": 1580, "OR": 1581, "\u0120par": 1582, "\u0120Dr": 1583, "\u01202016": 1584, "rist": 1585, "ering": 1586, "\u0120\u00c2": 1587, "\u0120large": 1588, "side": 1589, "acy": 1590, "ccess": 1591, "\u0120win": 1592, "\u0120important": 1593, "\u0120199": 1594, "\u0120doesn": 1595, "\u012017": 1596, "\u0120business": 1597, "\u0120clear": 1598, "\u0120rese": 1599, "\",": 1600, "ury": 1601, "\u0120equ": 1602, "aster": 1603, "alf": 1604, "\u0120American": 1605, "nect": 1606, "\u0120expect": 1607, "iversity": 1608, "\u0120occ": 1609, "\u0120Fl": 1610, "\u0120kind": 1611, "\u0120mean": 1612, "\u0120past": 1613, "\u0120dev": 1614, "\u0120bas": 1615, "let": 1616, "raft": 1617, "\u0120organ": 1618, "\u0120del": 1619, "\u0120perform": 1620, "\u0120story": 1621, "\u0120season": 1622, "\u0120Col": 1623, "\u0120claim": 1624, "\u0120came": 1625, "\u0120within": 1626, "\u0120line": 1627, "\u0120project": 1628, "\u0120At": 1629, "\u0120control": 1630, "ended": 1631, "\u0120Sy": 1632, "\u0120air": 1633, "ization": 1634, "\u0120*": 1635, "ley": 1636, "\u0120money": 1637, "idd": 1638, "You": 1639, "for": 1640, "\u0120family": 1641, "\u0120making": 1642, "\u0120bit": 1643, "\u0120police": 1644, "\u0120happen": 1645, "\u0120vers": 1646, "ony": 1647, "uff": 1648, "\u0120When": 1649, "\u0120sit": 1650, "ideo": 1651, "lf": 1652, "ison": 1653, "\u0120sure": 1654, "gin": 1655, "\u0120appear": 1656, "\u0120light": 1657, "\u0120es": 1658, "of": 1659, "\u0120water": 1660, "\u0120times": 1661, "not": 1662, "\u0120grow": 1663, "\u0120company": 1664, "\u0120Te": 1665, "ows": 1666, "\u0120mar": 1667, "ource": 1668, "iol": 1669, "arm": 1670, "br": 1671, "\u0120example": 1672, "\u0120conc": 1673, "\u0120fore": 1674, "\u0120To": 1675, "pro": 1676, "EN": 1677, "ries": 1678, "\u012025": 1679, "\u0120Can": 1680, "ney": 1681, "\u0120actually": 1682, "\u0120ever": 1683, "urity": 1684, "aken": 1685, "aps": 1686, "\u0120tax": 1687, "\u0120major": 1688, "ama": 1689, "\u0120often": 1690, "eral": 1691, "\u0120human": 1692, "\u0120job": 1693, "ister": 1694, "\u0120available": 1695, "ocr": 1696, "enn": 1697, "aid": 1698, "ivid": 1699, "\u0120record": 1700, "?\"": 1701, "\u0120sing": 1702, "\u0120Am": 1703, "idence": 1704, "\u0120news": 1705, "ster": 1706, "\u0120econom": 1707, "\u0120following": 1708, "\u0120Br": 1709, "ising": 1710, "\u0120hour": 1711, "most": 1712, "ument": 1713, "\u0120sex": 1714, "\u0120desc": 1715, "\u0120become": 1716, "\u0120Ed": 1717, "\u0120took": 1718, "\u0120having": 1719, "\u0120product": 1720, "ault": 1721, "As": 1722, "aring": 1723, "\u0120means": 1724, "\u0120hop": 1725, "une": 1726, "\u0120cho": 1727, "\u0120certain": 1728, "\u0120non": 1729, "\u0120deal": 1730, "24": 1731, "lement": 1732, "oci": 1733, "ene": 1734, "\u0120side": 1735, "\u0120Pr": 1736, "\u0120May": 1737, "\u0120reason": 1738, "ued": 1739, "ched": 1740, "ulation": 1741, "\u0120elect": 1742, "\u0120official": 1743, "\u0120possible": 1744, "\u0120hold": 1745, "ands": 1746, "ots": 1747, "\u0120city": 1748, "ories": 1749, "\u0120sever": 1750, "\u0120children": 1751, "\u0120once": 1752, "\u0120activ": 1753, "ler": 1754, "\u0120night": 1755, "itions": 1756, "\u0120John": 1757, "ape": 1758, "play": 1759, "\u0120done": 1760, "\u0120lim": 1761, "\u0120working": 1762, "\u0120Pres": 1763, "orld": 1764, "eb": 1765, "\u0120Co": 1766, "\u0120body": 1767, "ails": 1768, "utes": 1769, "\u0120Mr": 1770, "\u0120whether": 1771, "\u0120author": 1772, "rop": 1773, "\u0120proper": 1774, "\u0120seen": 1775, ");": 1776, "\u0120fac": 1777, "\u0120Su": 1778, "\u0120cond": 1779, "iting": 1780, "\u0120course": 1781, "\u0120}": 1782, "----------------": 1783, "aign": 1784, "\u0120event": 1785, "\u0120eng": 1786, "\u0120pot": 1787, "\u0120intern": 1788, "iam": 1789, "\u0120short": 1790, "empt": 1791, "\u00e3\u0124": 1792, "\u0120God": 1793, "ilar": 1794, "80": 1795, "\u0120orig": 1796, "IS": 1797, "ourn": 1798, "ability": 1799, "itive": 1800, "\u0120dam": 1801, "\u0120100": 1802, "\u0120press": 1803, "\u0120doing": 1804, "\u0120protect": 1805, "ring": 1806, "\u0120thought": 1807, "\u0120question": 1808, "rew": 1809, "\u0120War": 1810, "\u0120several": 1811, "\u0120State": 1812, "\u0120given": 1813, "\u0120fund": 1814, "\u0120Tw": 1815, "\u0120went": 1816, "ances": 1817, "work": 1818, "por": 1819, "my": 1820, "40": 1821, "\u0120arg": 1822, "artment": 1823, "ustom": 1824, "\u0120polic": 1825, "\u0120meet": 1826, "\u0120creat": 1827, "22": 1828, "\u0120States": 1829, "\u0120games": 1830, "raw": 1831, "uture": 1832, "\u0120understand": 1833, "urs": 1834, "\u0120Ob": 1835, "lish": 1836, "sy": 1837, "\u0120makes": 1838, "\u0120won": 1839, "agon": 1840, "\u0120htt": 1841, "\u0120love": 1842, "ential": 1843, "\u0120complete": 1844, "par": 1845, "\u0120Im": 1846, "AL": 1847, "\u0120account": 1848, "\u00c2\u0142": 1849, "ored": 1850, "vert": 1851, "\u0120ident": 1852, "\u01202015": 1853, "\u0120others": 1854, "\u0120Min": 1855, "iber": 1856, "verage": 1857, "There": 1858, "itional": 1859, "dd": 1860, "\u0120prob": 1861, "\u0120young": 1862, "\u0120along": 1863, "\u0120according": 1864, "\u0120yet": 1865, "\u0120members": 1866, "\u0120What": 1867, "oid": 1868, "\u0120Man": 1869, "And": 1870, "\u0120among": 1871, "ai": 1872, "\u0120employ": 1873, "\u0120Res": 1874, "\u0120>": 1875, "\u0120invol": 1876, "\u0120low": 1877, "af": 1878, "\u0120Car": 1879, "\u0120hig": 1880, "\u0120One": 1881, "\u0120Sec": 1882, "ination": 1883, "\u0120likely": 1884, "\u0120ant": 1885, "aged": 1886, "\u0120Russ": 1887, "\u0120ben": 1888, "\u0120rele": 1889, "For": 1890, "back": 1891, "\u0120Not": 1892, "\u0120president": 1893, "ball": 1894, "\u0120access": 1895, "ividual": 1896, "\u0120Dem": 1897, "\u0120Euro": 1898, "60": 1899, "\u0120known": 1900, "irl": 1901, "\u0120Gr": 1902, "\u0120early": 1903, "use": 1904, "iety": 1905, "\u00e2\u0122\u0135": 1906, "\u0120fight": 1907, "\u0120sent": 1908, "\u0120today": 1909, "\u0120market": 1910, "\".": 1911, "\u0120based": 1912, "\u0120strong": 1913, "urther": 1914, "\u0120deb": 1915, "mber": 1916, "\u0120problem": 1917, "\u0120death": 1918, "\u0120social": 1919, "imate": 1920, "AS": 1921, "ortun": 1922, "\u0120campaign": 1923, "ery": 1924, "Ch": 1925, "\u0120ey": 1926, "ially": 1927, "\u0120mus": 1928, "wh": 1929, "pos": 1930, "\u0120er": 1931, "\u0120saf": 1932, "\u0120months": 1933, "iron": 1934, "\u0120viol": 1935, "\u0120five": 1936, "\u0120stre": 1937, "\u0120players": 1938, "inc": 1939, "ald": 1940, "year": 1941, "aun": 1942, "\u0120success": 1943, "\u0120present": 1944, "erence": 1945, "\u01202014": 1946, "\u0120sugg": 1947, "\u0120particular": 1948, "\u0120try": 1949, "\u0120suggest": 1950, "\u0120Christ": 1951, "ones": 1952, "\u0120priv": 1953, "23": 1954, "\u0120crit": 1955, "\u0120land": 1956, "\u0120local": 1957, "ify": 1958, "29": 1959, "\u0120aut": 1960, "ED": 1961, "\u0120Gu": 1962, "\u0120mult": 1963, "\u0120political": 1964, "\u0120asked": 1965, "\u0120former": 1966, "itter": 1967, "ript": 1968, "\u0120close": 1969, "\u0120pract": 1970, "\u0120York": 1971, "\u0120getting": 1972, "\u0120across": 1973, "\u0120comb": 1974, "\u0120believe": 1975, "\u0120z": 1976, "\u0120toget": 1977, "\u0120together": 1978, "\u0120Cent": 1979, "irc": 1980, "\u0120individual": 1981, "\u0120Mc": 1982, "27": 1983, "isk": 1984, "\u0120Eng": 1985, "\u0120face": 1986, "\u012024": 1987, "\u0120value": 1988, "\u0120area": 1989, "ev": 1990, "\u0120writ": 1991, "\u0120President": 1992, "\u0120vot": 1993, "\u0120key": 1994, "\u0120mom": 1995, "put": 1996, "\u0120anything": 1997, "\u0120experience": 1998, "attle": 1999, "\u0120mind": 2000, "aff": 2001, "omm": 2002, "\u0120future": 2003, "ged": 2004, "\u0120cut": 2005, "\u0120tot": 2006, "itch": 2007, "\u0120video": 2008, "\u0120investig": 2009, "\u0120net": 2010, "\u0120My": 2011, "rict": 2012, "ien": 2013, ".)": 2014, "\u0120impro": 2015, "though": 2016, "wards": 2017, "\u0120connect": 2018, "\u0120Med": 2019, "selves": 2020, "ensive": 2021, "mb": 2022, "ober": 2023, "ators": 2024, "An": 2025, "\u012050": 2026, "\u0120redu": 2027, "resent": 2028, "\u0120above": 2029, "\u0120fre": 2030, "\u0120Europe": 2031, "sw": 2032, "\u0120amount": 2033, "\u0120App": 2034, "\u0120either": 2035, "\u0120milit": 2036, "\u0120anal": 2037, "\u0120fail": 2038, "\u0120En": 2039, "ales": 2040, "\u0120special": 2041, "\u0120black": 2042, "IT": 2043, "cher": 2044, "\u0120looking": 2045, "\u0120fire": 2046, "yn": 2047, "\u0120almost": 2048, "oon": 2049, "\u0120study": 2050, "\u0120miss": 2051, "ches": 2052, "rown": 2053, "\u0120tre": 2054, "\u0120community": 2055, "\u0120media": 2056, "\u0120food": 2057, "\u0120comes": 2058, "\u0120University": 2059, "\u0120single": 2060, "What": 2061, "uly": 2062, "\u0120half": 2063, "ague": 2064, "hod": 2065, "\u0120Republic": 2066, "\u0120started": 2067, "\u0120quick": 2068, "oto": 2069, "book": 2070, "\u0120issue": 2071, "itor": 2072, "\u0120else": 2073, "\u0120consider": 2074, "26": 2075, "rodu": 2076, "\u0120taken": 2077, "28": 2078, "99": 2079, "\u0120With": 2080, "\u0120true": 2081, "\u0120wa": 2082, "\u0120trad": 2083, "\u0120ago": 2084, "\u0120mess": 2085, "ief": 2086, "\u0120added": 2087, "oke": 2088, "\u0120bad": 2089, "\u0120fav": 2090, "33": 2091, "\u0120similar": 2092, "ask": 2093, "\u0120Don": 2094, "\u0120character": 2095, "orts": 2096, "\u0120House": 2097, "\u0120reported": 2098, "\u0120type": 2099, "val": 2100, "iod": 2101, "\u0120However": 2102, "\u0120targ": 2103, "\u0120entire": 2104, "pping": 2105, "\u0120history": 2106, "\u0120live": 2107, "ffic": 2108, "........": 2109, "ederal": 2110, "\u0120trying": 2111, "\u0120discuss": 2112, "\u0120Har": 2113, "aces": 2114, "lished": 2115, "\u0120self": 2116, "osp": 2117, "rest": 2118, "\u0120room": 2119, "elt": 2120, "\u0120fall": 2121, "olution": 2122, "\u0120et": 2123, "\u0120x": 2124, "\u0120isn": 2125, "\u0120idea": 2126, "bo": 2127, "\u0120sound": 2128, "\u0120Dep": 2129, "\u0120someone": 2130, "cially": 2131, "ully": 2132, "\u0120foc": 2133, "\u0120object": 2134, "ift": 2135, "aper": 2136, "\u0120player": 2137, "\u0120rather": 2138, "\u0120service": 2139, "ashing": 2140, "\u0120Do": 2141, "\u0120Part": 2142, "rug": 2143, "mon": 2144, "ply": 2145, "\u0120mor": 2146, "\u0120nothing": 2147, "\u0120provide": 2148, "IC": 2149, "ung": 2150, "\u0120party": 2151, "\u0120exist": 2152, "\u0120mag": 2153, "70": 2154, "\u0120rul": 2155, "\u0120house": 2156, "\u0120behind": 2157, "\u0120however": 2158, "\u0120World": 2159, "\u0120sum": 2160, "\u0120applic": 2161, "\u0120;": 2162, "\u0120function": 2163, "gr": 2164, "\u0120Pol": 2165, "\u0120front": 2166, "200": 2167, "\u0120series": 2168, "\u0120tem": 2169, "\u0120typ": 2170, "ills": 2171, "\u0120opt": 2172, "\u0120points": 2173, "\u0120below": 2174, "itted": 2175, "\u0120specific": 2176, "\u01202017": 2177, "umb": 2178, "\u0120ra": 2179, "\u0120previous": 2180, "\u0120pret": 2181, "reme": 2182, "\u0120custom": 2183, "\u0120court": 2184, "\u0120Me": 2185, "\u0120repl": 2186, "\u0120whole": 2187, "go": 2188, "cer": 2189, "\u0120treat": 2190, "\u0120Act": 2191, "\u0120probably": 2192, "\u0120learn": 2193, "ender": 2194, "\u0120Ass": 2195, "\u0120version": 2196, "now": 2197, "\u0120check": 2198, "\u0120Cal": 2199, "RE": 2200, "minist": 2201, "On": 2202, "ources": 2203, "\u0120benef": 2204, "\u0120doc": 2205, "\u0120deter": 2206, "\u0120enc": 2207, "\u0120super": 2208, "\u0120address": 2209, "\u0120vict": 2210, "\u01202013": 2211, "\u0120meas": 2212, "tr": 2213, "\u0120field": 2214, "When": 2215, "\u0120signific": 2216, "uge": 2217, "\u0120feat": 2218, "\u0120common": 2219, "load": 2220, "\u0120begin": 2221, "\u0120bring": 2222, "\u0120action": 2223, "erman": 2224, "\u0120describ": 2225, "\u0120indust": 2226, "\u0120wanted": 2227, "ried": 2228, "ming": 2229, "\u0120attempt": 2230, "45": 2231, "fer": 2232, "\u0120due": 2233, "ression": 2234, "##": 2235, "\u0120shall": 2236, "\u0120six": 2237, "oo": 2238, "\u0120step": 2239, "\u0120pub": 2240, "\u0120himself": 2241, "\u012023": 2242, "\u0120cop": 2243, "\u0120dest": 2244, "\u0120stop": 2245, "AC": 2246, "ibility": 2247, "\u0120lab": 2248, "icult": 2249, "\u0120hours": 2250, "\u0120create": 2251, "\u0120further": 2252, "\u0120America": 2253, "\u0120City": 2254, "\u0120dou": 2255, "head": 2256, "ST": 2257, "\u0120North": 2258, "cing": 2259, "\u0120national": 2260, "ule": 2261, "\u0120Inst": 2262, "\u0120taking": 2263, "\u0120Qu": 2264, "irt": 2265, "\u0120red": 2266, "\u0120research": 2267, "viron": 2268, "\u0120Ge": 2269, "\u0120break": 2270, "ana": 2271, "\u0120space": 2272, "aterial": 2273, "\u0120recent": 2274, "\u0120Ab": 2275, "\u0120general": 2276, "\u0120hit": 2277, "\u0120period": 2278, "\u0120everything": 2279, "ively": 2280, "\u0120phys": 2281, "\u0120saying": 2282, "anks": 2283, "\u0120cou": 2284, "\u0120cult": 2285, "aced": 2286, "eal": 2287, "uation": 2288, "\u0120coun": 2289, "lu": 2290, "\u0120include": 2291, "\u0120position": 2292, "\u0120After": 2293, "\u0120Canad": 2294, "\u0120Em": 2295, "\u0120imm": 2296, "\u0120Red": 2297, "\u0120pick": 2298, "\u0120compl": 2299, "\u0120matter": 2300, "reg": 2301, "ext": 2302, "angu": 2303, "isc": 2304, "ole": 2305, "aut": 2306, "\u0120compet": 2307, "eed": 2308, "fect": 2309, "\u012021": 2310, "\u0120Sen": 2311, "\u0120These": 2312, "asing": 2313, "\u0120cannot": 2314, "\u0120init": 2315, "\u0120relations": 2316, "ached": 2317, "\u0120bar": 2318, "\u012040": 2319, "\u0120TH": 2320, "\u01202012": 2321, "\u0120vol": 2322, "\u0120ground": 2323, "\u0120security": 2324, "\u0120upd": 2325, "ilt": 2326, "35": 2327, "\u0120concern": 2328, "\u0120Just": 2329, "\u0120white": 2330, "\u0120seems": 2331, "\u0120Her": 2332, "pecially": 2333, "ients": 2334, "\u0120announ": 2335, "\u0120fig": 2336, "ights": 2337, "\u0120stri": 2338, "like": 2339, "ids": 2340, "\u0120sus": 2341, "\u0120watch": 2342, "\u0120\u00e2": 2343, "\u0120wind": 2344, "\u0120Cont": 2345, "\u0120itself": 2346, "\u0120mass": 2347, "Al": 2348, "yle": 2349, "ique": 2350, "\u0120National": 2351, "\u0120abs": 2352, "\u0120pack": 2353, "\u0120outside": 2354, "\u0120anim": 2355, "\u0120pain": 2356, "eter": 2357, "\u0120manag": 2358, "duct": 2359, "ogn": 2360, "\u0120]": 2361, "\u0120Sept": 2362, "sec": 2363, "off": 2364, "\u0120Jan": 2365, "\u0120foot": 2366, "ades": 2367, "\u0120third": 2368, "\u0120mot": 2369, "\u0120evidence": 2370, "inton": 2371, "\u0120threat": 2372, "apt": 2373, "ples": 2374, "cle": 2375, "\u0120lo": 2376, "\u0120decl": 2377, "\u0120item": 2378, "medi": 2379, "\u0120represent": 2380, "omb": 2381, "amer": 2382, "\u0120significant": 2383, "ograph": 2384, "su": 2385, "\u0120cal": 2386, "ires": 2387, "0000": 2388, "ID": 2389, "AM": 2390, "\u0120simply": 2391, "\u0120longer": 2392, "\u0120file": 2393, "OT": 2394, "che": 2395, "So": 2396, "ateg": 2397, "org": 2398, "\u0120His": 2399, "\u0120ener": 2400, "\u0120dom": 2401, "\u0120upon": 2402, "ili": 2403, "\":\"": 2404, "\u0120themselves": 2405, "\u0120coming": 2406, "\u0120quite": 2407, "\u0120difficult": 2408, "\u0120Bar": 2409, "ilities": 2410, "rel": 2411, "ends": 2412, "cial": 2413, "64": 2414, "\u0120woman": 2415, "rap": 2416, "yr": 2417, "\u0120necess": 2418, "ips": 2419, "\u0120text": 2420, "\u0120require": 2421, "\u0120military": 2422, "\u0120review": 2423, "\u0120respons": 2424, "75": 2425, "\u0120subject": 2426, "\u0120instead": 2427, "\u0120issues": 2428, "\u0120gen": 2429, "\",\"": 2430, "\u0120minutes": 2431, "\u0120weap": 2432, "ray": 2433, "amed": 2434, "time": 2435, "bl": 2436, "How": 2437, "\u0120code": 2438, "\u0120Sm": 2439, "\u0120higher": 2440, "\u0120Ste": 2441, "ris": 2442, "\u0120page": 2443, "\u0120students": 2444, "\u0120Intern": 2445, "\u0120method": 2446, "\u0120Aug": 2447, "\u0120Per": 2448, "\u0120Ag": 2449, "\u0120policy": 2450, "\u0120Sw": 2451, "\u0120exec": 2452, "\u0120accept": 2453, "ume": 2454, "ribut": 2455, "\u0120words": 2456, "\u0120final": 2457, "\u0120changes": 2458, "\u0120Democr": 2459, "\u0120friends": 2460, "\u0120respect": 2461, "\u0120ep": 2462, "\u0120compan": 2463, "ivil": 2464, "\u0120damage": 2465, "****": 2466, "ogle": 2467, "vironment": 2468, "\u0120neg": 2469, "ental": 2470, "\u0120ap": 2471, "\u0120total": 2472, "ival": 2473, "!\"": 2474, "lim": 2475, "\u0120needs": 2476, "\u0120agre": 2477, "\u0120development": 2478, "\u0120age": 2479, "iple": 2480, "21": 2481, "\u0120results": 2482, "\u0120Af": 2483, "Sh": 2484, "\u0120gun": 2485, "\u0120Obama": 2486, "roll": 2487, "\u0120@": 2488, "\u0120rights": 2489, "\u0120Brit": 2490, "\u0120running": 2491, "\u0120wasn": 2492, "\u0120port": 2493, "\u0120rate": 2494, "\u0120pretty": 2495, "\u0120target": 2496, "\u0120saw": 2497, "\u0120circ": 2498, "\u0120works": 2499, "icro": 2500, "alt": 2501, "over": 2502, "www": 2503, "That": 2504, "lier": 2505, "\u0120everyone": 2506, "ude": 2507, "\u0120pie": 2508, "iddle": 2509, "rael": 2510, "\u0120rad": 2511, "\u0120block": 2512, "\u0120walk": 2513, "To": 2514, "\u00e3\u0123": 2515, "nes": 2516, "\u0120Aust": 2517, "aul": 2518, "rote": 2519, "\u0120South": 2520, "ession": 2521, "oph": 2522, "\u0120shows": 2523, "\u0120site": 2524, "\u0120jo": 2525, "\u0120risk": 2526, "clus": 2527, "lt": 2528, "\u0120inj": 2529, "iding": 2530, "\u0120Spe": 2531, "\u0120chall": 2532, "irm": 2533, "\u012022": 2534, "itting": 2535, "str": 2536, "\u0120hy": 2537, "LE": 2538, "key": 2539, "\u0120began": 2540, "atur": 2541, "ashington": 2542, "lam": 2543, "\u0120Dav": 2544, "bit": 2545, "\u0120size": 2546, "\u0120Par": 2547, "38": 2548, "ournal": 2549, "face": 2550, "\u0120decision": 2551, "\u0120larg": 2552, "\u0120jud": 2553, "rect": 2554, "\u0120continue": 2555, "\u0120Oct": 2556, "overed": 2557, "\u0120Int": 2558, "========": 2559, "\u0120parent": 2560, "\u0120Will": 2561, "\u0120easy": 2562, "\u0120drug": 2563, "anger": 2564, "\u0120sense": 2565, "\u0120di": 2566, "iday": 2567, "\u0120energy": 2568, "istic": 2569, "\u0120associ": 2570, "arter": 2571, "obal": 2572, "eks": 2573, "\u0120El": 2574, "urch": 2575, "\u0120girl": 2576, "oe": 2577, "itle": 2578, "\u012028": 2579, "\u0120Che": 2580, "\u0120request": 2581, "\u0120soon": 2582, "\u0120host": 2583, "ky": 2584, "\u0120states": 2585, "omes": 2586, "\u0120material": 2587, "lex": 2588, "\u0120moment": 2589, "\u0120answ": 2590, "onse": 2591, "\u0120especially": 2592, "\u0120norm": 2593, "\u0120services": 2594, "pite": 2595, "ran": 2596, "\u0120role": 2597, "44": 2598, "):": 2599, "\u0120cred": 2600, "Cl": 2601, "________": 2602, "\u0120mat": 2603, "\u0120log": 2604, "\u0120Clinton": 2605, "OU": 2606, "\u0120office": 2607, "\u012026": 2608, "\u0120charg": 2609, "\u0120track": 2610, "ma": 2611, "\u0120heart": 2612, "\u0120ball": 2613, "\u0120personal": 2614, "\u0120building": 2615, "na": 2616, "set": 2617, "body": 2618, "\u0120Black": 2619, "\u0120increase": 2620, "itten": 2621, "\u0120needed": 2622, "36": 2623, "32": 2624, "=\"": 2625, "\u0120lost": 2626, "\u0120became": 2627, "\u0120groups": 2628, "\u0120Mus": 2629, "\u0120wrote": 2630, "\u0120Pe": 2631, "\u0120prop": 2632, "joy": 2633, "\u00c3\u00a9": 2634, "\u0120White": 2635, "\u0120dead": 2636, ".'": 2637, "\u0120http": 2638, "\u0120webs": 2639, "OS": 2640, "\u0120inside": 2641, "\u0120wrong": 2642, "\u0120statement": 2643, "\u0120...": 2644, "yl": 2645, "\u0120film": 2646, "\u0120music": 2647, "\u0120share": 2648, "ification": 2649, "\u0120release": 2650, "\u0120forward": 2651, "\u0120stay": 2652, "\u0120comput": 2653, "itte": 2654, "ser": 2655, "\u0120original": 2656, "\u0120card": 2657, "\u0120cand": 2658, "\u0120div": 2659, "atural": 2660, "\u0120favor": 2661, "OM": 2662, "\u0120cases": 2663, "uses": 2664, "\u0120section": 2665, "\u0120leave": 2666, "ging": 2667, "oved": 2668, "\u0120Washington": 2669, "39": 2670, "\u0120Gl": 2671, "\u0120required": 2672, "action": 2673, "apan": 2674, "oor": 2675, "iter": 2676, "\u0120King": 2677, "\u0120countries": 2678, "\u0120German": 2679, "lling": 2680, "\u012027": 2681, "34": 2682, "\u0120questions": 2683, "\u0120prim": 2684, "\u0120cell": 2685, "\u0120shoot": 2686, "\u0120anyone": 2687, "\u0120West": 2688, "\u0120affect": 2689, "epend": 2690, "\u0120online": 2691, "\u0120Israel": 2692, "\u0120September": 2693, "\u0120ability": 2694, "\u0120content": 2695, "ises": 2696, "\u0120reve": 2697, "\u0120laun": 2698, "\u0120indic": 2699, "\u0120force": 2700, "cast": 2701, "\u0120sold": 2702, "aving": 2703, "fl": 2704, "\u0120soft": 2705, "\u0120companies": 2706, "ceed": 2707, "\u0120article": 2708, "\u0120aud": 2709, "\u0120rev": 2710, "\u0120educ": 2711, "\u0120playing": 2712, "05": 2713, "\u0120held": 2714, "ctor": 2715, "\u0120released": 2716, "\u0120federal": 2717, "37": 2718, "\u0120administ": 2719, "\u0120interview": 2720, "\u0120install": 2721, "\u0120received": 2722, "\u0120source": 2723, "uk": 2724, "Ph": 2725, "\u0120serious": 2726, "\u0120created": 2727, "\u0120cause": 2728, "\u0120immedi": 2729, "\u0120defin": 2730, "uel": 2731, "\u0120Department": 2732, "ctions": 2733, "\u0120Cour": 2734, "\u0120Now": 2735, "ze": 2736, "ites": 2737, "itution": 2738, "\u0120late": 2739, "\u0120speak": 2740, "ners": 2741, "\u0120legal": 2742, "ari": 2743, "\u0120Cor": 2744, "\u0120weeks": 2745, "\u0120model": 2746, "\u0120pred": 2747, "\u0120exact": 2748, "BC": 2749, "\u0120By": 2750, "ING": 2751, "osing": 2752, "\u0120takes": 2753, "\u0120regard": 2754, "\u0120opportun": 2755, "\u0120price": 2756, "\u0120198": 2757, "\u0120Apr": 2758, "fully": 2759, "\u0120ord": 2760, "\u0120problems": 2761, "ruction": 2762, "ham": 2763, "\u0120Count": 2764, "lege": 2765, "\u0120leaders": 2766, "ET": 2767, "lev": 2768, "\u0120deep": 2769, "ological": 2770, "ese": 2771, "haps": 2772, "\u0120Some": 2773, "\u0120pers": 2774, "\u0120contract": 2775, "\u0120relationship": 2776, "sp": 2777, "oud": 2778, "\u0120base": 2779, "48": 2780, "mit": 2781, "Ad": 2782, "ancial": 2783, "\u0120consum": 2784, "\u0120potential": 2785, "\u0120langu": 2786, "rem": 2787, "eth": 2788, "\u0120relig": 2789, "ressed": 2790, "66": 2791, "\u0120link": 2792, "\u0120lower": 2793, "ayer": 2794, "\u0120June": 2795, "\u0120fem": 2796, "unt": 2797, "erc": 2798, "urd": 2799, "\u0120contact": 2800, "\u0120ill": 2801, "\u0120mother": 2802, "\u0120estab": 2803, "htt": 2804, "\u0120March": 2805, "\u0120Bro": 2806, "\u0120China": 2807, "\u012029": 2808, "\u0120squ": 2809, "\u0120provided": 2810, "\u0120average": 2811, "asons": 2812, "\u01202011": 2813, "\u0120exam": 2814, "lin": 2815, "55": 2816, "ned": 2817, "\u0120perfect": 2818, "\u0120tou": 2819, "alse": 2820, "ux": 2821, "\u0120buy": 2822, "\u0120shot": 2823, "\u0120collect": 2824, "\u0120phot": 2825, "\u0120played": 2826, "\u0120surpr": 2827, "\u0120officials": 2828, "\u0120simple": 2829, "avy": 2830, "\u0120industry": 2831, "\u0120hands": 2832, "ground": 2833, "\u0120pull": 2834, "\u0120round": 2835, "\u0120user": 2836, "\u0120range": 2837, "uary": 2838, "\u0120private": 2839, "ops": 2840, "ees": 2841, "\u0120ways": 2842, "\u0120Mich": 2843, "\u0120veh": 2844, "\u0120except": 2845, "\u0120terms": 2846, "imum": 2847, "pper": 2848, "ION": 2849, "ores": 2850, "\u0120Dragon": 2851, "oul": 2852, "\u0120den": 2853, "\u0120performance": 2854, "\u0120bill": 2855, "cil": 2856, "47": 2857, "\u0120environment": 2858, "\u0120exc": 2859, "add": 2860, "\u0120worth": 2861, "\u0120pict": 2862, "\u0120chance": 2863, "\u01202018": 2864, "bor": 2865, "\u0120speed": 2866, "iction": 2867, "\u0120alleg": 2868, "\u0120Japan": 2869, "atory": 2870, "reet": 2871, "\u0120match": 2872, "\u0120II": 2873, "\u0120stru": 2874, "order": 2875, "\u0120ste": 2876, "\u0120living": 2877, "\u0120struct": 2878, "ino": 2879, "\u0120separ": 2880, "hern": 2881, "\u0120response": 2882, "\u0120enjoy": 2883, "\u0120via": 2884, "AD": 2885, "uments": 2886, "acebook": 2887, "\u0120member": 2888, "ibr": 2889, "izing": 2890, "\u0120tool": 2891, "\u0120Mon": 2892, "\u0120While": 2893, "hood": 2894, "\u0120Ang": 2895, "\u0120Def": 2896, "\u0120offer": 2897, "Tr": 2898, "aur": 2899, "\u0120turned": 2900, "\u0120July": 2901, "down": 2902, "anced": 2903, "\u0120recently": 2904, "\u0120Ear": 2905, "\u0120ce": 2906, "\u0120Star": 2907, "\u0120Cong": 2908, "rought": 2909, "\u0120blood": 2910, "\u0120hope": 2911, "\u0120comment": 2912, "aint": 2913, "\u0120arri": 2914, "iles": 2915, "\u0120particip": 2916, "ought": 2917, "ription": 2918, "08": 2919, "49": 2920, "\u0120gave": 2921, "\u0120select": 2922, "\u0120killed": 2923, "sych": 2924, "\u0120goes": 2925, "ij": 2926, "\u0120coll": 2927, "\u0120impact": 2928, "atives": 2929, "\u0120Ser": 2930, "09": 2931, "\u0120August": 2932, "\u0120boy": 2933, "de": 2934, "\u0120Des": 2935, "\u0120felt": 2936, "US": 2937, "\u0120expected": 2938, "\u0120image": 2939, "\u0120Mark": 2940, "ccording": 2941, "oice": 2942, "EC": 2943, "\u0120Mag": 2944, "ened": 2945, "hold": 2946, "\u0120Post": 2947, "\u0120prevent": 2948, "No": 2949, "\u0120involved": 2950, "\u0120eyes": 2951, "\u0120quickly": 2952, "At": 2953, "unk": 2954, "\u0120behav": 2955, "\u0120ur": 2956, "\u0120led": 2957, "come": 2958, "ey": 2959, "\u0120candid": 2960, "\u0120earlier": 2961, "\u0120focus": 2962, "ety": 2963, "Pro": 2964, "ledge": 2965, "ixed": 2966, "illed": 2967, "\u0120popular": 2968, "AP": 2969, "\u0120sett": 2970, "light": 2971, "\u0120various": 2972, "inks": 2973, "\u0120levels": 2974, "\u0120road": 2975, "ellig": 2976, "ables": 2977, "hel": 2978, "ittee": 2979, "\u0120Gener": 2980, "ype": 2981, "\u0120heard": 2982, "icles": 2983, "\u0120mis": 2984, "\u0120users": 2985, "\u0120San": 2986, "\u0120improve": 2987, "\u0120father": 2988, "\u0120search": 2989, "They": 2990, "vil": 2991, "\u0120profess": 2992, "\u0120knew": 2993, "\u0120loss": 2994, "\u0120events": 2995, "65": 2996, "\u0120billion": 2997, "07": 2998, "02": 2999, "\u0120News": 3000, "\u0120AM": 3001, "\u0120cover": 3002, "where": 3003, "ension": 3004, "\u0120bott": 3005, "\u0120areas": 3006, "ences": 3007, "ope": 3008, "\u0120Twitter": 3009, "ael": 3010, "\u0120gets": 3011, "\u0120Google": 3012, "\u0120sn": 3013, "iant": 3014, "\u0120vote": 3015, "\u0120nearly": 3016, "\u0120included": 3017, "\u0120recogn": 3018, "zz": 3019, "mm": 3020, "aled": 3021, "\u0120happened": 3022, "04": 3023, "\u0120hot": 3024, "\u0120whose": 3025, "\u0120civil": 3026, "\u0120suff": 3027, "oes": 3028, "itiz": 3029, "\u0120Syri": 3030, "\u0120respond": 3031, "\u0120hon": 3032, "\u0120features": 3033, "\u0120economic": 3034, "\u0120April": 3035, "rim": 3036, "\u0120technology": 3037, "\u0120option": 3038, "aging": 3039, "\u0120purch": 3040, "Re": 3041, "\u0120lat": 3042, "chie": 3043, "isl": 3044, "\u0120recomm": 3045, "uf": 3046, "\u0120training": 3047, "\u0120effects": 3048, "\u0120fast": 3049, "\u01202010": 3050, "\u0120occur": 3051, "\u0120website": 3052, "\u0120email": 3053, "\u0120sens": 3054, "ech": 3055, "\u0120oil": 3056, "\u0120influ": 3057, "\u0120currently": 3058, "\u0120Sch": 3059, "\u0120Add": 3060, "\u0120goal": 3061, "\u0120scient": 3062, "\u0120conv": 3063, "100": 3064, "emy": 3065, "\u0120decided": 3066, "\u0120travel": 3067, "\u0120mention": 3068, "LL": 3069, "03": 3070, "\u0120election": 3071, "\u0120phone": 3072, "\u0120looks": 3073, "\u0120situation": 3074, "\u0120cy": 3075, "\u0120hor": 3076, "bed": 3077, "\u0120Court": 3078, "aily": 3079, "aves": 3080, "\u0120quality": 3081, "\u0120Comp": 3082, "wise": 3083, "\u0120table": 3084, "\u0120staff": 3085, "\u0120Wind": 3086, "ett": 3087, "\u0120tried": 3088, "idered": 3089, "\u0120addition": 3090, "\u0120box": 3091, "\u0120lack": 3092, "arily": 3093, "\u0120wide": 3094, "\u0120mid": 3095, "\u0120board": 3096, "ysis": 3097, "\u0120anti": 3098, "ha": 3099, "\u0120dig": 3100, "ening": 3101, "\u0120dro": 3102, "Con": 3103, "68": 3104, "\u0120slow": 3105, "based": 3106, "sequ": 3107, "\u0120path": 3108, "Ex": 3109, "aker": 3110, "\u0120worked": 3111, "\u0120pen": 3112, "\u0120engine": 3113, "\u0120looked": 3114, "\u0120Super": 3115, "\u0120Serv": 3116, "\u0120victim": 3117, "Un": 3118, "\u0120property": 3119, "\u0120introdu": 3120, "\u0120execut": 3121, "\u0120PM": 3122, "Le": 3123, "\u0120color": 3124, "\u0120More": 3125, "\u012060": 3126, "\u0120network": 3127, "\u0120date": 3128, "cul": 3129, "idge": 3130, "\u0120extra": 3131, "31": 3132, "\u0120sle": 3133, "67": 3134, "\u0120wond": 3135, "\u0120reports": 3136, "just": 3137, "\u0120Austral": 3138, "\u0120capital": 3139, "\u0120ens": 3140, "\u0120command": 3141, "\u0120allowed": 3142, "\u0120prep": 3143, "\u0120capt": 3144, "hib": 3145, "\u0120numbers": 3146, "chan": 3147, "\u0120fair": 3148, "mp": 3149, "oms": 3150, "\u0120reach": 3151, "With": 3152, "tain": 3153, "\u0120broad": 3154, "\u0120couple": 3155, "ecause": 3156, "lying": 3157, "\u0120Feb": 3158, "\u0120screen": 3159, "\u0120lives": 3160, "\u0120prior": 3161, "\u0120Congress": 3162, "Ar": 3163, "\u0120approach": 3164, "\u0120emer": 3165, "aries": 3166, "\u0120Dis": 3167, "serv": 3168, "\u0120Ne": 3169, "\u0120built": 3170, "cies": 3171, "\u0120repe": 3172, "\u0120rules": 3173, "force": 3174, "\u0120Pal": 3175, "\u0120financial": 3176, "\u0120considered": 3177, "\u0120Char": 3178, "nces": 3179, "\u0120IS": 3180, "\u0120brought": 3181, "\u0120bi": 3182, "iers": 3183, "\u0120Sim": 3184, "OP": 3185, "\u0120products": 3186, "\u0120visit": 3187, "\u0120document": 3188, "\u0120conduct": 3189, "\u0120completely": 3190, "ining": 3191, "\u0120Calif": 3192, "ibly": 3193, "\u0120written": 3194, "\u0120TV": 3195, "ements": 3196, "\u0120draw": 3197, "One": 3198, "\u0120published": 3199, "\u0120secret": 3200, "rain": 3201, "het": 3202, "\u0120Facebook": 3203, "onday": 3204, "\u0120Up": 3205, "\u0120sexual": 3206, "\u0120thous": 3207, "\u0120Pat": 3208, "\u0120ess": 3209, "\u0120standard": 3210, "\u0120arm": 3211, "ges": 3212, "ection": 3213, "\u0120fell": 3214, "\u0120foreign": 3215, "ani": 3216, "\u0120Friday": 3217, "\u0120regular": 3218, "inary": 3219, "\u0120increased": 3220, "\u0120usually": 3221, "\u0120demon": 3222, "\u0120dark": 3223, "\u0120additional": 3224, "rol": 3225, "\u0120Of": 3226, "\u0120production": 3227, "!!": 3228, "undred": 3229, "\u0120international": 3230, "idents": 3231, "\u0120Free": 3232, "roup": 3233, "\u0120race": 3234, "\u0120mach": 3235, "\u0120huge": 3236, "All": 3237, "lear": 3238, "ovember": 3239, "\u0120town": 3240, "\u0120attention": 3241, "\u0120Off": 3242, "yond": 3243, "\u0120Then": 3244, "field": 3245, "\u0120terror": 3246, "raz": 3247, "\u0120Bo": 3248, "\u0120meeting": 3249, "\u0120Park": 3250, "\u0120arrest": 3251, "\u0120fear": 3252, "\u0120aw": 3253, "\u0120Val": 3254, "oring": 3255, "',": 3256, "\u0120extreme": 3257, "arr": 3258, "\u0120workers": 3259, "After": 3260, "\u012031": 3261, "net": 3262, "ament": 3263, "\u0120directly": 3264, "\u0120population": 3265, "ube": 3266, "\u0120October": 3267, "\u0120IN": 3268, "\u0120January": 3269, "59": 3270, "\u0120David": 3271, "\u0120cross": 3272, "cember": 3273, "\u0120First": 3274, "\u0120message": 3275, "irit": 3276, "\u0120nation": 3277, "\u0120poll": 3278, "isions": 3279, "\u0120answer": 3280, "ny": 3281, "isode": 3282, "\u0120carry": 3283, "\u0120Russia": 3284, "\u0120hear": 3285, "ength": 3286, "roy": 3287, "\u0120natural": 3288, "inally": 3289, "\u0120dog": 3290, "mitted": 3291, "\u0120trade": 3292, "\u0120subst": 3293, "\u0120multiple": 3294, "\u0120Afric": 3295, "\u0120fans": 3296, "\u0120sort": 3297, "\u0120global": 3298, "ication": 3299, "\u0120Wed": 3300, "ara": 3301, "\u0120achie": 3302, "\u0120language": 3303, "vey": 3304, "\u0120tal": 3305, "\u0120necessary": 3306, "\u0120details": 3307, "\u0120sen": 3308, "\u0120Sund": 3309, "\u0120Reg": 3310, "\u0120Rec": 3311, "06": 3312, "\u0120sil": 3313, "ressive": 3314, "\u0120medical": 3315, "unch": 3316, "ornia": 3317, "\u0120und": 3318, "fort": 3319, "ocks": 3320, "\u0120Monday": 3321, "uesday": 3322, "craft": 3323, "77": 3324, "urt": 3325, "\u0120ver": 3326, "\u0120Hill": 3327, "\u0120receive": 3328, "\u0120morning": 3329, "estern": 3330, "\u0120bank": 3331, "\u0120sat": 3332, "irth": 3333, "\u0120High": 3334, "\u0120device": 3335, "\u0120THE": 3336, "\u0120Center": 3337, "\u0120safe": 3338, "\u0120ple": 3339, "\u0120Canada": 3340, "\u0120systems": 3341, "\u0120assist": 3342, "\u0120surv": 3343, "\u0120battle": 3344, "\u0120Soc": 3345, "vertis": 3346, "She": 3347, "\u0120paper": 3348, "\u0120growth": 3349, "\u0120cast": 3350, "Sc": 3351, "\u0120plans": 3352, "lled": 3353, "\u0120parts": 3354, "\u0120wall": 3355, "\u0120movement": 3356, "\u0120practice": 3357, "imately": 3358, "\u0120display": 3359, "\u0120sometimes": 3360, "omp": 3361, "\u0120Paul": 3362, "\u0120Yes": 3363, "king": 3364, "58": 3365, "oly": 3366, "\u0120son": 3367, "\u0120avoid": 3368, "okes": 3369, "\u0120Jew": 3370, "\u0120towards": 3371, "asc": 3372, "\u0120//": 3373, "\u0120Kore": 3374, "\u0120talking": 3375, "\u0120correct": 3376, "\u0120spent": 3377, "icks": 3378, "iable": 3379, "eared": 3380, "\u0120term": 3381, "\u0120wants": 3382, "oming": 3383, "\u0120ut": 3384, "\u0120doub": 3385, "\u0120forces": 3386, "\u0120please": 3387, "69": 3388, "\u0120November": 3389, "atform": 3390, "ondon": 3391, "\u0120ones": 3392, "\u0120immediately": 3393, "\u0120Russian": 3394, "\u0120Met": 3395, "\u0120deg": 3396, "\u0120parents": 3397, "CH": 3398, "\u0120Americans": 3399, "aly": 3400, "\u0120Mod": 3401, "\u0120shown": 3402, "\u0120conditions": 3403, "\u0120stuff": 3404, "\u0120reb": 3405, "\u0120Your": 3406, "\u0120includes": 3407, "nown": 3408, "\u0120Sam": 3409, "\u0120experien": 3410, "mission": 3411, "\u0120Even": 3412, "aught": 3413, "\u0120announced": 3414, "\u0120Republican": 3415, "\u0120determin": 3416, "\u0120described": 3417, "\u0120County": 3418, "()": 3419, "\u0120door": 3420, "\u0120changed": 3421, "\u0120neigh": 3422, "\u0120Here": 3423, "\u0120clean": 3424, "\u0120pan": 3425, "\u0120December": 3426, "\u0120European": 3427, "iring": 3428, "apter": 3429, "\u0120club": 3430, "\u0120Tuesday": 3431, "\u0120paid": 3432, "\u0120Net": 3433, "\u0120attacks": 3434, "\u0120characters": 3435, "\u0120alone": 3436, "\u0120director": 3437, "dom": 3438, "\u012035": 3439, "\u0120load": 3440, "\u0120rout": 3441, "\u0120California": 3442, "\u0120finally": 3443, "\u0120rac": 3444, "\u0120contr": 3445, "\u0120exactly": 3446, "resh": 3447, "pri": 3448, "\u0120Islam": 3449, "\u0120nature": 3450, "\u0120career": 3451, "\u0120latest": 3452, "\u0120convers": 3453, "\u0120Sl": 3454, "pose": 3455, "cient": 3456, "\u0120Inc": 3457, "ivity": 3458, "88": 3459, "\u0120Att": 3460, "\u0120Mor": 3461, "nesday": 3462, "\u0120weight": 3463, "ken": 3464, "\u0120note": 3465, "\u0120teams": 3466, "\u0120\\": 3467, "airs": 3468, "\u0120Green": 3469, "\u0120hundred": 3470, "onent": 3471, "\u0120streng": 3472, "\u0120consist": 3473, "icated": 3474, "\u0120regul": 3475, "\u0120lic": 3476, "astic": 3477, "\u0120ten": 3478, "ursday": 3479, "elligence": 3480, "ously": 3481, "\u0120UK": 3482, "BI": 3483, "\u0120costs": 3484, "\u0120independ": 3485, "\u0120AP": 3486, "\u0120normal": 3487, "\u0120hom": 3488, "\u0120obvious": 3489, "\u0120swe": 3490, "\u0120star": 3491, "\u0120ready": 3492, "acher": 3493, "\u0120implement": 3494, "gest": 3495, "\u0120song": 3496, "\u0120Get": 3497, "\u0120Lab": 3498, "\u0120interesting": 3499, "using": 3500, "\u0120giving": 3501, "\u0120Sunday": 3502, "\u0120etc": 3503, "\u0120middle": 3504, "\u0120remember": 3505, "right": 3506, "osition": 3507, "utions": 3508, "\u0120max": 3509, "46": 3510, "\u0120yourself": 3511, "\u0120demand": 3512, "\u0120treatment": 3513, "\u0120danger": 3514, "\u0120Cons": 3515, "\u0120guy": 3516, "\u0120British": 3517, "\u0120physical": 3518, "\u0120related": 3519, "\u0120remain": 3520, "\u0120couldn": 3521, "\u0120refer": 3522, "\u0120citiz": 3523, "box": 3524, "ENT": 3525, "board": 3526, "\u0120inn": 3527, "IG": 3528, "ero": 3529, "\u0120Street": 3530, "ospital": 3531, "rench": 3532, "chers": 3533, "\u0120stra": 3534, "OL": 3535, "ager": 3536, "\u0120AN": 3537, "\u0120easily": 3538, "IA": 3539, "enge": 3540, "iny": 3541, "\u0120clos": 3542, "ocked": 3543, "\u0120uses": 3544, "\u0120Coun": 3545, "Im": 3546, "uild": 3547, "??": 3548, "more": 3549, "\u0120ang": 3550, "\u0120write": 3551, "olute": 3552, "57": 3553, "\u0120leader": 3554, "\u0120reading": 3555, "": 3784, "\u0120figure": 3785, "\u0120disapp": 3786, "enty": 3787, "\u0120software": 3788, "\u0120ult": 3789, "\u0120officers": 3790, "New": 3791, "Is": 3792, "\u0120remains": 3793, "\u0120India": 3794, "\u0120psych": 3795, "rief": 3796, "\u0120cat": 3797, "esc": 3798, "\u0120observ": 3799, "\u0120stage": 3800, "\u0120Dark": 3801, "\u0120enter": 3802, "change": 3803, "\u0120passed": 3804, "\u0120despite": 3805, "\u0120Out": 3806, "\u0120movie": 3807, "rs": 3808, "\u0120voice": 3809, "mine": 3810, "\u0120Play": 3811, "\u0120toward": 3812, "\u0120Ter": 3813, "\u0120region": 3814, "\u0120values": 3815, "orters": 3816, "\u0120mount": 3817, "\u0120officer": 3818, "\u0120Other": 3819, "ban": 3820, "\u0120hous": 3821, "wood": 3822, "room": 3823, "IV": 3824, "\u0120Sun": 3825, "see": 3826, "\u0120Over": 3827, "rog": 3828, "90": 3829, "\u0120lay": 3830, "\u0120Tur": 3831, "awn": 3832, "\u0120pressure": 3833, "\u0120Sub": 3834, "\u0120books": 3835, "edom": 3836, "\u0120Sand": 3837, "AA": 3838, "ago": 3839, "\u0120reasons": 3840, "ford": 3841, "\u0120activity": 3842, "UT": 3843, "Now": 3844, "\u0120Senate": 3845, "cell": 3846, "night": 3847, "\u0120calls": 3848, "inter": 3849, "\u0120letter": 3850, "\u0120Rob": 3851, "\u0120Je": 3852, "\u0120choose": 3853, "\u0120Law": 3854, "Get": 3855, "Be": 3856, "\u0120rob": 3857, "\u0120types": 3858, "\u0120platform": 3859, "\u0120quarter": 3860, "RA": 3861, "\u0120Time": 3862, "\u0120maybe": 3863, "\u0120Cr": 3864, "95": 3865, "pre": 3866, "\u0120moving": 3867, "\u0120lif": 3868, "\u0120gold": 3869, "\u0120som": 3870, "\u0120patients": 3871, "\u0120truth": 3872, "\u0120Ke": 3873, "urance": 3874, "antly": 3875, "mar": 3876, "\u0120charge": 3877, "\u0120Great": 3878, "\u0120cele": 3879, "--------------------------------": 3880, "\u0120rock": 3881, "roid": 3882, "ancy": 3883, "\u0120credit": 3884, "aud": 3885, "By": 3886, "\u0120Every": 3887, "\u0120moved": 3888, "inger": 3889, "ribution": 3890, "\u0120names": 3891, "\u0120straight": 3892, "\u0120Health": 3893, "\u0120Well": 3894, "\u0120feature": 3895, "\u0120rule": 3896, "\u0120sche": 3897, "inated": 3898, "\u0120Michael": 3899, "berg": 3900, "41": 3901, "iled": 3902, "band": 3903, "\u0120click": 3904, "\u0120Angel": 3905, "onents": 3906, "\u00c2\u0143": 3907, "\u0120Iraq": 3908, "\u0120Saturday": 3909, "\u0120aware": 3910, "part": 3911, "\u0120pattern": 3912, "OW": 3913, "\u0120Let": 3914, "\u0120grad": 3915, "igned": 3916, "\u0120associated": 3917, "\u0120style": 3918, "no": 3919, "iation": 3920, "aith": 3921, "ilies": 3922, "\u0120stories": 3923, "uration": 3924, "\u0120individuals": 3925, "\u0120\u00e2\u0122\u00a6": 3926, "miss": 3927, "\u0120Associ": 3928, "ishing": 3929, "aby": 3930, "\u0120summer": 3931, "\u0120Ben": 3932, "\u012032": 3933, "\u0120arch": 3934, "uty": 3935, "\u0120Texas": 3936, "hol": 3937, "\u0120fully": 3938, "\u0120mill": 3939, "\u0120followed": 3940, "\u0120Bill": 3941, "\u0120Indian": 3942, "\u0120Secret": 3943, "\u0120Bel": 3944, "\u0120February": 3945, "\u0120jobs": 3946, "\u0120seemed": 3947, "\u0120Govern": 3948, "ipped": 3949, "\u0120reality": 3950, "\u0120lines": 3951, "\u0120park": 3952, "\u0120measure": 3953, "\u0120Our": 3954, "IM": 3955, "\u0120brother": 3956, "\u0120growing": 3957, "\u0120ban": 3958, "\u0120estim": 3959, "\u0120cry": 3960, "\u0120School": 3961, "\u0120mechan": 3962, "\u0120OF": 3963, "\u0120Windows": 3964, "\u0120rates": 3965, "\u0120Oh": 3966, "\u0120positive": 3967, "\u0120culture": 3968, "istics": 3969, "ica": 3970, "\u0120har": 3971, "ya": 3972, "itely": 3973, "ipp": 3974, "\u0120map": 3975, "encies": 3976, "\u0120William": 3977, "II": 3978, "akers": 3979, "56": 3980, "\u0120Mart": 3981, "\u0120Rem": 3982, "\u0120altern": 3983, "itude": 3984, "\u0120coach": 3985, "rowd": 3986, "Don": 3987, "\u0120kids": 3988, "\u0120journal": 3989, "\u0120corpor": 3990, "\u0120false": 3991, "\u0120web": 3992, "\u0120sleep": 3993, "\u0120contain": 3994, "\u0120sto": 3995, "\u0120bed": 3996, "iverse": 3997, "\u0120Rich": 3998, "\u0120Chinese": 3999, "\u0120pun": 4000, "\u0120meant": 4001, "known": 4002, "\u0120notice": 4003, "\u0120favorite": 4004, "aven": 4005, "\u0120condition": 4006, "\u0120purpose": 4007, "))": 4008, "\u0120organization": 4009, "\u0120challeng": 4010, "\u0120manufact": 4011, "\u0120susp": 4012, "\u0120Ac": 4013, "\u0120critic": 4014, "unes": 4015, "uclear": 4016, "\u0120mer": 4017, "vention": 4018, "\u012080": 4019, "\u0120mist": 4020, "\u0120Us": 4021, "\u0120Tor": 4022, "http": 4023, "olf": 4024, "\u0120larger": 4025, "\u0120advant": 4026, "\u0120resear": 4027, "\u0120actions": 4028, "ml": 4029, "\u0120kept": 4030, "\u0120aim": 4031, ",'": 4032, "col": 4033, "\u0120benefits": 4034, "ifying": 4035, "\u0120actual": 4036, "\u0120International": 4037, "\u0120vehicle": 4038, "\u0120chief": 4039, "\u0120efforts": 4040, "\u0120League": 4041, "\u0120Most": 4042, "\u0120wait": 4043, "\u0120adult": 4044, "\u0120overall": 4045, "\u0120speech": 4046, "\u0120highly": 4047, "\u0120female": 4048, "\u0120error": 4049, "\u0120effective": 4050, "54": 4051, "\u0120encour": 4052, "well": 4053, "\u0120failed": 4054, "\u0120conserv": 4055, "\u0120programs": 4056, "\u0120trou": 4057, "\u0120ahead": 4058, "500": 4059, "vertisement": 4060, "IP": 4061, "\u0120Found": 4062, "pir": 4063, "\u0120%": 4064, "\u0120crime": 4065, "ander": 4066, "\u0120location": 4067, "\u0120Iran": 4068, "\u0120behavior": 4069, "azing": 4070, "\u0120rare": 4071, "\u0120emb": 4072, "\u0120caused": 4073, "\u0120ship": 4074, "\u0120active": 4075, "\u0120contribut": 4076, "\u0120green": 4077, "\u0120acqu": 4078, "\u0120reflect": 4079, "venue": 4080, "\u0120firm": 4081, "\u0120birth": 4082, "].": 4083, "\u0120clearly": 4084, "\u0120emot": 4085, "\u0120agency": 4086, "riage": 4087, "\u0120memory": 4088, "98": 4089, "SA": 4090, "\u0120See": 4091, "acing": 4092, "CC": 4093, "\u0120biggest": 4094, "\u0120rap": 4095, "\u0120basic": 4096, "\u0120band": 4097, "eat": 4098, "\u0120suspect": 4099, "\u0120Mac": 4100, "\u012090": 4101, "mark": 4102, "istan": 4103, "\u0120spread": 4104, "ams": 4105, "ki": 4106, "asy": 4107, "rav": 4108, "\u0120Rober": 4109, "\u0120demonstr": 4110, "rated": 4111, "\u0120absolute": 4112, "\u0120places": 4113, "\u0120impl": 4114, "ibrary": 4115, "\u0120cards": 4116, "\u0120destroy": 4117, "\u0120virt": 4118, "vere": 4119, "\u0120appeared": 4120, "yan": 4121, "point": 4122, "\u0120beg": 4123, "\u0120temper": 4124, "spe": 4125, "anted": 4126, "ears": 4127, "\u0120Direct": 4128, "\u0120length": 4129, "\u0120blog": 4130, "amb": 4131, "\u0120integ": 4132, "\u0120resources": 4133, "acc": 4134, "iful": 4135, "\u0120spot": 4136, "\u0120forced": 4137, "\u0120thousands": 4138, "\u0120Minister": 4139, "\u0120qual": 4140, "\u0120French": 4141, "atically": 4142, "\u0120generally": 4143, "\u0120drink": 4144, "\u0120thus": 4145, "IL": 4146, "odes": 4147, "\u0120appropri": 4148, "\u0120Read": 4149, "\u0120whom": 4150, "\u0120eye": 4151, "\u0120college": 4152, "\u012045": 4153, "irection": 4154, "\u0120ensure": 4155, "\u0120apparent": 4156, "iders": 4157, "\u0120religious": 4158, "\u0120minor": 4159, "olic": 4160, "\u0120tro": 4161, "\u0120Why": 4162, "ribute": 4163, "met": 4164, "\u0120primary": 4165, "\u0120developed": 4166, "\u0120peace": 4167, "\u0120skin": 4168, "ste": 4169, "ava": 4170, "\u0120blue": 4171, "\u0120families": 4172, "\u0120ir": 4173, "\u0120apply": 4174, "\u0120inform": 4175, "\u0120Smith": 4176, "CT": 4177, "ii": 4178, "\u0120limit": 4179, "\u0120resist": 4180, "................": 4181, "umn": 4182, "\u0120conflic": 4183, "\u0120twe": 4184, "udd": 4185, "\u0120Tom": 4186, "\u0120liter": 4187, "que": 4188, "bon": 4189, "\u0120hair": 4190, "\u0120eventually": 4191, "\u0120pus": 4192, "\u0120helped": 4193, "\u0120agg": 4194, "orney": 4195, "\u0120Apple": 4196, "\u0120fit": 4197, "\u0120Sur": 4198, "\u0120prem": 4199, "\u0120sales": 4200, "\u0120seconds": 4201, "\u0120strength": 4202, "\u0120feeling": 4203, "\u00bf\u00bd": 4204, "\u0120tour": 4205, "\u0120knows": 4206, "oom": 4207, "\u0120exerc": 4208, "\u0120somew": 4209, "\u00ef\u00bf\u00bd": 4210, ">>": 4211, "\u0120spokes": 4212, "\u0120ideas": 4213, "\u0120regist": 4214, "soft": 4215, "\u0120Del": 4216, "\u0120PC": 4217, "\u0120propos": 4218, "\u0120launch": 4219, "\u0120bottom": 4220, "TH": 4221, "\u0120Please": 4222, "vest": 4223, "itz": 4224, "\u0120Inter": 4225, "\u0120script": 4226, "\u0120rat": 4227, "arning": 4228, "\u0120il": 4229, "\u0120Jer": 4230, "\u0120Are": 4231, "\u0120whatever": 4232, "oken": 4233, "cience": 4234, "\u0120mode": 4235, "\u0120agree": 4236, "\u0120sources": 4237, "\u0120initial": 4238, "\u0120restrict": 4239, "\u0120wonder": 4240, "usion": 4241, "####": 4242, "\u0120Sil": 4243, "ville": 4244, "\u0120burn": 4245, "tw": 4246, "asion": 4247, "\u0120\u00c2\u00a3": 4248, "\u0120nor": 4249, "uing": 4250, "\u0120reached": 4251, "\u0120sun": 4252, "\u0120categ": 4253, "igration": 4254, "\u0120cook": 4255, "\u0120promot": 4256, "\u0120male": 4257, "\u0120climate": 4258, "\u0120fix": 4259, "\u0120alleged": 4260, "UR": 4261, "alled": 4262, "\u0120images": 4263, "Cont": 4264, "ota": 4265, "\u0120schools": 4266, "ios": 4267, "\u0120drop": 4268, "\u0120stream": 4269, "\u0120Mo": 4270, "\u0120previously": 4271, "aling": 4272, "\u0120pet": 4273, "\u0120double": 4274, "\u0120(@": 4275, "annel": 4276, "\u0120default": 4277, "ties": 4278, "\u0120rank": 4279, "\u0120Dec": 4280, "\u0120Council": 4281, "\u0120weapon": 4282, "\u0120stock": 4283, "\u0120analy": 4284, "\u0120Str": 4285, "\u0120picture": 4286, "\u0120Police": 4287, "ference": 4288, "\u0120century": 4289, "\u0120citizens": 4290, "\u0120onto": 4291, "\u0120expand": 4292, "\u0120hero": 4293, "\u0120Sol": 4294, "\u0120wild": 4295, "\u0120update": 4296, "\u0120customers": 4297, "ront": 4298, "def": 4299, "\u0120lik": 4300, "\u0120criminal": 4301, "\u0120Christian": 4302, "SP": 4303, "76": 4304, "\u0120leaving": 4305, "\u0120otherwise": 4306, "\u0120Dist": 4307, "\u0120basis": 4308, "52": 4309, "53": 4310, "icip": 4311, "\u0120Ber": 4312, "\u0120recommend": 4313, "\u0120floor": 4314, "\u0120crowd": 4315, "oles": 4316, "\u012070": 4317, "\u0120central": 4318, "\u0120Ev": 4319, "\u0120dream": 4320, "\u0120download": 4321, "\u0120confir": 4322, "\u0120Thom": 4323, "\u0120window": 4324, "\u0120happens": 4325, "\u0120unit": 4326, "\u0120tend": 4327, "\u0120spl": 4328, "\u0120becomes": 4329, "\u0120fighting": 4330, "\u0120predict": 4331, "\u0120Press": 4332, "\u0120Power": 4333, "\u0120heavy": 4334, "aked": 4335, "\u0120fan": 4336, "orter": 4337, "ategy": 4338, "BA": 4339, "izes": 4340, "\u0120spend": 4341, "Here": 4342, "\u01202007": 4343, "\u0120adop": 4344, "\u0120Ham": 4345, "\u0120football": 4346, "\u0120Port": 4347, "oday": 4348, "51": 4349, "ampions": 4350, "\u0120transfer": 4351, "ht": 4352, "\u012038": 4353, "term": 4354, "acity": 4355, "\u0120bur": 4356, "],": 4357, "ternal": 4358, "rig": 4359, "but": 4360, "\u0120therefore": 4361, "\u0120Because": 4362, "resp": 4363, "rey": 4364, "\u0120mission": 4365, "Some": 4366, "\u0120noted": 4367, "\u0120assum": 4368, "\u0120disease": 4369, "\u0120edit": 4370, "\u0120progress": 4371, "rd": 4372, "\u0120Brown": 4373, "ocal": 4374, "\u0120adding": 4375, "\u0120raised": 4376, "\u0120Any": 4377, "\u0120tick": 4378, "\u0120seeing": 4379, "\u0120People": 4380, "\u0120agreement": 4381, "\u0120server": 4382, "\u0120wat": 4383, "\u0120debate": 4384, "\u0120supposed": 4385, "iling": 4386, "\u0120largest": 4387, "\u0120successful": 4388, "\u0120Pri": 4389, "\u0120Democratic": 4390, "\u0120jump": 4391, "\u0120Syria": 4392, "\u0120owners": 4393, "\u0120offers": 4394, "\u0120shooting": 4395, "\u0120effic": 4396, "sey": 4397, "\u0120haven": 4398, "verse": 4399, "tered": 4400, "\u0120Light": 4401, "imal": 4402, "\u0120Big": 4403, "\u0120defend": 4404, "\u0120beat": 4405, "\u0120records": 4406, "%)": 4407, "\u0120scen": 4408, "\u0120employees": 4409, "\u0120devices": 4410, "hem": 4411, "\u0120commer": 4412, "\u0120Mex": 4413, "\u0120benefit": 4414, "\u0120Prof": 4415, "\u0120illeg": 4416, "\u0120surface": 4417, "\u0120Also": 4418, "\u0120harm": 4419, "ingly": 4420, "wide": 4421, "\u0120Alex": 4422, "\u0120shut": 4423, "\u0120Cur": 4424, "\u0120lose": 4425, "pm": 4426, "\u0120challenge": 4427, "semb": 4428, "\u0120station": 4429, "\u0120intelligence": 4430, "\u0120accur": 4431, "\u0120Flor": 4432, "\u0120requires": 4433, "\u0120Mal": 4434, "bum": 4435, "\u0120hospital": 4436, "\u0120spirit": 4437, "\u0120offered": 4438, "\u0120produce": 4439, "\u0120Commun": 4440, "\u0120creating": 4441, "\u0120cris": 4442, "spect": 4443, "\u0120ended": 4444, "\u0120daily": 4445, "\u0120voters": 4446, "lands": 4447, "ias": 4448, "ih": 4449, "ona": 4450, "\u0120smart": 4451, "\u0120Office": 4452, "\u0120Lord": 4453, "rial": 4454, "\u0120Internet": 4455, "\u0120circum": 4456, "\u0120extremely": 4457, "'.": 4458, "\u0120opinion": 4459, "\u0120Mil": 4460, "\u0120gain": 4461, "BS": 4462, "\u0120Fin": 4463, "yp": 4464, "\u0120useful": 4465, "\u0120budget": 4466, "\u0120comfort": 4467, "isf": 4468, "\u0120background": 4469, "eline": 4470, "\u0120episode": 4471, "\u0120enemy": 4472, "\u0120trial": 4473, "\u0120establish": 4474, "date": 4475, "\u0120Cap": 4476, "\u0120continues": 4477, "\u0120showing": 4478, "\u0120Union": 4479, "with": 4480, "\u0120posted": 4481, "\u0120System": 4482, "\u0120eat": 4483, "rian": 4484, "\u0120rise": 4485, "\u0120Germany": 4486, "ils": 4487, "\u0120signed": 4488, "\u0120vill": 4489, "\u0120grand": 4490, "mor": 4491, "\u0120England": 4492, "\u0120projects": 4493, "umber": 4494, "\u0120conference": 4495, "za": 4496, "\u0120responsible": 4497, "\u0120Arab": 4498, "\u0120learned": 4499, "\u00e2\u0122\u0136\u00e2\u0122\u0136": 4500, "ipping": 4501, "\u0120George": 4502, "OC": 4503, "\u0120returned": 4504, "\u0120Australia": 4505, "\u0120brief": 4506, "Qu": 4507, "\u0120brand": 4508, "illing": 4509, "abled": 4510, "\u0120highest": 4511, "\u0120train": 4512, "\u0120Commission": 4513, "while": 4514, "\u0120nom": 4515, "ception": 4516, "\u0120mut": 4517, "\u0120Blue": 4518, "\u0120incident": 4519, "vant": 4520, "86": 4521, "\u0120ID": 4522, "\u0120nuclear": 4523, "74": 4524, "\u0120Like": 4525, "\u0120RE": 4526, "\u0120Micro": 4527, "li": 4528, "mail": 4529, "\u0120charges": 4530, "89": 4531, "\u0120adjust": 4532, "ado": 4533, "\u0120earth": 4534, "NA": 4535, "\u0120prices": 4536, "PA": 4537, "\u0120draft": 4538, "\u0120runs": 4539, "\u0120candidate": 4540, "enses": 4541, "\u0120management": 4542, "\u0120Phil": 4543, "\u0120Miss": 4544, "\u0120teach": 4545, "gram": 4546, "\u0120understanding": 4547, "ait": 4548, "icago": 4549, "Add": 4550, "\u0120Ep": 4551, "secut": 4552, "\u0120separate": 4553, "\u0120instance": 4554, "\u0120eth": 4555, "\u0120unless": 4556, "********": 4557, "\u0120Fore": 4558, "inate": 4559, "\u0120operations": 4560, "Sp": 4561, "\u0120faith": 4562, "gar": 4563, "\u0120Church": 4564, "ronic": 4565, "\u0120config": 4566, "osure": 4567, "\u0120activities": 4568, "\u0120traditional": 4569, "\u012036": 4570, "\u0120direction": 4571, "\u0120machine": 4572, "\u0120surround": 4573, "\u0120push": 4574, "unction": 4575, "\u0120EU": 4576, "\u0120easier": 4577, "\u0120argument": 4578, "GB": 4579, "\u0120micro": 4580, "\u0120spending": 4581, "izations": 4582, "\u0120theory": 4583, "adow": 4584, "\u0120calling": 4585, "\u0120Last": 4586, "\u0120der": 4587, "\u0120influence": 4588, "\u0120commit": 4589, "\u0120photo": 4590, "\u0120unc": 4591, "istry": 4592, "gn": 4593, "aste": 4594, "acks": 4595, "\u0120disp": 4596, "ady": 4597, "do": 4598, "\u0120Good": 4599, "\u0120`": 4600, "\u0120wish": 4601, "\u0120revealed": 4602, "\u00c2\u0142\u00c2\u0142": 4603, "lig": 4604, "\u0120enforce": 4605, "\u0120Committee": 4606, "\u0120chem": 4607, "\u0120miles": 4608, "\u0120interested": 4609, "\u0120solution": 4610, "icy": 4611, "inct": 4612, "\u0120->": 4613, "\u0120Det": 4614, "\u0120removed": 4615, "\u0120compar": 4616, "eah": 4617, "\u0120plant": 4618, "\u0120Since": 4619, "\u0120achieve": 4620, "\u0120advantage": 4621, "\u0120slightly": 4622, "bing": 4623, "\u0120placed": 4624, "under": 4625, "2015": 4626, "\u0120Mad": 4627, "\u0120tim": 4628, "oses": 4629, "\u0120cru": 4630, "\u0120Rock": 4631, "\u0120mostly": 4632, "\u0120negative": 4633, "\u0120setting": 4634, "\u0120produced": 4635, "\u0120mur": 4636, "\u0120connection": 4637, "\u0120Mer": 4638, "\u0120driver": 4639, "\u0120executive": 4640, "\u0120assault": 4641, "\u0120born": 4642, "\u0120Ver": 4643, "tained": 4644, "\u0120structure": 4645, "\u0120reduce": 4646, "\u0120decades": 4647, "\u0120ded": 4648, "uke": 4649, "\u0120Many": 4650, "idden": 4651, "\u0120league": 4652, "Se": 4653, "\u0120join": 4654, "\u0120disco": 4655, "\u0120die": 4656, "cks": 4657, "actions": 4658, "\u0120assess": 4659, "agn": 4660, "\u0120goals": 4661, "ours": 4662, "IR": 4663, "\u0120senior": 4664, "iller": 4665, "mod": 4666, "ipment": 4667, "ocol": 4668, "uy": 4669, "\u0120Que": 4670, "\u0120parties": 4671, "irgin": 4672, "\u0120learning": 4673, "itable": 4674, "\u0120street": 4675, "\u0120camera": 4676, "App": 4677, "\u0120skills": 4678, "bre": 4679, "cious": 4680, "\u0120celebr": 4681, "\u0120Franc": 4682, "\u0120existing": 4683, "\u0120willing": 4684, "lor": 4685, "\u0120id": 4686, "\u0120Space": 4687, "\u0120critical": 4688, "\u0120La": 4689, "ortunately": 4690, "\u0120serve": 4691, "\u0120cold": 4692, "\u0120species": 4693, "TS": 4694, "\u0120animals": 4695, "\u0120Bay": 4696, "\u0120older": 4697, "\u0120Under": 4698, "estic": 4699, "\u0120Tre": 4700, "\u0120teacher": 4701, "\u0120prefer": 4702, "vis": 4703, "\u0120thread": 4704, "\u0120Matt": 4705, "\u0120manager": 4706, "\u00e3\u0125\u00bb": 4707, "\u0120professional": 4708, "\u0120Vol": 4709, "\u0120notes": 4710, "These": 4711, "ula": 4712, "\u0120fresh": 4713, "ented": 4714, "uzz": 4715, "edy": 4716, "clusion": 4717, "\u0120Rel": 4718, "\u0120doubt": 4719, "EO": 4720, "\u0120opened": 4721, "\u0120Bit": 4722, "Advertisement": 4723, "\u0120guess": 4724, "\u0120UN": 4725, "\u0120sequ": 4726, "\u0120explain": 4727, "otten": 4728, "\u0120attract": 4729, "aks": 4730, "\u0120string": 4731, "\u0120context": 4732, "ossible": 4733, "\u0120Republicans": 4734, "\u0120solid": 4735, "\u0120cities": 4736, "\u0120asking": 4737, "\u0120random": 4738, "ups": 4739, "uries": 4740, "arant": 4741, "dden": 4742, "gl": 4743, "\u0120Florida": 4744, "\u0120depend": 4745, "\u0120Scott": 4746, "\u012033": 4747, "\u0120iT": 4748, "icon": 4749, "\u0120mentioned": 4750, "\u01202000": 4751, "\u0120claimed": 4752, "\u0120definitely": 4753, "ulf": 4754, "\u0120core": 4755, "\u0120opening": 4756, "\u0120Const": 4757, "which": 4758, "\u0120Tra": 4759, "AG": 4760, "72": 4761, "\u0120believed": 4762, "ada": 4763, "\u012048": 4764, "\u0120Security": 4765, "yright": 4766, "\u0120Pet": 4767, "\u0120Lou": 4768, "\u0120holding": 4769, "================": 4770, "\u0120ice": 4771, "\u0120brow": 4772, "\u0120authorities": 4773, "host": 4774, "word": 4775, "\u0120score": 4776, "\u0120Div": 4777, "\u0120cells": 4778, "\u0120transl": 4779, "\u0120neighbor": 4780, "\u0120remove": 4781, "uct": 4782, "\u0120district": 4783, "\u0120According": 4784, "\u0120worse": 4785, "\u0120concerns": 4786, "\u0120presidential": 4787, "\u0120policies": 4788, "\u0120Hall": 4789, "73": 4790, "\u0120hus": 4791, "AY": 4792, "\u01202006": 4793, "\u0120Jud": 4794, "\u0120independent": 4795, "\u0120Justice": 4796, "iliar": 4797, "print": 4798, "ighter": 4799, "\u0120protection": 4800, "zen": 4801, "\u0120sudden": 4802, "house": 4803, "\u0120Jes": 4804, "PR": 4805, "\u0120Inf": 4806, "\u0120bul": 4807, "\u0120_": 4808, "\u0120Service": 4809, "\u0120PR": 4810, "\u0120strategy": 4811, "ffect": 4812, "\u0120girls": 4813, "\u0120missing": 4814, "oyal": 4815, "\u0120Team": 4816, "ulated": 4817, "\u0120dat": 4818, "\u0120politics": 4819, "abor": 4820, "According": 4821, "\u0120spell": 4822, "\u0120graph": 4823, "orthern": 4824, "TC": 4825, "Ab": 4826, "\u0120labor": 4827, "isher": 4828, "\u0120kick": 4829, "\u0120iTunes": 4830, "\u0120steps": 4831, "poses": 4832, "\u0120smaller": 4833, "En": 4834, "bert": 4835, "\u0120roll": 4836, "\u0120researchers": 4837, "\u0120closed": 4838, "\u0120transport": 4839, "\u0120lawy": 4840, "________________": 4841, "\u0120Chicago": 4842, "\u0120aspect": 4843, "\u0120none": 4844, "\u0120marriage": 4845, "96": 4846, "\u0120elements": 4847, "\u0120Fre": 4848, "\u0120Sal": 4849, "\u0120dram": 4850, "FC": 4851, "top": 4852, "equ": 4853, "\u0120hearing": 4854, "\u0120supported": 4855, "\u0120testing": 4856, "cohol": 4857, "\u0120massive": 4858, "\u0120stick": 4859, "\u0120guard": 4860, "isco": 4861, "phone": 4862, "From": 4863, "However": 4864, "\u0120border": 4865, "\u0120copy": 4866, "ography": 4867, "list": 4868, "71": 4869, "\u0120owner": 4870, "class": 4871, "ruit": 4872, "rate": 4873, "\u0120Once": 4874, "\u0120digital": 4875, "\u0120task": 4876, "ERS": 4877, "\u0120incred": 4878, "tes": 4879, "++": 4880, "\u0120France": 4881, "\u0120breat": 4882, "owl": 4883, "\u0120issued": 4884, "\u0120Western": 4885, "\u0120detect": 4886, "\u0120partners": 4887, "\u0120shared": 4888, "\u0120Call": 4889, "\u0120cancer": 4890, "ache": 4891, "ribe": 4892, "\u0120explained": 4893, "\u0120heat": 4894, "{\"": 4895, "\u0120investment": 4896, "\u0120Book": 4897, "\u0120wood": 4898, "\u0120tools": 4899, "\u0120Although": 4900, "\u0120belief": 4901, "\u0120crisis": 4902, "\u0120ge": 4903, "\u0120MP": 4904, "\u0120operation": 4905, "type": 4906, "~~": 4907, "ga": 4908, "\u0120contains": 4909, "anta": 4910, "\u0120express": 4911, "\u0120Group": 4912, "\u0120Journal": 4913, "ka": 4914, "\u0120amb": 4915, "\u0120USA": 4916, "\u0120finding": 4917, "\u0120funding": 4918, "how": 4919, "\u0120established": 4920, "ideos": 4921, "\u0120degree": 4922, "\u0120dangerous": 4923, "anging": 4924, "\u0120freedom": 4925, "pport": 4926, "outhern": 4927, "\u0120church": 4928, "\u0120catch": 4929, "\u0120Two": 4930, "\u0120presence": 4931, "\u0120Guard": 4932, "Up": 4933, "\u0120authority": 4934, "\u0120Project": 4935, "\u0120button": 4936, "\u0120consequ": 4937, "\u0120valid": 4938, "\u0120weak": 4939, "\u0120starts": 4940, "\u0120reference": 4941, "\u0120Mem": 4942, "\")": 4943, "UN": 4944, "orage": 4945, "\u0120Open": 4946, "\u0120collection": 4947, "ym": 4948, "gency": 4949, "\u0120beautiful": 4950, "ros": 4951, "\u0120tells": 4952, "\u0120waiting": 4953, "nel": 4954, "\u0120providing": 4955, "\u0120Democrats": 4956, "\u0120daughter": 4957, "\u0120master": 4958, "\u0120purposes": 4959, "\u0120Japanese": 4960, "\u0120equal": 4961, "\u0120turns": 4962, "\u0120documents": 4963, "\u0120watching": 4964, "Res": 4965, "\u0120ran": 4966, "2014": 4967, "\u0120reject": 4968, "\u0120Korea": 4969, "\u0120victims": 4970, "Level": 4971, "erences": 4972, "\u0120witness": 4973, "\u012034": 4974, "\u0120reform": 4975, "coming": 4976, "\u0120occup": 4977, "\u0120caught": 4978, "\u0120traffic": 4979, "ading": 4980, "\u0120models": 4981, "ario": 4982, "\u0120served": 4983, "\u0120batter": 4984, "uate": 4985, "\u0120Secretary": 4986, "\u0120agreed": 4987, "\u0120truly": 4988, "ynam": 4989, "\u0120Ret": 4990, "\u0120units": 4991, "\u0120Research": 4992, "hand": 4993, "azine": 4994, "\u0120Mike": 4995, "\u0120variety": 4996, "otal": 4997, "\u0120amazing": 4998, "\u0120confirmed": 4999, "\u0120entirely": 5000, "\u0120purchase": 5001, "\u0120element": 5002, "\u0120cash": 5003, "\u0120determine": 5004, "De": 5005, "\u0120cars": 5006, "\u0120Wall": 5007, "\u00e2\u0138": 5008, "\u0120views": 5009, "\u0120drugs": 5010, "\u0120department": 5011, "\u0120Step": 5012, "uit": 5013, "\u012039": 5014, "asure": 5015, "\u0120Class": 5016, "\u0120covered": 5017, "\u0120Bank": 5018, "\u0120mere": 5019, "uana": 5020, "\u0120multi": 5021, "\u0120mix": 5022, "\u0120unlike": 5023, "levision": 5024, "\u0120stopped": 5025, "\u0120sem": 5026, "\u0120Gal": 5027, "ules": 5028, "\u0120wel": 5029, "\u0120Johnson": 5030, "la": 5031, "\u0120skill": 5032, "\u0120becoming": 5033, "rie": 5034, "\u0120appropriate": 5035, "fe": 5036, "ellow": 5037, "\u0120Prot": 5038, "ulate": 5039, "ocation": 5040, "\u0120weekend": 5041, "odies": 5042, "\u0120sites": 5043, "\u0120animal": 5044, "\u0120Tim": 5045, "\u0120scale": 5046, "\u0120charged": 5047, "\u0120instruct": 5048, "illa": 5049, "\u0120methods": 5050, "\u0120cert": 5051, "\u0120judge": 5052, "\u0120Hel": 5053, "\u0120dollars": 5054, "\u0120standing": 5055, "\u0120Squ": 5056, "\u0120debt": 5057, "liam": 5058, "\u0120driving": 5059, "\u0120Sum": 5060, "\u0120Edition": 5061, "\u0120album": 5062, "andon": 5063, "IF": 5064, "\u0120Uk": 5065, "63": 5066, "ader": 5067, "\u0120commercial": 5068, "esh": 5069, "\u0120Government": 5070, "\u0120discovered": 5071, "\u0120output": 5072, "\u0120Hillary": 5073, "\u0120Carol": 5074, "\u01202005": 5075, "\u0120abuse": 5076, "ancing": 5077, "\u0120switch": 5078, "\u0120annual": 5079, "Tw": 5080, "\u0120stated": 5081, "agement": 5082, "inner": 5083, "\u0120democr": 5084, "\u0120residents": 5085, "\u0120allowing": 5086, "\u0120factors": 5087, "odd": 5088, "\u0120fuck": 5089, "emies": 5090, "\u0120occurred": 5091, "oti": 5092, "\u0120north": 5093, "\u0120Public": 5094, "\u0120injury": 5095, "\u0120insurance": 5096, "CL": 5097, "olly": 5098, "\u00e3\u0122": 5099, "\u0120repeated": 5100, "\u0120arms": 5101, "anged": 5102, "\u0120construction": 5103, "\u0120fle": 5104, "PU": 5105, "icians": 5106, "\u0120forms": 5107, "\u0120McC": 5108, "antic": 5109, "\u0120mental": 5110, "pire": 5111, "\u0120equipment": 5112, "\u0120fant": 5113, "\u0120discussion": 5114, "\u0120regarding": 5115, "kin": 5116, "arp": 5117, "\u0120chair": 5118, "ogue": 5119, "\u0120proceed": 5120, "\u0120Id": 5121, "Our": 5122, "\u0120murder": 5123, "Man": 5124, "\u012049": 5125, "asp": 5126, "\u0120supply": 5127, "\u0120input": 5128, "\u0120wealth": 5129, "liament": 5130, "\u0120proced": 5131, "orial": 5132, "\u0120Stat": 5133, "\u0120NFL": 5134, "hens": 5135, "\u0120Institute": 5136, "\u0120putting": 5137, "ournament": 5138, "etic": 5139, "\u0120located": 5140, "\u0120kid": 5141, "eria": 5142, "run": 5143, "\u0120princ": 5144, "\u0120!": 5145, "going": 5146, "\u0120Bet": 5147, "\u0120clot": 5148, "\u0120telling": 5149, "\u0120proposed": 5150, "iot": 5151, "orry": 5152, "\u0120funds": 5153, "gment": 5154, "\u0120Life": 5155, "\u0120baby": 5156, "\u0120Back": 5157, "\u0120spoke": 5158, "Image": 5159, "\u0120earn": 5160, "\u0120AT": 5161, "gu": 5162, "\u0120exchange": 5163, "\u0120Lin": 5164, "oving": 5165, "\u0120pair": 5166, "More": 5167, "azon": 5168, "\u0120arrested": 5169, "\u0120killing": 5170, "can": 5171, "\u0120Card": 5172, "yd": 5173, "\u0120identified": 5174, "\u0120mobile": 5175, "\u0120thanks": 5176, "onym": 5177, "\u0120Form": 5178, "\u0120hundreds": 5179, "\u0120Chris": 5180, "\u0120Cat": 5181, "\u0120trend": 5182, "hat": 5183, "\u0120Av": 5184, "oman": 5185, "\u0120electric": 5186, "\u0120Wil": 5187, "SE": 5188, "Of": 5189, "\u0120restaur": 5190, "oted": 5191, "\u0120trig": 5192, "\u0120nine": 5193, "\u0120bomb": 5194, "Why": 5195, "\u00c2\u00af": 5196, "\u0120coverage": 5197, "\u0120appeal": 5198, "\u0120Robert": 5199, "\u0120Sup": 5200, "\u0120finished": 5201, "\u0120flow": 5202, "\u0120deliver": 5203, "\u0120calcul": 5204, "\u0120photos": 5205, "\u0120phil": 5206, "\u0120pieces": 5207, "\u0120appre": 5208, "kes": 5209, "\u0120rough": 5210, "Do": 5211, "\u0120partner": 5212, "\u0120concerned": 5213, "\u012037": 5214, "\u0120Gen": 5215, "Col": 5216, "ctors": 5217, "\u0120=>": 5218, "state": 5219, "\u0120suggested": 5220, "\u0120Force": 5221, "CE": 5222, "\u0120herself": 5223, "\u0120Plan": 5224, "works": 5225, "ooth": 5226, "rency": 5227, "\u0120corner": 5228, "\u0120husband": 5229, "\u0120internet": 5230, "\u0120Aut": 5231, "ems": 5232, "osen": 5233, "\u0120Atl": 5234, "gen": 5235, "\u0120balance": 5236, "62": 5237, "\u0120sounds": 5238, "text": 5239, "\u0120arr": 5240, "oves": 5241, "\u0120millions": 5242, "\u0120radio": 5243, "\u0120satisf": 5244, "\u0120Dam": 5245, "Mr": 5246, "Go": 5247, "Spe": 5248, "\u0120combat": 5249, "rant": 5250, "\u0120Gree": 5251, "\u0120fuel": 5252, "\u0120distance": 5253, "\u0120tests": 5254, "\u0120decre": 5255, "\u0120Er": 5256, "\u0120managed": 5257, "DS": 5258, "\u0120tit": 5259, "\u0120measures": 5260, "\u0120Liber": 5261, "\u0120attend": 5262, "ashed": 5263, "\u0120Jose": 5264, "\u0120Night": 5265, "dit": 5266, "\u0120Nov": 5267, "\u0120End": 5268, "outs": 5269, "\u0120generation": 5270, "\u0120advoc": 5271, "yth": 5272, "\u0120conversation": 5273, "\u0120Sky": 5274, "active": 5275, "cel": 5276, "rier": 5277, "\u0120Frank": 5278, "\u0120gender": 5279, "\u0120concent": 5280, "\u0120carried": 5281, "anda": 5282, "\u0120Virgin": 5283, "\u0120arrived": 5284, "icide": 5285, "aded": 5286, "\u0120failure": 5287, "\u0120minimum": 5288, "lets": 5289, "\u0120worst": 5290, "\u0120keeping": 5291, "\u0120intended": 5292, "\u0120illegal": 5293, "\u0120subsc": 5294, "\u0120determined": 5295, "\u0120trip": 5296, "Yes": 5297, "\u0120raise": 5298, "\u0120~": 5299, "\u0120feels": 5300, "\u0120package": 5301, "\u0120Jo": 5302, "hi": 5303, "2016": 5304, "real": 5305, "\u0120fra": 5306, "\u0120symb": 5307, "Me": 5308, "ucky": 5309, "pret": 5310, "\u0120Kh": 5311, "\u0120Edit": 5312, "\u0120Web": 5313, "emic": 5314, "\u0120Color": 5315, "\u0120justice": 5316, "Int": 5317, "\u0120farm": 5318, "cknow": 5319, "\">": 5320, "eless": 5321, "\u0120reduced": 5322, "\u0120500": 5323, "xx": 5324, "\u0120Rad": 5325, "\u0120Wood": 5326, "\u0120clin": 5327, "\u0120hyp": 5328, "iler": 5329, "ura": 5330, "kins": 5331, "85": 5332, "61": 5333, "\u0120Their": 5334, "\u0120Mary": 5335, "\u0120san": 5336, "\u0120novel": 5337, "\u0120Who": 5338, "\u0120capacity": 5339, "\u0120impossible": 5340, "\u0120plays": 5341, "\u0120minister": 5342, "ijuana": 5343, "icate": 5344, "\u0120Set": 5345, "\u0120fram": 5346, "\u0120ing": 5347, "\u0120communities": 5348, "\u0120FBI": 5349, "ita": 5350, "\u0120bon": 5351, "\u0120strateg": 5352, "\u0120interests": 5353, "lock": 5354, "gers": 5355, "mas": 5356, "\u0120AND": 5357, "\u0120conflict": 5358, "\u0120requirements": 5359, "\u0120sac": 5360, "\u0120operating": 5361, "ini": 5362, "related": 5363, "\u0120committed": 5364, "\u0120relatively": 5365, "\u0120south": 5366, "\u00c2\u00af\u00c2\u00af": 5367, "\u0120afford": 5368, "\u0120identity": 5369, "\u0120decisions": 5370, "\u0120accused": 5371, "place": 5372, "\u0120victory": 5373, "och": 5374, "iat": 5375, "Name": 5376, "Com": 5377, "tion": 5378, "eds": 5379, "\u0120seek": 5380, "\u0120tight": 5381, "\u0120Images": 5382, "\u0120initi": 5383, "\u0120humans": 5384, "\u0120familiar": 5385, "\u0120audience": 5386, "\u0120internal": 5387, "venture": 5388, "\u0120sides": 5389, "\u0120TO": 5390, "\u0120dim": 5391, "\u0120conclud": 5392, "\u0120appoint": 5393, "\u0120enforcement": 5394, "\u0120Jim": 5395, "\u0120Association": 5396, "\u0120circumst": 5397, "\u0120Canadian": 5398, "\u0120joined": 5399, "\u0120differences": 5400, "\u0120Los": 5401, "\u0120protest": 5402, "\u0120twice": 5403, "win": 5404, "\u0120glass": 5405, "arsh": 5406, "\u0120Army": 5407, "\u0120expression": 5408, "\u0120decide": 5409, "\u0120planning": 5410, "ania": 5411, "\u0120handle": 5412, "\u0120Microsoft": 5413, "\u0120Nor": 5414, "\u0120maximum": 5415, "\u0120Rev": 5416, "\u0120sea": 5417, "\u0120eval": 5418, "\u0120helps": 5419, "ref": 5420, "\u0120bound": 5421, "\u0120mouth": 5422, "\u0120standards": 5423, "\u0120clim": 5424, "\u0120Camp": 5425, "\u0120Fox": 5426, "cles": 5427, "\u0120army": 5428, "\u0120Techn": 5429, "acking": 5430, "xy": 5431, "SS": 5432, "\u012042": 5433, "\u0120bug": 5434, "\u0120Ukrain": 5435, "\u0120Max": 5436, "\u0120Jones": 5437, "\u0120Show": 5438, "lo": 5439, "\u0120planet": 5440, "\u012075": 5441, "\u0120winning": 5442, "\u0120faster": 5443, "\u0120spect": 5444, "\u0120broken": 5445, "TR": 5446, "\u0120defined": 5447, "\u0120healthy": 5448, "\u0120competition": 5449, "https": 5450, "\u0120Island": 5451, "\u0120Fe": 5452, "\u0120announce": 5453, "\u0120Cup": 5454, "\u0120Instead": 5455, "\u0120client": 5456, "\u0120possibly": 5457, "section": 5458, "ocket": 5459, "look": 5460, "\u0120finish": 5461, "\u0120crew": 5462, "\u0120reserv": 5463, "\u0120editor": 5464, "\u0120hate": 5465, "\u0120sale": 5466, "\u0120controvers": 5467, "\u0120pages": 5468, "wing": 5469, "\u0120numer": 5470, "\u0120opposition": 5471, "\u01202004": 5472, "\u0120refuge": 5473, "\u0120flight": 5474, "\u0120apart": 5475, "\u0120Lat": 5476, "Americ": 5477, "\u0120Africa": 5478, "\u0120applications": 5479, "\u0120Palest": 5480, "\u0120Bur": 5481, "\u0120gar": 5482, "\u0120Social": 5483, "\u0120upgr": 5484, "\u0120shape": 5485, "\u0120speaking": 5486, "ansion": 5487, "ao": 5488, "\u0120Sn": 5489, "\u0120worry": 5490, "\u0120Britain": 5491, "Please": 5492, "roud": 5493, "\u0120hun": 5494, "\u0120introduced": 5495, "\u0120diet": 5496, "Ind": 5497, "\u0120Second": 5498, "\u0120functions": 5499, "uts": 5500, "\u0120Each": 5501, "\u0120Jeff": 5502, "\u0120stress": 5503, "\u0120accounts": 5504, "\u0120guarant": 5505, "\u0120Ann": 5506, "edia": 5507, "\u0120honest": 5508, "\u0120tree": 5509, "\u0120African": 5510, "\u0120Bush": 5511, "},": 5512, "\u0120sch": 5513, "\u0120Only": 5514, "\u0120fif": 5515, "igan": 5516, "\u0120exercise": 5517, "\u0120Exp": 5518, "\u0120scientists": 5519, "\u0120legislation": 5520, "\u0120Work": 5521, "\u0120Spr": 5522, "\u00c3\u0124": 5523, "\u0120Human": 5524, "\u0120\u00e8": 5525, "\u0120survey": 5526, "\u0120rich": 5527, "rip": 5528, "\u0120maintain": 5529, "\u0120flo": 5530, "\u0120leadership": 5531, "stream": 5532, "\u0120Islamic": 5533, "\u012001": 5534, "\u0120College": 5535, "\u0120magic": 5536, "\u0120Prime": 5537, "\u0120figures": 5538, "2017": 5539, "inder": 5540, "xual": 5541, "\u0120Dead": 5542, "\u0120absolutely": 5543, "\u0120fourth": 5544, "\u0120presented": 5545, "respond": 5546, "rible": 5547, "\u0120alcohol": 5548, "ato": 5549, "\u0120DE": 5550, "porary": 5551, "\u0120grab": 5552, "\u0120vari": 5553, "\u0120quant": 5554, "\u0120Photo": 5555, "\u0120plus": 5556, "rick": 5557, "arks": 5558, "\u0120alternative": 5559, "\u0120pil": 5560, "\u0120approx": 5561, "that": 5562, "\u0120objects": 5563, "\u0120Ro": 5564, "\u0120Android": 5565, "\u0120significantly": 5566, "\u0120Road": 5567, "kay": 5568, "Read": 5569, "avor": 5570, "\u0120acknow": 5571, "\u0120HD": 5572, "\u0120Sing": 5573, "Or": 5574, "\u0120Mont": 5575, "\u0120uns": 5576, "prof": 5577, "\u0120negoti": 5578, "\u0120Arch": 5579, "iki": 5580, "\u0120television": 5581, "\u0120Jewish": 5582, "\u0120committee": 5583, "\u0120motor": 5584, "\u0120appearance": 5585, "\u0120sitting": 5586, "\u0120strike": 5587, "\u0120Down": 5588, "comp": 5589, "\u0120Hist": 5590, "\u0120fold": 5591, "acement": 5592, "\u0120Louis": 5593, "\u0120belong": 5594, "\u0120\u00e2\u0122\u00a2": 5595, "\u0120mort": 5596, "\u0120prepared": 5597, "\u012064": 5598, "\u0120Master": 5599, "\u0120indeed": 5600, "\u0120Den": 5601, "\u0120rent": 5602, "TA": 5603, "ourney": 5604, "arc": 5605, "Su": 5606, "97": 5607, "\u0120advice": 5608, "\u0120changing": 5609, "\u0120listed": 5610, "\u0120launched": 5611, "isation": 5612, "\u0120Peter": 5613, "ishes": 5614, "\u0120lived": 5615, "\u0120Mel": 5616, "\u0120Supreme": 5617, "\u0120Federal": 5618, "\u0120);": 5619, "ructure": 5620, "\u0120sets": 5621, "\u0120philos": 5622, "uous": 5623, "\u0120\u00c2\u0142": 5624, "\u0120applied": 5625, "\u0120NOT": 5626, "\u0120housing": 5627, "\u0120Mount": 5628, "\u0120odd": 5629, "\u0120sust": 5630, "DA": 5631, "fficient": 5632, "\u0120?": 5633, "olved": 5634, "\u0120powers": 5635, "\u0120thr": 5636, "\u0120remaining": 5637, "\u0120Water": 5638, "LC": 5639, "\u0120causes": 5640, "\u00e3\u0123\u00ae": 5641, "\u0120manner": 5642, "ads": 5643, "\u0120suggests": 5644, "\u0120ends": 5645, "standing": 5646, "fig": 5647, "\u0120Dun": 5648, "idth": 5649, "\u0120gay": 5650, "\u0120termin": 5651, "\u0120Angeles": 5652, "MS": 5653, "\u0120scientific": 5654, "\u0120coal": 5655, "apers": 5656, "bar": 5657, "\u0120Thomas": 5658, "\u0120sym": 5659, "\u0120Run": 5660, "this": 5661, "PC": 5662, "igrants": 5663, "\u0120minute": 5664, "\u0120District": 5665, "cellent": 5666, "\u0120leaves": 5667, "\u0120completed": 5668, "amin": 5669, "\u0120focused": 5670, "\u0120monitor": 5671, "\u0120vehicles": 5672, "MA": 5673, "\u0120Mass": 5674, "\u0120Grand": 5675, "\u0120affected": 5676, "itutional": 5677, "\u0120construct": 5678, "\u0120follows": 5679, "\u0120ton": 5680, "reens": 5681, "\u0120homes": 5682, "\u0120Ext": 5683, "\u0120Level": 5684, "rast": 5685, "\u0120Ir": 5686, "\u0120elim": 5687, "\u0120largely": 5688, "\u0120Joe": 5689, "\u0120votes": 5690, "alls": 5691, "\u0120businesses": 5692, "\u0120Foundation": 5693, "\u0120Central": 5694, "\u0120yards": 5695, "\u0120materials": 5696, "ulner": 5697, "\u0120guide": 5698, "\u0120closer": 5699, "ums": 5700, "\u0120sports": 5701, "eder": 5702, "Just": 5703, "\u0120taxes": 5704, "84": 5705, "\u0120Old": 5706, "\u0120decade": 5707, "ola": 5708, "\u0120vir": 5709, "\u0120dropped": 5710, "\u0120delay": 5711, "itect": 5712, "\u0120secure": 5713, "stein": 5714, "level": 5715, "\u0120treated": 5716, "\u0120filed": 5717, "aine": 5718, "\u0120van": 5719, "\u0120mir": 5720, "\u0120column": 5721, "icted": 5722, "eper": 5723, "\u0120rot": 5724, "\u0120consult": 5725, "\u0120entry": 5726, "\u0120marijuana": 5727, "\u0120Dou": 5728, "\u0120apparently": 5729, "oking": 5730, "clusive": 5731, "\u0120increases": 5732, "ano": 5733, "\u0120specifically": 5734, "\u0120tele": 5735, "ensions": 5736, "\u0120religion": 5737, "abilities": 5738, "\u0120frame": 5739, "\u0120Note": 5740, "\u0120Lee": 5741, "\u0120helping": 5742, "\u0120edge": 5743, "oston": 5744, "\u0120organizations": 5745, "\u00c3\u0125": 5746, "\u0120Both": 5747, "hips": 5748, "\u0120bigger": 5749, "\u0120boost": 5750, "\u0120Stand": 5751, "\u0120row": 5752, "uls": 5753, "abase": 5754, "\u0120rid": 5755, "Let": 5756, "aren": 5757, "rave": 5758, "\u0120stret": 5759, "PD": 5760, "\u0120vision": 5761, "\u0120wearing": 5762, "\u0120appreci": 5763, "\u0120award": 5764, "\u0120Use": 5765, "\u0120factor": 5766, "war": 5767, "ulations": 5768, ")(": 5769, "\u0120god": 5770, "\u0120territ": 5771, "\u0120param": 5772, "asts": 5773, "87": 5774, "\u0120enemies": 5775, "\u0120Games": 5776, "FF": 5777, "\u0120accident": 5778, "Well": 5779, "\u0120Martin": 5780, "TER": 5781, "\u0120ath": 5782, "\u0120Hell": 5783, "\u0120forg": 5784, "\u0120veter": 5785, "\u0120Medic": 5786, "free": 5787, "\u0120stars": 5788, "\u0120expensive": 5789, "\u0120acad": 5790, "rawn": 5791, "\u0120Whe": 5792, "\u0120lock": 5793, "\u0120format": 5794, "\u0120soldiers": 5795, "sm": 5796, "\u0120agent": 5797, "\u0120responsibility": 5798, "ora": 5799, "\u0120Science": 5800, "\u0120rapid": 5801, "\u0120tough": 5802, "\u0120Jesus": 5803, "\u0120believes": 5804, "ML": 5805, "\u0120wear": 5806, "lete": 5807, "\u00c3\u0125\u00c3\u0124": 5808, "\u0120Dri": 5809, "\u0120commission": 5810, "\u0120Bob": 5811, "Oh": 5812, "aped": 5813, "\u0120warm": 5814, "\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124": 5815, "\u01202003": 5816, "ortion": 5817, "\u0120hasn": 5818, "uster": 5819, "\u0120univers": 5820, "\u0120Ill": 5821, "\u0120king": 5822, "ologies": 5823, "94": 5824, "\u0120Tem": 5825, "\u0120Mos": 5826, "\u0120patient": 5827, "\u0120Mexico": 5828, "cean": 5829, "\u0120Death": 5830, "\u0120Sanders": 5831, "you": 5832, "\u0120Cast": 5833, "\u0120Company": 5834, "pty": 5835, "\u0120happening": 5836, "FP": 5837, "\u0120Battle": 5838, "\u0120bought": 5839, "Am": 5840, "Mod": 5841, "Us": 5842, "uters": 5843, "\u0120Cre": 5844, "\u0120Those": 5845, "\u012044": 5846, "iser": 5847, "\u0120soul": 5848, "\u0120Top": 5849, "\u0120Harry": 5850, "\u0120Aw": 5851, "\u0120seat": 5852, "ffee": 5853, "\u0120revolution": 5854, "\u0120(\"": 5855, "\u0120During": 5856, "ette": 5857, "\u0120ring": 5858, "\u0120offensive": 5859, "\u0120returns": 5860, "\u0120videos": 5861, "\u0120discl": 5862, "\u0120famous": 5863, "enced": 5864, "\u0120Sign": 5865, "\u0120River": 5866, "\u0120300": 5867, "PM": 5868, "\u0120Bus": 5869, "\u0120CH": 5870, "\u0120candidates": 5871, "arden": 5872, "\u0120percentage": 5873, "\u0120visual": 5874, "\u0120thank": 5875, "\u0120trouble": 5876, "nergy": 5877, "\u01202001": 5878, "\u0120prove": 5879, "ashion": 5880, "\u0120enh": 5881, "\u0120Long": 5882, "UM": 5883, "\u0120connected": 5884, "\u0120possibility": 5885, "Over": 5886, "\u0120expert": 5887, "\u0120library": 5888, "arts": 5889, "\u0120Director": 5890, "\u0120fellow": 5891, "92": 5892, "irty": 5893, "\u0120dry": 5894, "\u0120signs": 5895, "\u0120Love": 5896, "\u0120quiet": 5897, "foot": 5898, "\u0120pure": 5899, "\u0120Hun": 5900, "\u0120filled": 5901, "phas": 5902, "\u0120Elect": 5903, "endment": 5904, "\u0120Expl": 5905, "\u0120unable": 5906, "ns": 5907, "mo": 5908, "\u0120vast": 5909, "obe": 5910, "\u0120identify": 5911, "apping": 5912, "\u0120Carolina": 5913, "gress": 5914, "\u0120prote": 5915, "\u0120fish": 5916, "\u0120circumstances": 5917, "razy": 5918, "\u0120Phot": 5919, "\u0120bodies": 5920, "\u0120Mur": 5921, "\u0120developing": 5922, "\u0120AR": 5923, "\u0120experienced": 5924, "\u0120substant": 5925, "\u0120Board": 5926, "esome": 5927, "\u0120domestic": 5928, "\u0120combined": 5929, "\u0120Put": 5930, "\u0120chemical": 5931, "\u0120Child": 5932, "\u0120pool": 5933, "\u0120Cy": 5934, "\u0120egg": 5935, "cons": 5936, "sters": 5937, "\u0120hurt": 5938, "\u0120markets": 5939, "\u0120conservative": 5940, "\u0120supporters": 5941, "\u0120agencies": 5942, "idel": 5943, "Ob": 5944, "urb": 5945, "\u012043": 5946, "\u0120Defense": 5947, "ye": 5948, "\u0120Ap": 5949, "dule": 5950, "\u0120temperature": 5951, "\u0120conducted": 5952, "\u0120Chief": 5953, "\u0120pulled": 5954, "\u0120fol": 5955, "Last": 5956, "onto": 5957, "osis": 5958, "VER": 5959, "Des": 5960, "\u0120Pan": 5961, "First": 5962, "\u0120advance": 5963, "\u0120license": 5964, "rors": 5965, "\u0120Jon": 5966, "\u0120imagine": 5967, "\u0120hell": 5968, "\u0120fixed": 5969, "\u0120incor": 5970, "osite": 5971, "\u0120Log": 5972, "icken": 5973, "]:": 5974, "\u0120surprise": 5975, "hab": 5976, "\u0120craft": 5977, "olt": 5978, "\u0120Jul": 5979, "\u0120dial": 5980, "\u0120relevant": 5981, "\u0120entered": 5982, "\u0120leads": 5983, "\u0120AD": 5984, "\u0120Clean": 5985, "\u0120pictures": 5986, "essor": 5987, "\u0120alt": 5988, "\u0120paying": 5989, "Per": 5990, "\u0120Market": 5991, "\u0120updates": 5992, "amily": 5993, "\u0120Type": 5994, "\u0120Home": 5995, "\u012055": 5996, "sembly": 5997, "rome": 5998, "83": 5999, "\u0120greatest": 6000, "\u0120height": 6001, "\u0120heav": 6002, "aints": 6003, "\u0120listen": 6004, "aser": 6005, "\u0120SH": 6006, "\u0120capable": 6007, "acle": 6008, "\u0120perspect": 6009, "inating": 6010, "\u0120offering": 6011, "rypt": 6012, "\u0120Develop": 6013, "abin": 6014, "rc": 6015, "\u0120bright": 6016, "alty": 6017, "arrow": 6018, "\u0120suppl": 6019, "inding": 6020, "acked": 6021, "gypt": 6022, "\u0120Another": 6023, "pg": 6024, "\u0120Virginia": 6025, "\u0120Lu": 6026, "\u0120planned": 6027, "\u0120pit": 6028, "\u0120sweet": 6029, "Type": 6030, "\u0120Di": 6031, "\u0120typically": 6032, "\u0120Francisco": 6033, "\u0120prospect": 6034, "\u0120Dan": 6035, "\u0120teen": 6036, "rees": 6037, "\u0120sched": 6038, "\u0120hol": 6039, "\u0120scr": 6040, "\u0120lots": 6041, "life": 6042, "\u0120newsp": 6043, "\u0120forget": 6044, "\u0120None": 6045, "\u0120Middle": 6046, "\u0120Ryan": 6047, "edd": 6048, "\u0120severe": 6049, "\u0120suit": 6050, "ller": 6051, "93": 6052, "\u0120correspond": 6053, "\u0120explos": 6054, "uations": 6055, "\u0120flag": 6056, "game": 6057, "rid": 6058, "\u0120prin": 6059, "\u0120Data": 6060, "\u0120deploy": 6061, "\u0120Enter": 6062, "suit": 6063, "ghan": 6064, "\u0120Men": 6065, "\u0120thoughts": 6066, "\u0120matters": 6067, "\u0120adapt": 6068, "\u0120Ari": 6069, "\u0120fill": 6070, "\u0120forth": 6071, "\u0120sam": 6072, "\u012041": 6073, "\u0120payment": 6074, "\u0120Hor": 6075, "\u0120spring": 6076, "duc": 6077, "\u0120losing": 6078, "\u0120bringing": 6079, "FO": 6080, "ala": 6081, "\u0120distribution": 6082, "hered": 6083, "bour": 6084, "\u0120Israeli": 6085, "oma": 6086, "\u0120combination": 6087, "\u0120plenty": 6088, "VE": 6089, "Can": 6090, "\u0120Haw": 6091, "\u0120perman": 6092, "\u0120Special": 6093, "\u0120tow": 6094, "\u0120seeking": 6095, "\u0120examples": 6096, "\u0120classes": 6097, "cr": 6098, "\u0120beer": 6099, "\u0120moves": 6100, "\u0120IP": 6101, "\u0120Kn": 6102, "\u0120panel": 6103, "Even": 6104, "\u0120properly": 6105, "\u0120ris": 6106, "\u0120plug": 6107, "\u0120estimated": 6108, "Every": 6109, "\u0120defensive": 6110, "agraph": 6111, "\u0120pregn": 6112, "\u0120instit": 6113, "\u0120Vict": 6114, "\u0120volume": 6115, "\u0120positions": 6116, "\u0120links": 6117, "\u0120Program": 6118, "\u0120Week": 6119, "agues": 6120, "\u0120transform": 6121, "ker": 6122, "\u0120CEO": 6123, "\u0120cas": 6124, "\u0120opponent": 6125, "\u0120tweet": 6126, "\u0120Code": 6127, "\u0120shop": 6128, "\u0120fly": 6129, "\u0120talks": 6130, "\u0120bag": 6131, "Phone": 6132, "\u0120aid": 6133, "\u0120plants": 6134, "\u012065": 6135, "\u0120attorney": 6136, "arters": 6137, "quest": 6138, "\u0120Magic": 6139, "\u0120begins": 6140, "\u0120myster": 6141, "\u0120environmental": 6142, "\u0120storage": 6143, "NN": 6144, "\u0120marg": 6145, "\u0120ske": 6146, "\u0120metal": 6147, "elly": 6148, "\u0120ordered": 6149, "\u0120remained": 6150, "\u0120loved": 6151, "\u0120prompt": 6152, "\u0120updated": 6153, "\u0120experts": 6154, "\u0120walking": 6155, "\u0120ancient": 6156, "\u0120performed": 6157, "ATE": 6158, "\u0120neither": 6159, "iency": 6160, "\u0120manufacture": 6161, "\u0120Pak": 6162, "\u0120selected": 6163, "\u0120mine": 6164, "\u0120ultimately": 6165, "\u0120explan": 6166, "\u0120label": 6167, "\u0120Services": 6168, "ributed": 6169, "Trump": 6170, "\u0120syn": 6171, "\u0120Ult": 6172, "SC": 6173, "\u0120meat": 6174, "\u0120giant": 6175, "\u0120Wars": 6176, "\u0120ON": 6177, "\u0120adm": 6178, "\u0120interpret": 6179, "\u0120evening": 6180, "\u0120evil": 6181, "\u0120Boston": 6182, "\u0120Wild": 6183, "\u0120\u00c3": 6184, "\u0120Bitcoin": 6185, "\u0120Amazon": 6186, "Dr": 6187, "\u0120Information": 6188, "\u0120obviously": 6189, "\u0120advanced": 6190, "Photo": 6191, "olar": 6192, "\u0120weather": 6193, "\u0120symbol": 6194, "\u0120sole": 6195, "\u0120potentially": 6196, "oster": 6197, "\u0120originally": 6198, "mun": 6199, "300": 6200, "aze": 6201, "essions": 6202, "\u0120deck": 6203, "\u0120stood": 6204, "\u0120youth": 6205, "\u0120Bern": 6206, "Rep": 6207, "\u0120Test": 6208, "\u0120basically": 6209, "otic": 6210, "\u0120involve": 6211, "olit": 6212, "lyn": 6213, "See": 6214, "\u0120aircraft": 6215, "\u0120confirm": 6216, "EW": 6217, "\u0120messages": 6218, "\u0120Richard": 6219, "\u0120kit": 6220, "\u0120prohib": 6221, "\u0120vulner": 6222, "isters": 6223, "\u0120existence": 6224, "\u0120turning": 6225, "\u0120SP": 6226, "\u0120desire": 6227, "\u0120flat": 6228, "\u0120ment": 6229, "season": 6230, "anges": 6231, "\u0120neighborhood": 6232, "\u0120Lake": 6233, "ATION": 6234, "\u0120pointed": 6235, "bur": 6236, "\u0120innov": 6237, "ucks": 6238, "UL": 6239, "\u0120professor": 6240, "\u0120expressed": 6241, "AB": 6242, "icious": 6243, "\u01202002": 6244, "\u0120Dev": 6245, "\u0120session": 6246, "\u0120bare": 6247, "sen": 6248, "\u0120diss": 6249, "\u0120Cath": 6250, "\u0120Pass": 6251, "\u0120Point": 6252, "\u0120doctor": 6253, "orrow": 6254, "ailed": 6255, "\u0120Rub": 6256, "\u0120DC": 6257, "\u0120Charl": 6258, "person": 6259, "\u0120writer": 6260, "ighters": 6261, "ureau": 6262, "\u0120oblig": 6263, "\u0120recorded": 6264, "\u0120broke": 6265, "\u0120orders": 6266, "ilty": 6267, "\u0120motion": 6268, "inity": 6269, "law": 6270, "adium": 6271, "\u0120immigration": 6272, "\u0120contrast": 6273, "\u0120batt": 6274, "\u0120excellent": 6275, "\u0120technical": 6276, "ami": 6277, "\u0120tun": 6278, "\u0120cloud": 6279, "\u0120Year": 6280, "geon": 6281, "\u0120creation": 6282, "\u0120strange": 6283, "\u0120auth": 6284, "\u0120fort": 6285, "born": 6286, "\u0120extent": 6287, "\u0120Today": 6288, "\u0120Club": 6289, "\u0120rain": 6290, "\u0120sample": 6291, "\u0120accepted": 6292, "\u0120tact": 6293, "\u0120fired": 6294, "\u0120Son": 6295, "\u0120stands": 6296, "\u0120boot": 6297, "\u012047": 6298, "\u0120statements": 6299, "\u0120versions": 6300, "\u0120selling": 6301, "ounded": 6302, "\u01201990": 6303, "\u0120weren": 6304, "\u0120Watch": 6305, "\u0120experiment": 6306, "Post": 6307, "\u0120retail": 6308, "uled": 6309, "Inst": 6310, "unte": 6311, "\u00e3\u0125\u00bc": 6312, "\u0120depart": 6313, "\u0120bond": 6314, "ivery": 6315, "ompl": 6316, "\u0120reaction": 6317, "\u0120Syrian": 6318, "\u0120Pac": 6319, "apped": 6320, "aniel": 6321, "DP": 6322, "\u0120resolution": 6323, "\u0120react": 6324, "\u0120approved": 6325, "onom": 6326, "mond": 6327, "\u0120Offic": 6328, "---": 6329, "\u0120replace": 6330, "\u0120tack": 6331, "\u0120sport": 6332, "\u0120chain": 6333, "\u0120emergency": 6334, "rad": 6335, "\u0120Palestin": 6336, "\u012046": 6337, "\u0120automatically": 6338, "\u0120route": 6339, "\u0120pal": 6340, "\u0120banks": 6341, "\u0120Paris": 6342, "\u0120Media": 6343, "road": 6344, "icing": 6345, "ixt": 6346, "isted": 6347, "\u0120grew": 6348, "\u0120coord": 6349, "\u0120Where": 6350, "omin": 6351, "\u0120subs": 6352, "\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd": 6353, "\u0120\u00c2\u00b1": 6354, "\u0120corporate": 6355, "\u0120selection": 6356, "noon": 6357, "\u0120Report": 6358, "cs": 6359, "cluding": 6360, "orders": 6361, "anche": 6362, "\u0120Its": 6363, "\u0120slowly": 6364, "\u0120Egypt": 6365, "\u0120Acc": 6366, "\u0120colle": 6367, "iques": 6368, "EX": 6369, "\u0120attempts": 6370, "url": 6371, "\u0120Cross": 6372, "\u0120findings": 6373, "\u0120SC": 6374, "\u0120OR": 6375, "\u0120index": 6376, "ensity": 6377, "\u0120Way": 6378, "\u0120Land": 6379, "\u0120shock": 6380, "dis": 6381, "\u0120dynam": 6382, "\u0120cart": 6383, "mosp": 6384, "Since": 6385, "iest": 6386, "\u0120Boy": 6387, "\u0120storm": 6388, "\u0120Contin": 6389, "2013": 6390, "hew": 6391, "ilit": 6392, "\u0120essential": 6393, "iquid": 6394, "Other": 6395, "ivered": 6396, "\u0120reasonable": 6397, "Act": 6398, "\u0120subsequ": 6399, "\u0120Pack": 6400, "\u0120Fort": 6401, "\u0120considering": 6402, "\u0120university": 6403, "log": 6404, "\u0120married": 6405, "\u0120illust": 6406, "\u0120True": 6407, "\u00a3\u0131": 6408, "\u0120numerous": 6409, "rastructure": 6410, "\u0120seriously": 6411, "\u0120referred": 6412, "ua": 6413, "\u0120consistent": 6414, "onna": 6415, "\u0120Real": 6416, "ruption": 6417, "ciples": 6418, "\u0120facts": 6419, "91": 6420, "otes": 6421, "erg": 6422, "Then": 6423, "\u0120accompl": 6424, "Note": 6425, "\u0120revenue": 6426, "\u0120passing": 6427, "\u0120mal": 6428, "een": 6429, "\u0120Yet": 6430, "\u0120gather": 6431, "terday": 6432, "ework": 6433, "\u0120Author": 6434, "Pe": 6435, "\u0120optim": 6436, "\u0120rub": 6437, "\u0120\u00e8\u00a3\u0131": 6438, "\u0120unknown": 6439, "stone": 6440, "\u0120union": 6441, "olve": 6442, "\u0120opportunities": 6443, "\u0120browser": 6444, "\u0120Wal": 6445, "\u0120Cost": 6446, "\u0120reporting": 6447, "sts": 6448, "pet": 6449, "\u0120sand": 6450, "\u0120suddenly": 6451, "\u0120surprising": 6452, "\u0120VR": 6453, "\u0120somewhat": 6454, "\u0120Bas": 6455, "ulture": 6456, "izz": 6457, "\u0120CD": 6458, "\u0120challenges": 6459, "\u0120settings": 6460, "\u0120experiences": 6461, "\u0120Full": 6462, "\u0120cann": 6463, "\u0120receiving": 6464, "EST": 6465, "\u0120joint": 6466, "\u0120cultural": 6467, "\u0120ast": 6468, "82": 6469, "astern": 6470, "ceived": 6471, "\u0120Cru": 6472, "\u0120bull": 6473, "pired": 6474, "amm": 6475, "\u0120facing": 6476, "power": 6477, "\u0120boss": 6478, "\u0120Hol": 6479, "\u0120instr": 6480, "\u0120increasingly": 6481, "\u0120shift": 6482, "\u0120streets": 6483, "\u0120Williams": 6484, "abb": 6485, "\u0120lie": 6486, "\u0120laugh": 6487, "\u0120Ca": 6488, "PL": 6489, "\u0120adults": 6490, "\u0120customer": 6491, "\u0120obtained": 6492, "\u0120supporting": 6493, "html": 6494, "fire": 6495, "\u0120detailed": 6496, "\u0120picked": 6497, "\u0120Right": 6498, "lder": 6499, "EE": 6500, "stood": 6501, "\u0120Kim": 6502, "\u0120wire": 6503, "\u0120sight": 6504, "\u0120developers": 6505, "\u0120persons": 6506, "\u0120sad": 6507, "\u0120cup": 6508, "\u0120warning": 6509, "\u0120boys": 6510, "long": 6511, "\u0120bird": 6512, "fo": 6513, "\u0120wal": 6514, "\u0120observed": 6515, "\u0120zone": 6516, "iveness": 6517, "\u0120channel": 6518, "cript": 6519, "\u0120refused": 6520, "\u0120Again": 6521, "\u0120suc": 6522, "\u0120spokesman": 6523, "\u0120Ref": 6524, "rite": 6525, "ouston": 6526, "\u00e3\u0125\u00b3": 6527, "\u0120Sher": 6528, "\u0120acts": 6529, "\u0120Name": 6530, "\u0120struggle": 6531, "arry": 6532, "ometimes": 6533, "\u0120discrim": 6534, "HT": 6535, "\u0120category": 6536, "\u0120realize": 6537, "\u0120employee": 6538, "\u0120Afghan": 6539, "enger": 6540, "\u0120guns": 6541, "\u0120Steve": 6542, "\u0120Mot": 6543, "\u0120Ol": 6544, "oked": 6545, "\u0120thick": 6546, "\u0120fairly": 6547, "illy": 6548, "\u0120surve": 6549, "\u0120Mat": 6550, "weight": 6551, "\u00e2\u0136": 6552, "\u0120troops": 6553, "\u0120agents": 6554, "\u0120battery": 6555, "\u0120motiv": 6556, "\u00c3\u00a1": 6557, "Sec": 6558, "den": 6559, "overy": 6560, "LS": 6561, "\u0120flu": 6562, "\u0120confident": 6563, "\u0120Oper": 6564, "\u0120empty": 6565, "\u0120phen": 6566, "\u0120sector": 6567, "\u0120excited": 6568, "\u0120remote": 6569, "aph": 6570, "oen": 6571, "\u0120destroyed": 6572, "\u0120moral": 6573, "\u0120HP": 6574, "\u0120Ron": 6575, "\u0120dress": 6576, "\u0120Bat": 6577, "\u0120lit": 6578, "\u0120MS": 6579, "\u0120af": 6580, "HL": 6581, "rum": 6582, "isms": 6583, "\u0120shouldn": 6584, "\u0120sympt": 6585, "\u0120Toronto": 6586, "hetic": 6587, "\u0120carbon": 6588, "\u0120installed": 6589, "\u0120violent": 6590, "\u0120solar": 6591, "ja": 6592, "\u0120practices": 6593, "\u0120ride": 6594, "\u0120Penn": 6595, "\u0120improved": 6596, "\u0120audio": 6597, "\u0120behavi": 6598, "\u0120PS": 6599, "\u0120eating": 6600, "Data": 6601, "\u0120Review": 6602, "pass": 6603, "claim": 6604, "uated": 6605, "angers": 6606, "chen": 6607, "\u0120properties": 6608, "\u0120anywhere": 6609, "Another": 6610, "\u0120blow": 6611, "\u0120Jackson": 6612, "\u0120proud": 6613, "\u0120plane": 6614, "lines": 6615, "\u0120square": 6616, "\u0120proof": 6617, "ansas": 6618, "\u0120talked": 6619, "makers": 6620, "\u0120sister": 6621, "\u0120holds": 6622, "\u0120resident": 6623, "\u0120==": 6624, "\u0120resistance": 6625, "\u0120split": 6626, "\u0120prosecut": 6627, "\u0120confidence": 6628, "resents": 6629, "\u0120cuts": 6630, "\u0120exception": 6631, "\u0120zero": 6632, "Getty": 6633, "\u0120copyright": 6634, "\u0120totally": 6635, "ormal": 6636, "ifications": 6637, "\u0120Australian": 6638, "\u0120sick": 6639, "\u0120150": 6640, "\u0120household": 6641, "\u0120fees": 6642, "\u0120drivers": 6643, "ogen": 6644, "\u0120NY": 6645, "\u0120necessarily": 6646, "\u0120regulations": 6647, "earing": 6648, "sl": 6649, "\u0120perspective": 6650, "care": 6651, "icial": 6652, "His": 6653, "\u0120escape": 6654, "\u0120surprised": 6655, "\u0120Van": 6656, "urrent": 6657, "\u0120vac": 6658, "81": 6659, "\u0120Thus": 6660, "\u0120emphas": 6661, "\u0120Champions": 6662, "\u0120Ice": 6663, "\u0120narr": 6664, "\u0120heads": 6665, "\u0120causing": 6666, "bel": 6667, "fortunately": 6668, "\u0120Ma": 6669, "\u0120targets": 6670, "cipl": 6671, "\u0120afternoon": 6672, "\u0120adds": 6673, "\u0120Maybe": 6674, "\u0120Four": 6675, "essed": 6676, "plete": 6677, "\u0120usual": 6678, "cho": 6679, "ingu": 6680, "\u0120withd": 6681, "\u0120Energy": 6682, "\u0120Econom": 6683, "OO": 6684, "\u0120articles": 6685, "\u0120injured": 6686, "\u0120manage": 6687, "\u0120explains": 6688, "\u0120diagn": 6689, "Rec": 6690, "atures": 6691, "\u0120linked": 6692, "\u0120discussed": 6693, "\u0120explo": 6694, "\u0120occasion": 6695, "athan": 6696, "\u0120opposite": 6697, "\u0120faces": 6698, "\u0120denied": 6699, "\u0120Knight": 6700, "\u0120nut": 6701, "\u0120approximately": 6702, "\u0120disappoint": 6703, "onymous": 6704, "\u0120Best": 6705, "\u0120Lo": 6706, "\u0120Hy": 6707, "\u0120Aff": 6708, "\u0120voting": 6709, "anwhile": 6710, "\u0120III": 6711, "\u0120institutions": 6712, "agram": 6713, "\u0120Daily": 6714, "\u0120drag": 6715, "\u0120nearby": 6716, "\u0120guilty": 6717, "\u0120conver": 6718, "Pre": 6719, "ship": 6720, "\u0120reward": 6721, "\u0120philosoph": 6722, "\u0120SS": 6723, "ugh": 6724, "\u0120apps": 6725, "friend": 6726, "\u0120upper": 6727, "\u0120advert": 6728, "\u0120snow": 6729, "\u0120frust": 6730, "\u0120ourselves": 6731, "Fr": 6732, "\u0120Die": 6733, "ampion": 6734, "\u0120dismiss": 6735, "\u0120cere": 6736, "\u0120signal": 6737, "from": 6738, "\u0120).": 6739, "\u012052": 6740, "\u0120crimes": 6741, "itors": 6742, "estival": 6743, "useum": 6744, "\u0120council": 6745, "\u0120Saud": 6746, "May": 6747, "\u0120Gun": 6748, "ician": 6749, "ether": 6750, "\u0120sufficient": 6751, "\u0120Hen": 6752, "sole": 6753, "\u0120historical": 6754, "\u0120Far": 6755, "\u0120Turn": 6756, "\u0120pin": 6757, "\u0120succeed": 6758, "mat": 6759, "lymp": 6760, "\u0120tradition": 6761, "\u0120Ok": 6762, "\u0120cro": 6763, "\u0120description": 6764, "alle": 6765, "\u0120sky": 6766, "Te": 6767, "\u0120widely": 6768, "\u0120wave": 6769, "\u0120definition": 6770, "\u0120Jews": 6771, "\u0120cycle": 6772, "\u0120refere": 6773, "\u0120brings": 6774, "usal": 6775, "\u0120alive": 6776, "\u0120frequently": 6777, "\u0120intention": 6778, "\u0120Control": 6779, "lv": 6780, "ystem": 6781, "\u0120privacy": 6782, "gent": 6783, "rence": 6784, "\u0120Quest": 6785, "\u0120Christmas": 6786, "\u0120rail": 6787, "\u0120cooper": 6788, "\u0120tested": 6789, "\u0120Capt": 6790, "asks": 6791, "\u0120comfortable": 6792, "\u0120delivered": 6793, "scape": 6794, "\u0120depth": 6795, "\u0120GOP": 6796, "\u0120writes": 6797, "\u0120assets": 6798, "\u0120sav": 6799, "iments": 6800, "\u0120transition": 6801, "\u0120artist": 6802, "\u0120Look": 6803, "\u0120lob": 6804, "\u0120components": 6805, "arity": 6806, "\u0120walked": 6807, "\u0120root": 6808, "\u0120participants": 6809, "\u0120noticed": 6810, "\u0120resc": 6811, "\u0120nav": 6812, "\u0120Administ": 6813, "da": 6814, "utral": 6815, "plate": 6816, "\u0120importance": 6817, "\u0120assert": 6818, "iously": 6819, "cription": 6820, "\u0120injuries": 6821, "\u0120Check": 6822, "\u0120registered": 6823, "\u0120intent": 6824, "\u0120missed": 6825, "ographic": 6826, "\u0120sentence": 6827, "ounter": 6828, "\u0120assistance": 6829, "evin": 6830, "\u0120database": 6831, "\u0120buildings": 6832, "\u0120classic": 6833, "\u0120thinks": 6834, "\u0120Ohio": 6835, "Pr": 6836, "ugg": 6837, "\u0120fee": 6838, "pan": 6839, "\u0120effectively": 6840, "\u0120facility": 6841, "\u0120bear": 6842, "\u0120chapter": 6843, "\u0120dogs": 6844, "\u0120Columb": 6845, "\u0120latter": 6846, "itial": 6847, "\u0120admitted": 6848, "TV": 6849, "\u0120Georg": 6850, "\u0120posts": 6851, "\\\\": 6852, "\u0120lawyer": 6853, "\u0120equival": 6854, "\u0120mand": 6855, "\u0120controlled": 6856, "\u0120Walk": 6857, "\u0120Andrew": 6858, "\u0120menu": 6859, "amental": 6860, "\u0120protected": 6861, "va": 6862, "\u0120administr": 6863, "oral": 6864, "\u0120rein": 6865, "\u0120Sar": 6866, "\u0120amounts": 6867, "\u0120native": 6868, "\u0120Moon": 6869, "\u0120represents": 6870, "\u0120abandon": 6871, "\u0120carrying": 6872, "\u0120tank": 6873, "mary": 6874, "\u0120declared": 6875, "Tube": 6876, "\u0120hat": 6877, "\u0120punish": 6878, "ellect": 6879, "mes": 6880, "\u0120universe": 6881, "\u0120Rod": 6882, "phy": 6883, "\u0120infrastructure": 6884, "\u012051": 6885, "\u0120opposed": 6886, "ownt": 6887, "ca": 6888, "\u0120Make": 6889, "\u0120hardware": 6890, "\u0120coffee": 6891, "Rel": 6892, "bal": 6893, "world": 6894, "\u0120Saf": 6895, "\u0120Sea": 6896, "inals": 6897, "\u0120owned": 6898, "\u0120hall": 6899, "ersion": 6900, "\u0120describe": 6901, "\u0120Pot": 6902, "\u0120portion": 6903, "\u0120atmosp": 6904, "\u0120governments": 6905, "\u0120depending": 6906, "\u0120offense": 6907, "\u0120trick": 6908, "awa": 6909, "\u0120Line": 6910, "\u0120Vis": 6911, "\u0120Hard": 6912, "\u0120Orig": 6913, "\u0120Click": 6914, "\u0120desk": 6915, "\u0120Valley": 6916, "\u0120Sov": 6917, "\u0120movies": 6918, "\u0120remark": 6919, "\u0120mail": 6920, "\u0120conscious": 6921, "\u0120ruling": 6922, "\u0120Rights": 6923, "\u0120medic": 6924, "hent": 6925, "\u0120Women": 6926, "><": 6927, "\u0120replaced": 6928, "\u0120Prem": 6929, "\u0120Thanks": 6930, "\u0120renew": 6931, "\u0120Ball": 6932, "iform": 6933, "\u0120shots": 6934, "Comm": 6935, "\u0120armed": 6936, "\u0120constant": 6937, "\u0120taste": 6938, "\u0120realized": 6939, "\u0120buff": 6940, "\u0120mo": 6941, "\u0120efficient": 6942, "Most": 6943, "oration": 6944, "ifies": 6945, "\u0120communication": 6946, "\u0120flood": 6947, "\u0120consequences": 6948, "\u0120anyway": 6949, "igg": 6950, "\u0120GM": 6951, "\u0120Thank": 6952, "\u0120iron": 6953, "\u0120evolution": 6954, "\u0120Cop": 6955, "twitter": 6956, "\u012095": 6957, "\u0120relationships": 6958, "adel": 6959, "\u0120Young": 6960, "\u0120proposal": 6961, "ayers": 6962, "uilding": 6963, "\u0120Hot": 6964, "ORE": 6965, "cos": 6966, "\u0120collabor": 6967, "PG": 6968, "axy": 6969, "\u0120knowing": 6970, "\u0120supports": 6971, "owed": 6972, "\u0120controls": 6973, "\u0120merely": 6974, "umer": 6975, "\u0120athlet": 6976, "\u0120fashion": 6977, "path": 6978, "\u0120gift": 6979, "\u0120era": 6980, "AND": 6981, "\u0120kinds": 6982, "\u0120Korean": 6983, "\u0120legit": 6984, "ulous": 6985, "\u0120essentially": 6986, "\u0120therap": 6987, "nic": 6988, "\u0120suffered": 6989, "\u0120hur": 6990, "\u0120promise": 6991, "\u0120excess": 6992, "\u0120overw": 6993, "\u0120prime": 6994, "\u0120Houston": 6995, "erry": 6996, "\u0120Ms": 6997, "RS": 6998, "2012": 6999, "\u0120stores": 7000, "\u0120Olymp": 7001, "\u0120journey": 7002, "Although": 7003, "Sub": 7004, "\u0120Educ": 7005, "\u0120Chapter": 7006, "\u0120requests": 7007, "\u0120consumers": 7008, "\u0120tiny": 7009, "\u0120isol": 7010, "\u0120Fair": 7011, "ba": 7012, "\u0120YOU": 7013, "\u0120crash": 7014, "celer": 7015, "\u0120emotional": 7016, "\u0120goods": 7017, "\u0120elected": 7018, "\u0120moder": 7019, "\u0120Linux": 7020, "\u0120blocks": 7021, "\u0120island": 7022, "\u0120Society": 7023, "\u0120elections": 7024, "\u0120broadcast": 7025, "\u0120cheap": 7026, "\u0120nations": 7027, "\u0120seasons": 7028, "400": 7029, "\u0120waste": 7030, "\u0120Sat": 7031, "\u0120fields": 7032, "employ": 7033, "\u0120profile": 7034, "\u0120authors": 7035, "ALL": 7036, "\u0120Gra": 7037, "west": 7038, "\u0120Ty": 7039, "\u0120deaths": 7040, "\u0120vacc": 7041, "\u0120formed": 7042, "\u0120du": 7043, "\u0120ongoing": 7044, "\u0120Muslims": 7045, "elf": 7046, "igure": 7047, "\u0120assume": 7048, "\u0120Ukraine": 7049, "water": 7050, "\u0120coast": 7051, "\u0120voted": 7052, "gor": 7053, "\u0120AS": 7054, "\u0120Michigan": 7055, "aza": 7056, "\u0120Arm": 7057, "iro": 7058, "\u0120flex": 7059, "asters": 7060, "''": 7061, "\u0120welcome": 7062, "arl": 7063, "\u0120locations": 7064, "igation": 7065, "\u0120Fil": 7066, "\u0120buying": 7067, "\u0120architect": 7068, "\u0120harder": 7069, "\u0120Cub": 7070, "\u0120interface": 7071, "\u0120restaurant": 7072, "\u0120discover": 7073, "\u0120exceed": 7074, "\u0120favour": 7075, "gery": 7076, "\u0120duty": 7077, "\u0120pitch": 7078, "ador": 7079, "\u0120Mach": 7080, "boy": 7081, "\u0120responded": 7082, "\u0120extended": 7083, "hers": 7084, "Many": 7085, "raid": 7086, "ifer": 7087, "\u0120Ins": 7088, "Ser": 7089, "\u0120medium": 7090, "she": 7091, "\u0120Sports": 7092, "\u0120magazine": 7093, "utation": 7094, "\u0120limits": 7095, "\u0120Gall": 7096, "\u0120external": 7097, "razil": 7098, "\u0120younger": 7099, "tle": 7100, "\u0120remind": 7101, "\u0120CON": 7102, "\u0120immediate": 7103, "\u0120hidden": 7104, "\u0120volunte": 7105, "\u0120simpl": 7106, "odcast": 7107, "\u0120phase": 7108, "dr": 7109, "\u0120plot": 7110, "\u0120exposure": 7111, "RI": 7112, "ograp": 7113, "vin": 7114, "anish": 7115, "\u0120Acad": 7116, "\u0120Engine": 7117, "\u0120expansion": 7118, "\u0120Pay": 7119, "Your": 7120, "\u0120pushed": 7121, "\u0120Ell": 7122, "\u0120Head": 7123, "\u0120marketing": 7124, "\u0120AC": 7125, "ket": 7126, "\u0120hits": 7127, "\u0120gro": 7128, "\u0120Age": 7129, "\u0120Scot": 7130, "][": 7131, "\u0120stim": 7132, "\u0120iPhone": 7133, "\u012a\u0134": 7134, "\u0120narrow": 7135, "\u0120Getty": 7136, "\u0120Turkey": 7137, "\u0120perfectly": 7138, "\u0120enable": 7139, "utch": 7140, "\u0120precise": 7141, "\u0120regime": 7142, "\u0120shif": 7143, "\u0120compens": 7144, "gun": 7145, "div": 7146, "\u0120chosen": 7147, "\u0120Ken": 7148, "Any": 7149, "\u0120trees": 7150, "\u0120recommended": 7151, "\u0120Ren": 7152, "uable": 7153, "\u0120HT": 7154, "Follow": 7155, "EG": 7156, "\u0120Hand": 7157, "\u0120Kenn": 7158, "\u0120arguments": 7159, "\u0120exists": 7160, "\u0120bike": 7161, "\u0120Conserv": 7162, "\u0120breaking": 7163, "\u0120Gar": 7164, "\u0120crazy": 7165, "\u0120virtual": 7166, "aylor": 7167, "ixel": 7168, "\u01201980": 7169, "\u0120permission": 7170, "\u0120Series": 7171, "\u0120consumer": 7172, "\u0120closely": 7173, "called": 7174, "\u012054": 7175, "\u0120hopes": 7176, "\u0120array": 7177, "\u0120Win": 7178, "\u0120Labour": 7179, "\u0120spons": 7180, "\u0120Ire": 7181, "\u0120pow": 7182, "\u0120readers": 7183, "\u0120employment": 7184, "\u0120creature": 7185, "\u0120resulting": 7186, "\u0120accurate": 7187, "\u0120moments": 7188, "\u0120argued": 7189, "\u0120ped": 7190, "During": 7191, "\u012053": 7192, "\u0120Tal": 7193, "\u0120sought": 7194, "\u0120suffering": 7195, "\u0120icon": 7196, "lee": 7197, "\u0120($": 7198, "alian": 7199, "\u00c2\u00b0": 7200, "\u0120pra": 7201, "\u0120bonus": 7202, "(\"": 7203, "ko": 7204, "\u0120acting": 7205, "DE": 7206, "fall": 7207, "\u0120comparison": 7208, "\u0120smooth": 7209, "\u0120NAS": 7210, "upp": 7211, "\u0120Joseph": 7212, "eping": 7213, "\u0120Take": 7214, "\u0120Mid": 7215, "\u0120sending": 7216, "fast": 7217, "\u0120Fall": 7218, "\u0120dealing": 7219, "user": 7220, "\u0120Organ": 7221, "Co": 7222, "\u0120attached": 7223, "\u0120sees": 7224, "%.": 7225, "\u0120typical": 7226, "ART": 7227, "\u0120finds": 7228, "\u0120Asia": 7229, "umin": 7230, "\u0120Core": 7231, "\u0120Ent": 7232, "inent": 7233, "uce": 7234, "\u0120Blood": 7235, "\u0120Never": 7236, "\u0120emails": 7237, "\u0120highlight": 7238, "\u0120confront": 7239, "atus": 7240, "uted": 7241, "\u0120unus": 7242, "\u0120topic": 7243, "\u0120Adam": 7244, "\u0120ble": 7245, "ati": 7246, "\u0120understood": 7247, "Set": 7248, "struct": 7249, "TP": 7250, "\u0120mob": 7251, "aa": 7252, "\u0120Start": 7253, "pected": 7254, "sell": 7255, "\u0120dedicated": 7256, "\u0120CA": 7257, "uan": 7258, "\u0120songs": 7259, "escription": 7260, "\u0120tech": 7261, "\u0120rape": 7262, "\u0120aside": 7263, "\u0120grant": 7264, "\u012056": 7265, "sub": 7266, "\u0120argue": 7267, "\u0120containing": 7268, "\u0120schedule": 7269, "\u0120liberal": 7270, "\u0120publicly": 7271, "\u0120heavily": 7272, "\u0120Ut": 7273, "iner": 7274, "\u0120Section": 7275, "\u0120Care": 7276, "weet": 7277, "ls": 7278, "Dis": 7279, "\u00e2\u0136\u0122": 7280, "\u0120Follow": 7281, "Back": 7282, "\u0120IT": 7283, "\u0120bes": 7284, "ji": 7285, "\u0120Hit": 7286, "ested": 7287, "\u0120everybody": 7288, "\u0120Swed": 7289, "\u0120femin": 7290, "\u0120facilities": 7291, "\u0120conven": 7292, "Comp": 7293, "\u0120OS": 7294, "core": 7295, "\u0120anx": 7296, "\u0120division": 7297, "\u0120Cam": 7298, "\u0120Stan": 7299, "mates": 7300, "\u0120explore": 7301, "plom": 7302, "\u0120shares": 7303, "pload": 7304, "anes": 7305, "\u0120ideal": 7306, "eters": 7307, "\u0120Base": 7308, "\u0120plastic": 7309, "\u0120distinct": 7310, "\u0120Network": 7311, "\u0120Seattle": 7312, "\u0120trading": 7313, "ensus": 7314, "intend": 7315, "\u0120exhib": 7316, "\u0120initially": 7317, "\u0120Food": 7318, "\u0120thousand": 7319, "\u0120Business": 7320, "acter": 7321, "\u0120paragraph": 7322, "\u0120roughly": 7323, "\u0120www": 7324, "\u0120creative": 7325, "\u0120Conf": 7326, "\u0120consumption": 7327, "\u0120films": 7328, "agan": 7329, "\u0120obtain": 7330, "\u0120tall": 7331, "\u0120tor": 7332, "\u0120acknowled": 7333, "\u0120grown": 7334, "alo": 7335, "KE": 7336, "\u0120400": 7337, "enders": 7338, "taining": 7339, "UG": 7340, "\u0120suicide": 7341, "\u0120watched": 7342, "\u0120List": 7343, "ali": 7344, "rehens": 7345, "\u0120surrounding": 7346, "\u0120pip": 7347, "\u0120flying": 7348, "\u0120Java": 7349, "ordan": 7350, "\u0120serving": 7351, "inations": 7352, "post": 7353, "\u0120sho": 7354, "Av": 7355, "\u0120jail": 7356, "zy": 7357, "\u01201999": 7358, "\u0120>": 9609, "orous": 9610, "\u0120firms": 9611, "screen": 9612, "una": 9613, "\u0120embarrass": 9614, "ulse": 9615, "\u0120letting": 9616, "\u0120threw": 9617, "iley": 9618, "\u0120channels": 9619, "lan": 9620, "\u0120Vegas": 9621, "\u0120sear": 9622, "\u0120fantastic": 9623, "arre": 9624, "uzzle": 9625, "\u0120Der": 9626, "Those": 9627, "\u0120swing": 9628, "\u0120sheet": 9629, "index": 9630, "cover": 9631, "ogan": 9632, "\u0120variables": 9633, "\u0120Tech": 9634, "\u0120spoken": 9635, "achel": 9636, "\u0120Da": 9637, "\u0120Mountain": 9638, "\u0120loaded": 9639, "\u0120footage": 9640, "version": 9641, "\u0120unl": 9642, "\u0120Phoenix": 9643, "\u0120throwing": 9644, "\u0120firing": 9645, "\u0120tracking": 9646, "\u0120width": 9647, "\u0120struggling": 9648, "rooms": 9649, "otion": 9650, "\u0120monthly": 9651, "\u0120Server": 9652, "\u0120eggs": 9653, "open": 9654, "MC": 9655, "\u01201993": 9656, "\u0120hired": 9657, "\u0120stayed": 9658, "\u0120Allen": 9659, "\u0120stro": 9660, "\u012098": 9661, "step": 9662, "\u0120Turkish": 9663, "\u0120fabric": 9664, "isting": 9665, "\u0120Dom": 9666, "\u0120dates": 9667, "\u0120pron": 9668, "\u0120basketball": 9669, "\u0120lucky": 9670, "\u0120Arabia": 9671, "\u0120assumed": 9672, "esty": 9673, "\u0120affairs": 9674, "\u0120glad": 9675, "\u0120Indeed": 9676, "\u0120FA": 9677, "\u0120Word": 9678, "\u0120joining": 9679, "ifice": 9680, "pread": 9681, "irts": 9682, "\u0120Select": 9683, "\u0120populations": 9684, "aware": 9685, "\u0120nose": 9686, "\u0120complaints": 9687, "start": 9688, "\u0120scoring": 9689, "Thanks": 9690, "\u0120mining": 9691, "\u0120visitors": 9692, "SH": 9693, "\u0120damaged": 9694, "\u0120characteristics": 9695, "\u0120Pent": 9696, "DC": 9697, "\u012083": 9698, "\u0120Six": 9699, "rates": 9700, "\u0120flags": 9701, "\u0120Brew": 9702, "dog": 9703, "Mark": 9704, "////": 9705, "\u0120execution": 9706, "\u0120joke": 9707, "phones": 9708, "\u0120testimony": 9709, "\u0120obst": 9710, "QL": 9711, "\u0120Cut": 9712, "\u0120studied": 9713, "\u0120Nintendo": 9714, "icket": 9715, "\u0120NBC": 9716, "\u0120lad": 9717, "\u0120Bra": 9718, "\u0120Moh": 9719, "\u0120kernel": 9720, "\u0120overwhelming": 9721, "\u0120aged": 9722, "\u0120applicable": 9723, "\u0120Cond": 9724, "\u0120roads": 9725, "\u0120Block": 9726, "made": 9727, "odge": 9728, "\u0120commands": 9729, "\u0120offices": 9730, "veland": 9731, "\u0120tut": 9732, "\u0120receiver": 9733, "\u0120Fro": 9734, "\u0120shopping": 9735, "\u0120iP": 9736, "\u0120Stre": 9737, "\u0120ABC": 9738, "\u0120entertainment": 9739, "\u0120Bow": 9740, "orted": 9741, "Mc": 9742, "\u0120reads": 9743, "grad": 9744, "\u0120Collect": 9745, "\u0120\u00e2\u012a\u0134": 9746, "\u0120Capital": 9747, "ederation": 9748, "\u0120employer": 9749, "\u0120involvement": 9750, "\u0120anxiety": 9751, "alia": 9752, "\u0120roof": 9753, "\u0120Among": 9754, "\u0120Democrat": 9755, "\u0120stats": 9756, "\u0120Vill": 9757, "\u0120constitutional": 9758, "\u0120referring": 9759, "itty": 9760, "\u0120tackle": 9761, "outube": 9762, "\u0120backed": 9763, "\u0120Hong": 9764, "\u0120Broad": 9765, "\u0120ele": 9766, "\u0120Ott": 9767, "\u01201992": 9768, "hour": 9769, "achusetts": 9770, "Cal": 9771, "\u0120defeated": 9772, "\u012081": 9773, "esp": 9774, "\u0120seemingly": 9775, "was": 9776, "\u0120Jenn": 9777, "\u0120Kurd": 9778, "\u0120gene": 9779, "\u0120discount": 9780, "Ret": 9781, "ECT": 9782, "();": 9783, "\u0120clubs": 9784, "\u0120sid": 9785, "\u0120Marsh": 9786, "Check": 9787, "\u0120pp": 9788, "\u0120Eag": 9789, "idespread": 9790, "\u0120beings": 9791, "FT": 9792, "\u0120introduction": 9793, "\u0120Change": 9794, "ARD": 9795, "\u0120110": 9796, "adows": 9797, "ierce": 9798, "\u0120meal": 9799, "author": 9800, "\u0120Bang": 9801, "lahoma": 9802, "\u0120ranks": 9803, "2011": 9804, "????": 9805, "max": 9806, "\u0120collapse": 9807, "\u0120opens": 9808, "\u0120echo": 9809, "\u0120soph": 9810, "\u0120racist": 9811, "\u0120enormous": 9812, "\u0120waves": 9813, "\u0120tap": 9814, "\u0120comprehensive": 9815, ".--": 9816, "\u0120Roy": 9817, "\u0120farmers": 9818, "Related": 9819, "aired": 9820, "rones": 9821, "\u0120Crim": 9822, "\u0120proportion": 9823, "\u0120designs": 9824, "\u0120negotiations": 9825, "\u0120virtually": 9826, "\u0120Batman": 9827, "\u0120warn": 9828, "\u0120legitimate": 9829, "mate": 9830, "\u0120convention": 9831, ",,": 9832, "netic": 9833, "\u0120SD": 9834, "\u0120consistently": 9835, "\u0120compensation": 9836, "\u0120punishment": 9837, "\u0120ye": 9838, "\u0120tie": 9839, "\u0120Bureau": 9840, "irlf": 9841, "\u0120Bu": 9842, "\u0120Aren": 9843, "\u0120Philipp": 9844, "\u0120knife": 9845, "\u0120memories": 9846, "\u0120Ross": 9847, "\u0120angle": 9848, "\u012086": 9849, "\u0120Thunder": 9850, "\u0120rend": 9851, "\u0120Tour": 9852, "\u0120counts": 9853, "sung": 9854, "\u0120Imp": 9855, "\u0120educational": 9856, "\u0120accessible": 9857, "COM": 9858, "\u0120drew": 9859, "yer": 9860, "Gl": 9861, "amine": 9862, "ORT": 9863, "OB": 9864, "IB": 9865, "master": 9866, "\u0120trials": 9867, "ogy": 9868, "har": 9869, "\u0120Trust": 9870, "\u0120preferred": 9871, "irlfriend": 9872, "\u0120Nev": 9873, "\u0120bin": 9874, "\u0120cow": 9875, "Page": 9876, "\u0120signature": 9877, "\u0120BL": 9878, "700": 9879, "\u0120retired": 9880, "\u0120bytes": 9881, "\u0120neighb": 9882, "\u0120Legend": 9883, "\u0120devast": 9884, "\u0120suspected": 9885, "isons": 9886, "\u0120Pok\u00c3\u00a9mon": 9887, "scale": 9888, "\u0120capabilities": 9889, "\u0120revel": 9890, "\u0120cheese": 9891, "dy": 9892, "igrant": 9893, "\u0120failing": 9894, "bits": 9895, "\u0120Heroes": 9896, "\u0120Ghost": 9897, "\u0120Scient": 9898, "\u0120appointed": 9899, "uri": 9900, "\u0120institution": 9901, "\u0120expanded": 9902, "greg": 9903, "\u0120monitoring": 9904, "\u0120podcast": 9905, "\u0120coalition": 9906, "\u012096": 9907, "Jo": 9908, "\u0120stolen": 9909, "\u0120Sab": 9910, "\u0120stops": 9911, "\u0120holiday": 9912, "\u0120intr": 9913, "Car": 9914, "Black": 9915, "\u0120LGBT": 9916, "\u0120warming": 9917, "\u0120Anderson": 9918, "\u012089": 9919, "\u0120producer": 9920, "Med": 9921, "\u0120accuracy": 9922, "\u0120Marvel": 9923, "izabeth": 9924, "\u0120Patrick": 9925, "mony": 9926, "\u0120mini": 9927, "acles": 9928, "\u0120overt": 9929, "they": 9930, "\u0120membership": 9931, "\u0120Ven": 9932, "\u0120exch": 9933, "\u0120removal": 9934, "\u0120Dave": 9935, "TY": 9936, "mad": 9937, "\u0120Find": 9938, "\u0120adequ": 9939, "\u0120ec": 9940, "\u0120teeth": 9941, "\u0120emotion": 9942, "\u0120perm": 9943, "\u0120solely": 9944, "db": 9945, "\u0120extraord": 9946, "IGHT": 9947, "cal": 9948, "\u0120guidelines": 9949, "\u0120dying": 9950, "\u0120suspended": 9951, "\u0120Premier": 9952, "\u0120Anthony": 9953, "elve": 9954, "\u0120dad": 9955, "\u0120Eth": 9956, "\u0120Football": 9957, "\u0120abandoned": 9958, "\u0120<<": 9959, "\u0120march": 9960, "\u0120horror": 9961, "\u00e2\u0122\u00a6\"": 9962, "\u0120childhood": 9963, "\u0120campaigns": 9964, "\u0120lunch": 9965, "\u0120Albert": 9966, "block": 9967, "\u00e2\u0138\u012a\u00e2\u0138\u012a": 9968, "ounding": 9969, "\u0120bone": 9970, "organ": 9971, "aders": 9972, "\u0120Flash": 9973, "\u0120Drive": 9974, "\u0120tonight": 9975, "\u0120wars": 9976, "\u0120FL": 9977, "\u0120formation": 9978, "const": 9979, "News": 9980, "\u0120compe": 9981, "orious": 9982, "\u0120Staff": 9983, "\u0120discussions": 9984, "\u0120Protection": 9985, "\u0120Jam": 9986, "\u0120criteria": 9987, "\u0120installation": 9988, "\u0120accomplish": 9989, "izza": 9990, "\u0120publisher": 9991, "\u0120rescue": 9992, "\u0120Try": 9993, "ULL": 9994, "\u0120Som": 9995, "\u0120Hop": 9996, "oret": 9997, "ths": 9998, "ordon": 9999, "\u0120pocket": 10000, "\u0120Inv": 10001, "Download": 10002, "\u0120Crime": 10003, "\u0120bene": 10004, "\u0120Guide": 10005, "\u0120Assembly": 10006, "\u0120parameters": 10007, "IE": 10008, "\u0120Alexander": 10009, "\u0120concert": 10010, "\u0120Sche": 10011, "\u0120shoes": 10012, "\u0120visiting": 10013, "\u0120recall": 10014, "\u0120bub": 10015, "\u0120rural": 10016, "\u0120concrete": 10017, "\u0120Ros": 10018, "Next": 10019, "Russ": 10020, "\u0120loans": 10021, "\u0120Shield": 10022, "\u0120trem": 10023, "hemat": 10024, "kg": 10025, "\u0120Harris": 10026, "isition": 10027, "\u0120Move": 10028, "\u0120FC": 10029, "\u0120fate": 10030, "\u0120Cho": 10031, "\u0120tired": 10032, "\u0120principal": 10033, "hist": 10034, "iences": 10035, "athy": 10036, "\u0120sevent": 10037, "\u0120mood": 10038, "\u0120strategic": 10039, "\u0120diseases": 10040, "\u0120forum": 10041, "\u0120tempor": 10042, "\u0120headquarters": 10043, "Par": 10044, "ige": 10045, "flix": 10046, "\u0120guitar": 10047, "\u012094": 10048, "Only": 10049, "\u0120releases": 10050, "roph": 10051, "================================": 10052, "\u0120600": 10053, "\u0120Continue": 10054, "igate": 10055, "\u0120Crit": 10056, "system": 10057, "\u0120disabled": 10058, "\u0120unexpected": 10059, "ithub": 10060, "\u0120unclear": 10061, "\u0120Est": 10062, "\u0120contrad": 10063, "\u0120strategies": 10064, "ventures": 10065, "\u0120passage": 10066, "AME": 10067, "\u0120improving": 10068, "\u0120reveals": 10069, "\u0120decrease": 10070, "ova": 10071, "\u0120annoy": 10072, "\u0120Short": 10073, "\u0120Library": 10074, "\u0120cyber": 10075, "nell": 10076, "\u0120Hur": 10077, "\u0120CB": 10078, "\u0120photograp": 10079, "UI": 10080, "\u0120sed": 10081, "Ge": 10082, "\u012087": 10083, "\u0120diverse": 10084, "\u0120encouraged": 10085, "\u0120conspiracy": 10086, "\u0120birds": 10087, "\u0120operator": 10088, "\u0120handful": 10089, "\u0120classified": 10090, "?)": 10091, "\u0120dramatic": 10092, "\u0120investigators": 10093, "ito": 10094, "\u0120widespread": 10095, "\u0120Room": 10096, "----------------------------------------------------------------": 10097, "\u0120collective": 10098, "\u0120journalist": 10099, "String": 10100, "\u0120temperatures": 10101, "ila": 10102, "\u0120guid": 10103, "\u0120inspect": 10104, "\u0120missile": 10105, "\u0120Mayor": 10106, "\u0120manual": 10107, "\u0120simultane": 10108, "\u0120ratings": 10109, "\u0120suck": 10110, "\u012097": 10111, "\u0120universal": 10112, "\u0120pharm": 10113, "\u0120disrupt": 10114, "iano": 10115, "AV": 10116, "\u0120ft": 10117, "\u0120statist": 10118, "olds": 10119, "\u0120Walker": 10120, "php": 10121, "\u0120undert": 10122, "\u0120Las": 10123, "ishop": 10124, "ntil": 10125, "reshold": 10126, "\u0120Whether": 10127, "Ms": 10128, "\u0120deny": 10129, "\u0120Cloud": 10130, "\u0120provider": 10131, "\u0120surviv": 10132, "\u0120Update": 10133, "has": 10134, "\u0120mistakes": 10135, "charge": 10136, "pled": 10137, "rity": 10138, "\u0120node": 10139, "\u0120Massachusetts": 10140, "ools": 10141, "lication": 10142, "\u0120fails": 10143, "emale": 10144, "ori": 10145, "backs": 10146, "\u0120shirt": 10147, "\u0120''": 10148, "\u0120NAT": 10149, "\u0120waters": 10150, "elson": 10151, "\u0120ease": 10152, "\u0120scar": 10153, "\u0120contents": 10154, "mind": 10155, "\u0120contribution": 10156, "\u0120shr": 10157, "\u0120handed": 10158, "\u0120stability": 10159, "\u0120trave": 10160, "Em": 10161, "\u0120mirror": 10162, "123": 10163, "\u0120weigh": 10164, "\u0120fiction": 10165, "ouver": 10166, "istant": 10167, "rition": 10168, "\u0120Fed": 10169, "\u0120physically": 10170, "\u0120stake": 10171, "\u0120Article": 10172, "\u0120Arc": 10173, "\u0120Lewis": 10174, "\u0120Mind": 10175, "\u0120demonstrate": 10176, "\u0120profits": 10177, "vision": 10178, "omic": 10179, "olid": 10180, "\u0120battles": 10181, "\u0120drives": 10182, "\u0120eastern": 10183, "\u0120Sony": 10184, "!!!": 10185, "aration": 10186, "vard": 10187, "\u0120GL": 10188, "portation": 10189, "\u012092": 10190, "\u0120lawmakers": 10191, "\u0120protecting": 10192, "\u0120EPA": 10193, "\u0120yeah": 10194, "\u0120shame": 10195, "olph": 10196, "even": 10197, "xit": 10198, "\u0120attach": 10199, "\u0120representing": 10200, "\u0120obs": 10201, "\u0120Utah": 10202, "iffs": 10203, "\u0120Freedom": 10204, "\u00c3\u00b3": 10205, "AK": 10206, "\u0120incidents": 10207, "itage": 10208, "\u0120viewers": 10209, "cd": 10210, "\u0120mouse": 10211, "\u0120clar": 10212, "\u0120accordance": 10213, "\u0120bot": 10214, "cor": 10215, "\u0120Summer": 10216, "held": 10217, "\u0120innocent": 10218, "\u0120initiative": 10219, "ols": 10220, "________________________________": 10221, "\u0120spots": 10222, "pace": 10223, "\u0120conventional": 10224, "\u0120corporations": 10225, "\u0120blocked": 10226, "HD": 10227, "attered": 10228, "\u0120refers": 10229, "\u0120buck": 10230, "\u0120Digital": 10231, "120": 10232, "\u0120topics": 10233, "TF": 10234, "\u00c4\u0123": 10235, "brid": 10236, "reement": 10237, "\u0120underlying": 10238, "\u0120Member": 10239, "\u0120investigating": 10240, "\u0120pregnancy": 10241, "\u0120touchdown": 10242, "\u0120Band": 10243, "\u0120Caller": 10244, "\u0120instances": 10245, "PP": 10246, "wa": 10247, "Good": 10248, "\u01201991": 10249, "\u0120Cold": 10250, "\u0120fears": 10251, "\u0120remarks": 10252, "\u0128\u0134": 10253, "atal": 10254, "\u0120mit": 10255, "\u0120experiments": 10256, "ipt": 10257, "Color": 10258, "indu": 10259, "Update": 10260, "\u012093": 10261, "Ag": 10262, "\u0120\u00e5": 10263, "ancouver": 10264, "Both": 10265, "\u0120judges": 10266, "Object": 10267, "\u0120stere": 10268, "umbn": 10269, "\u0120participation": 10270, "\u0120Stars": 10271, "\u0120Jere": 10272, "\u0120weekly": 10273, "\u0120Ban": 10274, "\u0120conversations": 10275, "\u0120Pitt": 10276, "uz": 10277, "\u0120Indiana": 10278, "\u0120Kick": 10279, "\u0120infection": 10280, "\u0120heroes": 10281, "\u0120settled": 10282, "\u0120strip": 10283, "\u0120hal": 10284, "\u0120dump": 10285, "\u0120Sci": 10286, "\u0120les": 10287, "\u0120references": 10288, "\u0120URL": 10289, "\u0120Bridge": 10290, "\u0120wanting": 10291, "Force": 10292, "\u0120exclus": 10293, "Meanwhile": 10294, "mn": 10295, "\u0120gentle": 10296, "maker": 10297, "senal": 10298, "\u0120Gro": 10299, "ouri": 10300, "\u0120Rain": 10301, "\u0120Alliance": 10302, "\u0120lift": 10303, "ela": 10304, "SD": 10305, "\u0120Cleveland": 10306, "\u0120ranked": 10307, "\u0120stadium": 10308, "\u0120deadly": 10309, "\u00e4\u00b8": 10310, "\u0120riding": 10311, "aria": 10312, "\u0120Armor": 10313, "\u0120documentation": 10314, "\u0120Greece": 10315, "reek": 10316, "\u0120lens": 10317, "\u0120Sa": 10318, "\u0120gross": 10319, "\u0120Emer": 10320, "agers": 10321, "\u0120Dub": 10322, "\u0120Rh": 10323, "\u0120AMD": 10324, "\u0120arrival": 10325, "\u0120desert": 10326, "\u0120supplement": 10327, "\u0120Resp": 10328, "\u0120knee": 10329, "\u0120margin": 10330, "font": 10331, "ogg": 10332, "2010": 10333, "\u0120Pir": 10334, "\u0120Prom": 10335, "ivals": 10336, "\u0120intake": 10337, "\u0120differently": 10338, "ugs": 10339, "\u0120bits": 10340, "cluded": 10341, "\u0120searching": 10342, "\u0120Du": 10343, "umble": 10344, "\u0120functional": 10345, "\u0120Baltimore": 10346, "\u0120Could": 10347, "\u0120desired": 10348, "\u0120circuit": 10349, "\u0120Lyn": 10350, "\u0120GO": 10351, "\u0120False": 10352, "repre": 10353, "':": 10354, "alties": 10355, "\u0120minim": 10356, "\u0120drove": 10357, "\u0120Should": 10358, "\u0120hip": 10359, "\u0120pros": 10360, "\u0120utility": 10361, "\u0120Nature": 10362, "\u0120Mode": 10363, "President": 10364, "opp": 10365, "rat": 10366, "formance": 10367, "\u0120concentration": 10368, "\u0120font": 10369, "\u0120Bud": 10370, "\u0120amid": 10371, "\u0120revers": 10372, "\u0120ML": 10373, "Bar": 10374, "\u0120interaction": 10375, "\u0120jurisd": 10376, "\u0120spells": 10377, "dep": 10378, "fil": 10379, "\u0120civilians": 10380, "utter": 10381, "\u0120Cooper": 10382, "\u0120Below": 10383, "\u0120entrance": 10384, "\u0120convert": 10385, "\u0120controversy": 10386, "owered": 10387, "\u0120contrary": 10388, "\u0120arc": 10389, "\u0120Executive": 10390, "\u0120Officer": 10391, "\u0120packages": 10392, "\u0120progressive": 10393, "width": 10394, "\u0120reserved": 10395, "vol": 10396, "\u0120Samsung": 10397, "\u0120printed": 10398, "\u0120centers": 10399, "\u0120introduce": 10400, "\u0120Kennedy": 10401, "\u0120odds": 10402, "\u0120surely": 10403, "\u0120independence": 10404, "\u0120passengers": 10405, "reprene": 10406, "\u0120Beh": 10407, "\u0120loves": 10408, "\u0120ESPN": 10409, "\u0120facilit": 10410, "\u0120identical": 10411, "\u0120doct": 10412, "\u0120partnership": 10413, "conf": 10414, "\u0120Hide": 10415, "\u0120confused": 10416, "\u0120Cow": 10417, "Men": 10418, "\u0120wrest": 10419, "\u0120Iraqi": 10420, "\u0120holes": 10421, "\u0120Studies": 10422, "\u0120pregnant": 10423, "hard": 10424, "\u0120signals": 10425, "IX": 10426, "\u0120pulling": 10427, "\u0120graduate": 10428, "\u0120nominee": 10429, "Date": 10430, "\u0120permitted": 10431, "\u0120\u00e2\u0124\u00ac": 10432, "\u0120Oklahoma": 10433, "Start": 10434, "\u0120authorized": 10435, "\u0120alarm": 10436, "\u0120Cos": 10437, "van": 10438, "\u0120generations": 10439, "cular": 10440, "\u0120dragon": 10441, "\u0120Software": 10442, "\u0120Edward": 10443, "\u0120controller": 10444, "Sen": 10445, "gered": 10446, "\u0120Vik": 10447, "\u0120approached": 10448, "Thank": 10449, "\u0120cance": 10450, "\u0120formula": 10451, "\u0120Small": 10452, "\u0120weakness": 10453, "\u0120ramp": 10454, "itudes": 10455, "jud": 10456, "\u0120brilliant": 10457, "\u0120accus": 10458, "source": 10459, "\u0120800": 10460, "\u0120Evil": 10461, "Sw": 10462, "\u0120homeless": 10463, "week": 10464, "iens": 10465, "rics": 10466, "\u0120Third": 10467, "TO": 10468, "\u0120organic": 10469, "\u0120presentation": 10470, "agh": 10471, "\u0120Download": 10472, "vation": 10473, "\u0120assembly": 10474, "orable": 10475, "holders": 10476, "\u0120Bernie": 10477, "\u0120Help": 10478, "\u0120tong": 10479, "\u0120Fight": 10480, "\u0120beach": 10481, "Book": 10482, "\u0120Lic": 10483, "\u0120rush": 10484, "\u0120Round": 10485, "oup": 10486, "\u0120Marx": 10487, "\u0120calculated": 10488, "\u0120Devil": 10489, "\u0120Sarah": 10490, "\u0120occasionally": 10491, "\u0120bullet": 10492, "Available": 10493, "gate": 10494, "\u012091": 10495, "\u0120hosp": 10496, "\u0120promises": 10497, "\u0120HIV": 10498, "\u0120Stadium": 10499, "\u0120Stock": 10500, "\u0120Corporation": 10501, "gage": 10502, "NG": 10503, "\u0120Credit": 10504, "\u0120sne": 10505, "ibl": 10506, "\u0120accum": 10507, "such": 10508, "\u0120terrorists": 10509, "\u0120consciousness": 10510, "\u0120Zh": 10511, "\u0120drama": 10512, "oola": 10513, "piration": 10514, "\u0120labour": 10515, "\u0120Nin": 10516, "\u0120utter": 10517, "\u0120democratic": 10518, "\u0120assass": 10519, "ilation": 10520, "\u0120gest": 10521, "\u0120abroad": 10522, "\u0120metab": 10523, "\u0120sorts": 10524, "\u0120flav": 10525, "UB": 10526, "\u0120mg": 10527, "\u0120Nothing": 10528, "\u0120Od": 10529, "\u0120musical": 10530, "2009": 10531, "\u0120drops": 10532, "ocated": 10533, "ateral": 10534, "000000": 10535, "\u0120gre": 10536, "\u0120equality": 10537, "\u0120burden": 10538, "\u0120vig": 10539, "\u0120Leader": 10540, "------------": 10541, "\u0120ceremony": 10542, "\u0120fighter": 10543, "\u0120actors": 10544, "\u0120\u00e6": 10545, "aman": 10546, "Fi": 10547, "\u0120align": 10548, "puter": 10549, "\u0120elder": 10550, "\u0120NSA": 10551, "\u0120representation": 10552, "\u0120Ontario": 10553, "ITH": 10554, "usalem": 10555, "\u0120harassment": 10556, "itzer": 10557, "\u0120symp": 10558, "\u0120boxes": 10559, "\u0120DR": 10560, "\u0120manifest": 10561, "atre": 10562, "\u0120^": 10563, "\u0120dies": 10564, "leton": 10565, "\u0120missions": 10566, "ethe": 10567, "\u0120resolve": 10568, "\u0120followers": 10569, "\u0120asc": 10570, "\u0120km": 10571, "lord": 10572, "ammed": 10573, "\u0120silent": 10574, "\u0120Associated": 10575, "\u0120timing": 10576, "\u0120prisoners": 10577, "\u0120Kings": 10578, "\u0120Five": 10579, "\u0120tower": 10580, "\u0120approaches": 10581, "\u0120precisely": 10582, "\u0120bureau": 10583, "\u0120Mother": 10584, "\u0120Iss": 10585, "\u0120keyboard": 10586, "itual": 10587, "\u0120funded": 10588, "\u0120staying": 10589, "\u0120psychological": 10590, "\u0120mile": 10591, "\u0120Leon": 10592, "\u0120Barb": 10593, "will": 10594, "\u0120wider": 10595, "\u0120Atlantic": 10596, "\u0120till": 10597, "\u0120Rome": 10598, "rot": 10599, "\u0120accompan": 10600, "\u0120flour": 10601, "aco": 10602, "World": 10603, "\u0120Express": 10604, "\u0120Yu": 10605, "Cor": 10606, "\u0120pleased": 10607, "party": 10608, "\u0120pointing": 10609, "\u0120inflation": 10610, "\u0120roy": 10611, "\u0120),": 10612, "ainer": 10613, "\u0120wedding": 10614, "ormon": 10615, "\u0120requiring": 10616, "\u0120qualified": 10617, "\u0120segment": 10618, "END": 10619, "\u0120sizes": 10620, "eals": 10621, "\u0120corrupt": 10622, "assador": 10623, "\u0120celeb": 10624, "\u0120dreams": 10625, "\u0120Mess": 10626, "\u0120checking": 10627, "\u0120Version": 10628, "\u0120preparing": 10629, "\u0120actively": 10630, "\u0120Diff": 10631, "\u0120lux": 10632, "\u0120Winter": 10633, "acteria": 10634, "\u0120NE": 10635, "\u0120deputy": 10636, "\u0120transgender": 10637, "\u0120summary": 10638, "\u0120inher": 10639, "eries": 10640, "char": 10641, "\u0120Yan": 10642, "\u0120knock": 10643, "\u0120Path": 10644, "\u0120lip": 10645, "roller": 10646, "\u0120impression": 10647, "\u0120celebrate": 10648, "\u0120slide": 10649, "\u0120guests": 10650, "\u0120clip": 10651, "FS": 10652, "\u0120savings": 10653, "\u0120captain": 10654, "\u0120legacy": 10655, "\u0120Denver": 10656, "\u0120wounded": 10657, "taboola": 10658, "ACT": 10659, "\u0120pursue": 10660, "\u0120oxy": 10661, "\u0120q": 10662, "\u0120semi": 10663, "\u0120Need": 10664, "\u0120Affairs": 10665, "\u0120obsc": 10666, "\u0120checked": 10667, "\u0120dual": 10668, "Code": 10669, "\u0120MD": 10670, "lem": 10671, "ulty": 10672, "\u0120\u00c2\u00a9": 10673, "\u0120Elizabeth": 10674, "\u0120centuries": 10675, "arded": 10676, "src": 10677, "\u0120evident": 10678, "ennis": 10679, "atin": 10680, "\u0120unemployment": 10681, "\u0120Mario": 10682, "\u0120intim": 10683, "Christ": 10684, "\u0120biological": 10685, "\u0120soldier": 10686, "\u0120Added": 10687, "\u0120math": 10688, "\u0120Gil": 10689, "\u0120bias": 10690, "\u0120dating": 10691, "\u0120Ocean": 10692, "\u0120mice": 10693, "Mus": 10694, "hire": 10695, "\u0120Tes": 10696, "Server": 10697, "limited": 10698, "Size": 10699, "\u0120meters": 10700, "\u0120rocket": 10701, "essee": 10702, "\u0120certificate": 10703, "\u0120Iranian": 10704, "ASS": 10705, "\u0120grid": 10706, "Dec": 10707, "\u0120rolling": 10708, "commun": 10709, "\u0120Sweden": 10710, "bury": 10711, "\u0120tissue": 10712, "\u0120racism": 10713, "\u0120Local": 10714, "\u0120mystery": 10715, "\u0120examine": 10716, "\u0120stem": 10717, "\u0120sits": 10718, "\u0120hoped": 10719, "oting": 10720, "\u0120dialogue": 10721, "\u0120persu": 10722, "Watch": 10723, "lay": 10724, "MAN": 10725, "\u0120chronic": 10726, "\u0120Portland": 10727, "market": 10728, "\u0120SEC": 10729, "\u0120parallel": 10730, "\u0120scandal": 10731, "\u0120carries": 10732, "\u0120phenomenon": 10733, "human": 10734, "acker": 10735, "\u0120Ox": 10736, "\u0120retirement": 10737, "tainment": 10738, "ovie": 10739, "\u0120Gear": 10740, "\u0120duties": 10741, "\u0120dose": 10742, "\u0120scroll": 10743, "MB": 10744, "inf": 10745, "\u0120sauce": 10746, "\u0120landscape": 10747, "reddit": 10748, "\u0120Championship": 10749, "\u0120Reddit": 10750, "alid": 10751, "\u0120coin": 10752, "\u0120overs": 10753, "\u0120posting": 10754, "about": 10755, "\u0120fel": 10756, "andy": 10757, "\u0120bold": 10758, "\u0120focusing": 10759, "effect": 10760, "GR": 10761, "\u0120deemed": 10762, "\u0120recommendations": 10763, "\u0120stepped": 10764, "\u0120voter": 10765, "\u0120Deep": 10766, "\u0120Instagram": 10767, "\u0120moderate": 10768, "\u0120Maryland": 10769, "\u0120restricted": 10770, "\u0120MB": 10771, "\u0120Chall": 10772, "\u0120tob": 10773, "\u0120cir": 10774, "\u0120Occ": 10775, "\u0120Ever": 10776, "\u0120collaps": 10777, "INFO": 10778, "=-": 10779, "\u0120Pict": 10780, "\u0120Account": 10781, "nc": 10782, "\u0120ought": 10783, "\u0120export": 10784, "\u0120drunk": 10785, "('": 10786, "\u0120wise": 10787, "\u0120Mort": 10788, "necess": 10789, "\u0120ancest": 10790, "\u0120Incre": 10791, "\u0120frequent": 10792, "mir": 10793, "\u0120interpretation": 10794, "\u0120dependent": 10795, "\u0120coins": 10796, "\u0120Bol": 10797, "Video": 10798, "\u0120Justin": 10799, "\u0120fatal": 10800, "\u0120cooking": 10801, "\u0120confusion": 10802, "ipher": 10803, "\u0120custody": 10804, "\u0120Morgan": 10805, "omach": 10806, "\u0120Governor": 10807, "\u0120restaurants": 10808, "eling": 10809, "\u0120acknowledged": 10810, "\u0120ther": 10811, "\u0120genes": 10812, "ching": 10813, "Hey": 10814, "\u0120tactics": 10815, "\u0120Mexican": 10816, "\u0120vend": 10817, "\u0120hes": 10818, "quer": 10819, "\u0120noting": 10820, "\u0120Cameron": 10821, "\u0120targeting": 10822, "rock": 10823, "\u0120credits": 10824, "\u0120emotions": 10825, "\u0120representatives": 10826, "news": 10827, "\u0120legislative": 10828, "\u0120removing": 10829, "\u0120tweeted": 10830, "\u0120Carter": 10831, "\u0120Fixed": 10832, "\u0120forcing": 10833, "\u0120speaker": 10834, "\u0120males": 10835, "\u0120Vietnam": 10836, "lined": 10837, "\u0120concepts": 10838, "\u0120voices": 10839, "oir": 10840, "\u0120Trib": 10841, "Whe": 10842, "\u0120Jerusalem": 10843, "\u0120Sant": 10844, "\u0120cul": 10845, "\u0120lady": 10846, "\u0120Hawai": 10847, "\u0120arts": 10848, "\u0120Inn": 10849, "\u0120Machine": 10850, "\u0120Emperor": 10851, "\u0120slot": 10852, "gly": 10853, "\u0120Process": 10854, "III": 10855, "\u0120athletes": 10856, "\u0120Temple": 10857, "\u0120Represent": 10858, "\u0120presc": 10859, "\u0120tons": 10860, "\u0120golden": 10861, "\u0120punch": 10862, "\u0120GR": 10863, "iverpool": 10864, "\u0120enact": 10865, "\u0120lobby": 10866, "\u0120mos": 10867, "\u0120picking": 10868, "\u0120lifetime": 10869, "\u0120cognitive": 10870, "Each": 10871, "zo": 10872, "\u0120dub": 10873, "\u0120consists": 10874, "oln": 10875, "\u0120festival": 10876, "amous": 10877, "\u0120intellig": 10878, "words": 10879, "\u0120Smart": 10880, "\u0120dele": 10881, "\u0120lapt": 10882, "\u0120magical": 10883, "\u0120Sin": 10884, "bus": 10885, "urities": 10886, "ighth": 10887, "\u0120Ruby": 10888, "\u0120Sure": 10889, "olving": 10890, "\u0120jun": 10891, "OST": 10892, "\u0120imposed": 10893, "\u0120astron": 10894, "\u0120correl": 10895, "\u0120NS": 10896, "\u0120Kit": 10897, "\u0120Future": 10898, "burn": 10899, "\u0120immune": 10900, "ocus": 10901, "\u0120courses": 10902, "\u0120String": 10903, "\u0120lean": 10904, "\u0120ghost": 10905, "\u0120outcomes": 10906, "\u0120expense": 10907, "\u0120everyday": 10908, "\u0120acceptable": 10909, "Ah": 10910, "\u0120equipped": 10911, "\u0120orange": 10912, "FR": 10913, "\u0120Dutch": 10914, "Though": 10915, "\u0120Rank": 10916, "QU": 10917, "\u0120Roberts": 10918, "what": 10919, "rend": 10920, "\u0120disappear": 10921, "\u0120spawn": 10922, "\u0120Lam": 10923, "ois": 10924, "\u0120deserve": 10925, "\u0120minimal": 10926, "\u0120nervous": 10927, "\u0120Would": 10928, "\u0120rook": 10929, "\u0120Vancouver": 10930, "\u0120resign": 10931, "shire": 10932, "\u0120Works": 10933, "\u0120Build": 10934, "\u0120affordable": 10935, "\u0120Gary": 10936, "\u0120Arena": 10937, "\u0120hanging": 10938, "\u0120implications": 10939, "\u0120Song": 10940, "\u0120maintaining": 10941, "\u0120guards": 10942, "CON": 10943, "\u0120derived": 10944, "\u0120executed": 10945, "\u0120theories": 10946, "\u0120quoted": 10947, "\u0120Andre": 10948, "oga": 10949, "seless": 10950, "info": 10951, "\u0120Belg": 10952, "\u0120tears": 10953, "\u0120Surv": 10954, "\u0120birthday": 10955, "igious": 10956, "immer": 10957, "\u0120spectrum": 10958, "\u0120architecture": 10959, "\u0120recruit": 10960, "arma": 10961, "Table": 10962, "\u0120monsters": 10963, "\u0120Gov": 10964, "\u0120destination": 10965, "\u0120attractive": 10966, "\u0120foss": 10967, "\u0120Moreover": 10968, "\u0120presents": 10969, "THE": 10970, "\u0120reply": 10971, "pton": 10972, "\u0120cum": 10973, "\u0120delight": 10974, "\u0120affects": 10975, "\u0120donations": 10976, "\u0120Toy": 10977, "\u0120Him": 10978, "MENT": 10979, "\u0120overcome": 10980, "itched": 10981, "\u0120Fantasy": 10982, "\u0120Hat": 10983, "\u0120Beast": 10984, "bott": 10985, "\u0120investigations": 10986, "Run": 10987, "\u0120hunting": 10988, "di": 10989, "fund": 10990, "\u0120sessions": 10991, "estyle": 10992, "\u0120portray": 10993, "oids": 10994, "Yeah": 10995, "\u0120communicate": 10996, "\u0120comedy": 10997, "\u0120Yang": 10998, "\u0120belt": 10999, "\u0120Marine": 11000, "\u0120predicted": 11001, "Play": 11002, "\u0120importantly": 11003, "\u0120remarkable": 11004, "\u0120eliminate": 11005, "David": 11006, "\u0120bind": 11007, "VID": 11008, "\u0120advocates": 11009, "\u0120Gaza": 11010, "imp": 11011, "DB": 11012, "\u0120Na": 11013, "\u0120Similar": 11014, "IES": 11015, "\u0120charity": 11016, "vas": 11017, "math": 11018, "\u0120\u00e2\u0138": 11019, "oker": 11020, "ndum": 11021, "\u0120caps": 11022, "\u0120Hal": 11023, "2000": 11024, "ean": 11025, "\u0120fleet": 11026, "\u0120recre": 11027, "Right": 11028, "\u0120sleeping": 11029, "ijing": 11030, "kind": 11031, "\u0120designated": 11032, "\u00c3\u00a4": 11033, "\u0120animation": 11034, "kee": 11035, "\u0120Introdu": 11036, "\u0120/>": 11037, "\u0120delayed": 11038, "\u0120tremend": 11039, "\u0120curious": 11040, "Use": 11041, "\u0120lect": 11042, "dam": 11043, "\u0120innovation": 11044, "\u0120Points": 11045, "\u0120loading": 11046, "\u0120dispute": 11047, "ctic": 11048, "irds": 11049, "\u0120BY": 11050, "\u0120nurs": 11051, "\u0120Value": 11052, "IONS": 11053, "\u0120Hum": 11054, "\u0120template": 11055, "mers": 11056, "\u0120appearances": 11057, "\u0120Entertainment": 11058, "\u0120translation": 11059, "\u0120sake": 11060, "\u0120beneath": 11061, "\u0120inhib": 11062, "\u0120euro": 11063, "abetes": 11064, "\u0120studying": 11065, "\u0120Mas": 11066, "\u0120perceived": 11067, "\u0120examined": 11068, "\u0120eager": 11069, "\u0120coaches": 11070, "\u0120imper": 11071, "chi": 11072, "\u0120produces": 11073, "\").": 11074, "\u0120Everyone": 11075, "\u0120municip": 11076, "\u0120girlfriend": 11077, "\u0120hire": 11078, "\u0120Vice": 11079, "\u0120suitable": 11080, "opy": 11081, "\u0120inequ": 11082, "\u0120Duke": 11083, "fish": 11084, "first": 11085, "\u0120Obs": 11086, "\u0120interior": 11087, "\u0120Bruce": 11088, "\u0120Ry": 11089, "\u0120analys": 11090, "\u0120considerable": 11091, "\u0120forecast": 11092, "\u0120fert": 11093, "orship": 11094, "\u0120Drug": 11095, "\u0120ALL": 11096, ":\"": 11097, "thur": 11098, "\u0120Mail": 11099, "\u0120ballot": 11100, "\u0120instantly": 11101, "\u0120Channel": 11102, "\u0120picks": 11103, "\u01201989": 11104, "\u0120tent": 11105, "oli": 11106, "\u0120civilian": 11107, "bling": 11108, "ello": 11109, "bu": 11110, "\u0120inch": 11111, "\u0120logo": 11112, "\u0120cooperation": 11113, "\u0120walks": 11114, "\u0120investments": 11115, "\u0120imprison": 11116, "\u0120Festival": 11117, "\u0120Ky": 11118, "\u0120legally": 11119, "\u0120gri": 11120, "charg": 11121, "Sl": 11122, "\u0120threatening": 11123, "duction": 11124, "flow": 11125, "\u0120dismissed": 11126, "ibraries": 11127, "cap": 11128, "ele": 11129, "\u0120McG": 11130, "\u0120Harvard": 11131, "\u0120Conservative": 11132, "\u0120CBS": 11133, "png": 11134, "\u0120roots": 11135, "\u0120Having": 11136, "umbled": 11137, "\u0120Fun": 11138, "\\/": 11139, "\u0120Search": 11140, "plex": 11141, "\u0120discussing": 11142, "\u0120continu": 11143, "\u0120Tai": 11144, "\u0120Wik": 11145, "Free": 11146, "fit": 11147, "\u0120refuse": 11148, "\u0120managing": 11149, "\u0120synd": 11150, "ipedia": 11151, "walk": 11152, "\u0120professionals": 11153, "\u0120guidance": 11154, "\u0120universities": 11155, "\u0120assemb": 11156, "untu": 11157, "Finally": 11158, "ASE": 11159, "\u0120Auto": 11160, "\u0120Had": 11161, "\u0120anniversary": 11162, "LD": 11163, "\u0120Dur": 11164, "\u0120Ultimate": 11165, "ihad": 11166, "product": 11167, "\u0120transit": 11168, "\u0120restore": 11169, "\u0120explaining": 11170, "\u0120asset": 11171, "\u0120transferred": 11172, "\u0120burst": 11173, "apolis": 11174, "\u0120Magazine": 11175, "\u0120Cra": 11176, "\u0120BR": 11177, "gged": 11178, "\u0120HE": 11179, "Mich": 11180, "bet": 11181, "\u0120Lady": 11182, "ylum": 11183, "erves": 11184, "\u0120meets": 11185, "white": 11186, "Log": 11187, "\u0120corresponding": 11188, "\u0120insisted": 11189, "GG": 11190, "\u0120surrounded": 11191, "\u0120tens": 11192, "\u0120lane": 11193, "\u0120coinc": 11194, "home": 11195, "\u0120existed": 11196, "ected": 11197, "\u0120Double": 11198, "lamm": 11199, "\u0120skept": 11200, "exp": 11201, "\u0120perception": 11202, "iev": 11203, "\u0120Being": 11204, "oft": 11205, "\u0120adopt": 11206, ".:": 11207, "];": 11208, "Windows": 11209, "\u0120satellite": 11210, "ASH": 11211, "\u0120infant": 11212, "description": 11213, "\u0120Meanwhile": 11214, "cm": 11215, "oca": 11216, "\u0120Treat": 11217, "actor": 11218, "\u0120tobacco": 11219, "\u0120Norm": 11220, "emption": 11221, "\u0120flesh": 11222, "\u0120je": 11223, "oop": 11224, "\u0120Heaven": 11225, "\u0120beating": 11226, "anim": 11227, "\u0120gathering": 11228, "\u0120cultiv": 11229, "GO": 11230, "abe": 11231, "\u0120Jonathan": 11232, "\u0120Safety": 11233, "\u0120badly": 11234, "prot": 11235, "\u0120choosing": 11236, "\u0120contacted": 11237, "\u0120quit": 11238, "\u0120distur": 11239, "\u0120stir": 11240, "\u0120token": 11241, "Det": 11242, "\u0120Pa": 11243, "\u0120functionality": 11244, "003": 11245, "some": 11246, "\u0120limitations": 11247, "\u0120meth": 11248, "build": 11249, "config": 11250, "NT": 11251, "rell": 11252, "blem": 11253, "\u0120Mom": 11254, "\u0120veterans": 11255, "\u0120Hu": 11256, "\u0120trends": 11257, "arer": 11258, "\u0120Given": 11259, "\u0120Caption": 11260, "may": 11261, "AST": 11262, "\u0120wondering": 11263, "\u0120Clark": 11264, "normal": 11265, "\u0120separated": 11266, "\u0120desp": 11267, "stic": 11268, "brew": 11269, "\u0120relating": 11270, "\u0120Nik": 11271, "\u0120Farm": 11272, "\u0120enthusi": 11273, "good": 11274, "deb": 11275, "\u0120activist": 11276, "\u0120mart": 11277, "\u0120explosion": 11278, "\u0120Economic": 11279, "Link": 11280, "\u0120insight": 11281, "\u0120convenient": 11282, "\u0120counterpart": 11283, "support": 11284, "\u0120Virt": 11285, "agen": 11286, "\u0120Tennessee": 11287, "\u0120Simon": 11288, "\u0120Award": 11289, "OCK": 11290, "\u0120Figure": 11291, "\u0120overseas": 11292, "\u0120pride": 11293, "\u0120Cas": 11294, "note": 11295, "mg": 11296, "Current": 11297, "\u0120displays": 11298, "content": 11299, "\u0120traveling": 11300, "\u0120hospitals": 11301, "\u0120Financial": 11302, "\u0120Past": 11303, "\u0120defendant": 11304, "\u0120streaming": 11305, "mble": 11306, "\u0120Berlin": 11307, "uki": 11308, "\u0120distribut": 11309, "\u0120antib": 11310, "\u0120chocolate": 11311, "\u0120Castle": 11312, "\u0120interrupt": 11313, "\u0120Row": 11314, "\u0120conversion": 11315, "\u0120bugs": 11316, "\u0120Rather": 11317, "liest": 11318, "LY": 11319, "\u0120Jean": 11320, "common": 11321, "akh": 11322, "\u0120130": 11323, "otton": 11324, "\u0120Dean": 11325, "\u0120amendment": 11326, "\u0120gameplay": 11327, "\u0120Warren": 11328, "oda": 11329, "\u0120highlights": 11330, "\u0120irre": 11331, "\u0120NATO": 11332, "\u0120balls": 11333, "\u0120demanding": 11334, "URE": 11335, "\u0120Luke": 11336, "Figure": 11337, "stop": 11338, "onia": 11339, "zone": 11340, "izers": 11341, "\u0120WR": 11342, "\u0120awarded": 11343, "\u0120regulatory": 11344, "\u0120Hart": 11345, "\u0120SN": 11346, "pling": 11347, "\u0120sour": 11348, "\u0120Pixel": 11349, "usive": 11350, "\u0120fet": 11351, "\u0120Sent": 11352, "\u0120automatic": 11353, "\u0120fer": 11354, "vernment": 11355, "\u0120Khan": 11356, "TON": 11357, "father": 11358, "\u0120extraordinary": 11359, "throp": 11360, "\u0120Python": 11361, "\u0120GPU": 11362, "\u0120sexually": 11363, "\u0120desktop": 11364, "itivity": 11365, "\u0120Antonio": 11366, "\u0120orient": 11367, "\u0120ears": 11368, "obby": 11369, "ouses": 11370, "vertisements": 11371, "\u0120manufacturers": 11372, "icient": 11373, "minute": 11374, "\u0120conviction": 11375, "\u0120garden": 11376, "public": 11377, "\u0120satisfied": 11378, "fold": 11379, "OK": 11380, "\u0120inhab": 11381, "\u0120Think": 11382, "\u0120programme": 11383, "\u0120stomach": 11384, "\u0120coordin": 11385, "\u0120holy": 11386, "\u0120threshold": 11387, "\u0120rhet": 11388, "\u0120serial": 11389, "\u0120employers": 11390, "\u0120Everything": 11391, "rah": 11392, "\u0120bother": 11393, "\u0120brands": 11394, "Value": 11395, "\u0120Ted": 11396, "\u0120Planet": 11397, "\u0120pink": 11398, "\u0120Furthermore": 11399, "sa": 11400, "PE": 11401, "reck": 11402, "\u0120USD": 11403, "otte": 11404, "\u0120&&": 11405, "\u0120landed": 11406, "gets": 11407, "\u0120producers": 11408, "\u0120healthcare": 11409, "\u0120dominant": 11410, "\u0120destro": 11411, "\u0120amended": 11412, "chron": 11413, "\u0120fits": 11414, "\u0120Syd": 11415, "\u0120Authority": 11416, "ATCH": 11417, "\u0120fights": 11418, "\u0120LLC": 11419, "\u0120---": 11420, "\u0120Corp": 11421, "\u0120toxic": 11422, "specific": 11423, "\u0120Corn": 11424, "\u0120Chel": 11425, "\u0120telephone": 11426, "\u0120Pant": 11427, "\u0120mysterious": 11428, "aunch": 11429, "odox": 11430, "media": 11431, "\u0120witnesses": 11432, "agu": 11433, "\u0120questioned": 11434, "\u0120Brexit": 11435, "\u0120Remember": 11436, "enez": 11437, "\u0120endorse": 11438, "iatric": 11439, "\u0120Ident": 11440, "\u0120ridiculous": 11441, "110": 11442, "\u0120prayer": 11443, "\u0120scientist": 11444, "\u01201950": 11445, "\u0120Aqu": 11446, "\u0120underground": 11447, "\u0120UFC": 11448, "mare": 11449, "\u0120Later": 11450, "wich": 11451, "\u0120subscrib": 11452, "\u0120hosts": 11453, "\u0120err": 11454, "\u0120grants": 11455, "antom": 11456, "\u0120summon": 11457, "early": 11458, "\u0120Clear": 11459, "\u0120Prim": 11460, "\u0120suspension": 11461, "\u0120guaranteed": 11462, "apper": 11463, "\u0120rice": 11464, "\u0120Sean": 11465, "\u0120Shin": 11466, "\u0120referendum": 11467, "\u0120fled": 11468, "rust": 11469, "\u0120360": 11470, "tery": 11471, "\u0120shocked": 11472, "BR": 11473, "\u0120Oil": 11474, "\u0120Allah": 11475, "\u0120partly": 11476, "\u0120ignor": 11477, "\u0120transmission": 11478, "\u0120homosexual": 11479, "iversal": 11480, "\u0120hopefully": 11481, "\u00e3\u0124\u00a4": 11482, "\u0120lesson": 11483, "Leg": 11484, "\u0120..": 11485, "Yet": 11486, "table": 11487, "appropri": 11488, "rett": 11489, "\u0120boards": 11490, "\u0120incorrect": 11491, "\u0120bacteria": 11492, "aru": 11493, "amac": 11494, "\u0120snap": 11495, ".'\"": 11496, "\u0120parad": 11497, "tem": 11498, "heart": 11499, "\u0120availability": 11500, "\u0120wisdom": 11501, "\u0120(+": 11502, "\u0120priest": 11503, "\u0120\u00c2\u0142\u0120\u00c2\u0142": 11504, "Open": 11505, "\u0120span": 11506, "\u0120parameter": 11507, "\u0120convince": 11508, "\u0120(%)": 11509, "rac": 11510, "\u0120fo": 11511, "\u0120safely": 11512, "\u0120converted": 11513, "\u0120Olympic": 11514, "\u0120reserve": 11515, "\u0120healing": 11516, "\u0120Mine": 11517, "Max": 11518, "\u0120inherent": 11519, "\u0120Graham": 11520, "\u0120integrated": 11521, "Dem": 11522, "\u0120pipeline": 11523, "\u0120applying": 11524, "\u0120embed": 11525, "\u0120Charlie": 11526, "\u0120cave": 11527, "2008": 11528, "\u0120consensus": 11529, "\u0120rewards": 11530, "Pal": 11531, "\u0120HTML": 11532, "\u0120popularity": 11533, "looking": 11534, "\u0120Sword": 11535, "\u0120Arts": 11536, "')": 11537, "\u0120electron": 11538, "clusions": 11539, "\u0120integrity": 11540, "\u0120exclusively": 11541, "\u0120grace": 11542, "\u0120torture": 11543, "\u0120burned": 11544, "two": 11545, "\u0120180": 11546, "Produ": 11547, "\u0120entreprene": 11548, "raphics": 11549, "\u0120gym": 11550, "ricane": 11551, "\u0120Tam": 11552, "\u0120administrative": 11553, "\u0120manufacturer": 11554, "\u0120vel": 11555, "\u0120Ni": 11556, "\u0120isolated": 11557, "\u0120Medicine": 11558, "\u0120backup": 11559, "\u0120promoting": 11560, "\u0120commander": 11561, "\u0120flee": 11562, "\u0120Russell": 11563, "\u0120forgotten": 11564, "\u0120Missouri": 11565, "\u0120residence": 11566, "mons": 11567, "\u0120resemb": 11568, "\u0120wand": 11569, "\u0120meaningful": 11570, "PT": 11571, "\u0120bol": 11572, "\u0120helic": 11573, "\u0120wealthy": 11574, "\u0120rifle": 11575, "strong": 11576, "rowing": 11577, "plan": 11578, "asury": 11579, "\u00e2\u0122\u00a6.": 11580, "\u0120expanding": 11581, "\u0120Hamilton": 11582, "\u0120receives": 11583, "SI": 11584, "eatures": 11585, "\u0120Anim": 11586, "REE": 11587, "Put": 11588, "\u0120briefly": 11589, "rive": 11590, "\u0120stimul": 11591, "\u0120``(": 11592, "\u0120__": 11593, "\u0120chip": 11594, "\u0120haz": 11595, "\u0120prize": 11596, "\u0120Things": 11597, "ACE": 11598, "ulin": 11599, "dict": 11600, "oku": 11601, "\u0120associate": 11602, "ockets": 11603, "youtube": 11604, "Story": 11605, "ategory": 11606, "\u0120mild": 11607, "ailing": 11608, "\u0120Ye": 11609, "Orig": 11610, "\u0120Ka": 11611, "orig": 11612, "\u0120propaganda": 11613, "\u0120anonymous": 11614, "\u0120struggled": 11615, "\u0120outrage": 11616, "ATED": 11617, "\u0120Beijing": 11618, "rary": 11619, "\u0120leather": 11620, "\u0120worlds": 11621, "\u0120broader": 11622, "125": 11623, "idal": 11624, "\u0120Better": 11625, "\u0120tear": 11626, "Ext": 11627, "\u0120proposals": 11628, "\u0120iter": 11629, "\u0120Squad": 11630, "\u0120volunt": 11631, "mi": 11632, "Did": 11633, "\u0120Pu": 11634, "pin": 11635, "\u0120speakers": 11636, "\u0120borders": 11637, "\u0120figured": 11638, "='": 11639, "\u0120simultaneously": 11640, "aeda": 11641, "\u0120charging": 11642, "\u0120urged": 11643, "\u0120conj": 11644, "256": 11645, "\u0120Gordon": 11646, "merce": 11647, "\u0120documentary": 11648, "Share": 11649, "itol": 11650, "ONE": 11651, "\u0120Garden": 11652, "hatt": 11653, "\u0120Thompson": 11654, "aneous": 11655, "apore": 11656, "\u0120tanks": 11657, "\u0120lessons": 11658, "track": 11659, "\u0120outstanding": 11660, "\u0120volunteers": 11661, "\u0120spray": 11662, "\u0120managers": 11663, "large": 11664, "\u0120camps": 11665, "\u0120artificial": 11666, "\u0120Ru": 11667, "\u0120bags": 11668, "thal": 11669, "\u0120compatible": 11670, "\u0120Blade": 11671, "\u0120fed": 11672, "\u0120argues": 11673, "FI": 11674, "\u0120unfair": 11675, "\u0120corn": 11676, "\u0120offset": 11677, "\u0120directions": 11678, "\u0120disappointed": 11679, "\u0120Convention": 11680, "\u0120viewing": 11681, "ME": 11682, "ocity": 11683, "\u0120towns": 11684, "\u0120layers": 11685, "\u0120rolled": 11686, "\u0120jumped": 11687, "\u0120attribute": 11688, "\u0120unnecess": 11689, "incoln": 11690, "\u0120suppose": 11691, "\u0120Nether": 11692, "cha": 11693, "\u0120buried": 11694, "\u0120sixth": 11695, "Ben": 11696, "ressing": 11697, "OUR": 11698, "\u0120wound": 11699, "\u0120cycl": 11700, "\u0120mechanisms": 11701, "\u0120congressional": 11702, "\u0120Element": 11703, "\u0120agreements": 11704, "\u0120decor": 11705, "\u0120closest": 11706, "\u0120Mit": 11707, "Google": 11708, "}}": 11709, "\u0120mixture": 11710, "\u0120fluid": 11711, "Sign": 11712, "\u0120Scholar": 11713, "\u0120pist": 11714, "asket": 11715, "abling": 11716, "\u0120racing": 11717, "hero": 11718, "riel": 11719, "assy": 11720, "\u0120cheaper": 11721, "ben": 11722, "\u0120vertical": 11723, "amacare": 11724, "\u0120Reading": 11725, "gments": 11726, "\u0120helicop": 11727, "\u0120sacrifice": 11728, "aya": 11729, "paren": 11730, "VA": 11731, "\u0120Les": 11732, "\u0120Studio": 11733, "\u0120violations": 11734, "\u0120Anna": 11735, "acer": 11736, "\u00e9\u00be": 11737, "\u0120Rat": 11738, "\u0120Beck": 11739, "\u0120Dick": 11740, "\u0120ACT": 11741, "\u0120composition": 11742, "\u0120texture": 11743, "\u0120Own": 11744, "\u0120smartphone": 11745, "\u0120NA": 11746, "\u0120forb": 11747, "import": 11748, "\u0120defending": 11749, "ilst": 11750, "rer": 11751, "\u0120oh": 11752, "\u0120Jeremy": 11753, "\u0120banking": 11754, "ceptions": 11755, "\u0120respective": 11756, "/.": 11757, "\u0120drinks": 11758, "\u0120Wi": 11759, "\u0120bands": 11760, "\u0120Liverpool": 11761, "\u0120grip": 11762, "\u0120Buy": 11763, "\u0120openly": 11764, "\u0120reviewed": 11765, "pert": 11766, "\u0120verify": 11767, "\u0120Cole": 11768, "\u0120Wales": 11769, "MO": 11770, "\u0120unpre": 11771, "\u0120shelter": 11772, "\u0120Imperial": 11773, "\u0120gui": 11774, "\u0120Dak": 11775, "\u0120suggestions": 11776, "\u0120explicitly": 11777, "\u0120slave": 11778, "\u0120blockchain": 11779, "\u0120competing": 11780, "\u0120promising": 11781, "SON": 11782, "\u0120soccer": 11783, "\u0120constitution": 11784, "429": 11785, "\u0120distract": 11786, "\u0120User": 11787, "esides": 11788, "\u0120Method": 11789, "\u0120Tokyo": 11790, "\u0120accompanied": 11791, "Client": 11792, "sur": 11793, "alog": 11794, "\u0120identification": 11795, "\u0120invasion": 11796, "asma": 11797, "\u0120industries": 11798, "ppers": 11799, "\u0120subtle": 11800, "\u0120Unit": 11801, "natural": 11802, "\u0120survived": 11803, "\u0120flaw": 11804, "\u013a\u0127": 11805, "\u0120Holl": 11806, "\u0120deficit": 11807, "\u0120tutorial": 11808, "\u0120Chance": 11809, "\u0120arguing": 11810, "\u0120contemporary": 11811, "\u0120integration": 11812, "forward": 11813, "\u0120tum": 11814, "itis": 11815, "\u0120hiding": 11816, "\u0120Domin": 11817, "\u0120Tan": 11818, "\u0120Building": 11819, "\u0120Vin": 11820, "\u0120spokesperson": 11821, "\u0120Notes": 11822, "\u0120emerging": 11823, "\u0120preparation": 11824, "\u0120prost": 11825, "\u0120suspects": 11826, "\u0120autonom": 11827, "Description": 11828, "\u0120dealt": 11829, "\u0120Pear": 11830, "\u0120steady": 11831, "\u0120decreased": 11832, "\u0120sovere": 11833, "\u0120Clin": 11834, "\u0120gradually": 11835, "orses": 11836, "\u0120WAR": 11837, "Serv": 11838, "\u00e3\u0124\u00a2": 11839, "hr": 11840, "\u0120dirty": 11841, "\u0120Barn": 11842, "\u0120BC": 11843, "\u0120dil": 11844, "\u0120calendar": 11845, "\u0120compliance": 11846, "\u0120chamber": 11847, "bb": 11848, "\u0120passenger": 11849, "ateful": 11850, "\u0120Title": 11851, "\u0120Sydney": 11852, "\u0120Got": 11853, "\u0120darkness": 11854, "\u0120defect": 11855, "\u0120packed": 11856, "assion": 11857, "\u0120gods": 11858, "\u0120harsh": 11859, "ICK": 11860, "leans": 11861, "\u0120algorithm": 11862, "\u0120oxygen": 11863, "\u0120visits": 11864, "\u0120blade": 11865, "\u0120kilomet": 11866, "\u0120Kentucky": 11867, "\u0120killer": 11868, "Pack": 11869, "enny": 11870, "\u0120divine": 11871, "\u0120nomination": 11872, "being": 11873, "\u0120engines": 11874, "\u0120cats": 11875, "\u0120buffer": 11876, "\u0120Phill": 11877, "\u0120traff": 11878, "AGE": 11879, "\u0120tongue": 11880, "\u0120radiation": 11881, "erer": 11882, "mem": 11883, "\u0120Explicit": 11884, "\u00e9\u00be\u012f": 11885, "\u0120couples": 11886, "\u0120physics": 11887, "\u0120McK": 11888, "\u0120politically": 11889, "awks": 11890, "\u0120Bloom": 11891, "\u0120worship": 11892, "eger": 11893, "uter": 11894, "\u0120FO": 11895, "\u0120mathemat": 11896, "\u0120sentenced": 11897, "\u0120disk": 11898, "\u0120Marg": 11899, "\u0120/*": 11900, "PI": 11901, "\u0120optional": 11902, "\u0120babies": 11903, "\u0120seeds": 11904, "\u0120Scottish": 11905, "\u0120thy": 11906, "]]": 11907, "\u0120Hitler": 11908, "PH": 11909, "ngth": 11910, "\u0120recovered": 11911, "inge": 11912, "\u0120powder": 11913, "\u0120lips": 11914, "\u0120designer": 11915, "\u0120disorders": 11916, "\u0120courage": 11917, "\u0120chaos": 11918, "\"},{\"": 11919, "\u0120carrier": 11920, "bably": 11921, "High": 11922, "\u0120RT": 11923, "esity": 11924, "len": 11925, "\u0120routes": 11926, "uating": 11927, "Fil": 11928, "NOT": 11929, "wall": 11930, "sburgh": 11931, "\u0120engaging": 11932, "\u0120JavaScript": 11933, "orer": 11934, "lihood": 11935, "\u0120unions": 11936, "\u0120Federation": 11937, "\u0120Tesla": 11938, "\u0120completion": 11939, "\u0120Ta": 11940, "\u0120privilege": 11941, "\u0120Orange": 11942, "\u0120neur": 11943, "parency": 11944, "\u0120bones": 11945, "\u0120titled": 11946, "\u0120prosecutors": 11947, "\u0120ME": 11948, "\u0120engineer": 11949, "\u0120Universe": 11950, "\u0120Hig": 11951, "nie": 11952, "oard": 11953, "\u0120hearts": 11954, "\u0120Gre": 11955, "ussion": 11956, "\u0120ministry": 11957, "\u0120penet": 11958, "\u0120Nut": 11959, "\u0120Ow": 11960, "\u0120XP": 11961, "instein": 11962, "\u0120bulk": 11963, "System": 11964, "icism": 11965, "\u0120Marketable": 11966, "\u0120preval": 11967, "\u0120poster": 11968, "\u0120attending": 11969, "urable": 11970, "\u0120licensed": 11971, "\u0120Gh": 11972, "etry": 11973, "\u0120Tradable": 11974, "\u0120blast": 11975, "\u00e0\u00a4": 11976, "\u0120Titan": 11977, "elled": 11978, "die": 11979, "Have": 11980, "\u0120Flame": 11981, "\u0120profound": 11982, "\u0120participating": 11983, "\u0120anime": 11984, "\u0120Ess": 11985, "\u0120specify": 11986, "\u0120regarded": 11987, "\u0120Spell": 11988, "\u0120sons": 11989, "owned": 11990, "\u0120merc": 11991, "\u0120experimental": 11992, "lando": 11993, "hs": 11994, "\u0120Dungeon": 11995, "inos": 11996, "\u0120comply": 11997, "\u0120Systems": 11998, "arth": 11999, "\u0120seized": 12000, "local": 12001, "\u0120Girls": 12002, "udo": 12003, "oned": 12004, "\u0120Fle": 12005, "\u0120constructed": 12006, "\u0120hosted": 12007, "\u0120scared": 12008, "actic": 12009, "\u0120Islands": 12010, "\u0120MORE": 12011, "\u0120bless": 12012, "\u0120blocking": 12013, "\u0120chips": 12014, "\u0120evac": 12015, "Ps": 12016, "\u0120corporation": 12017, "\u0120ox": 12018, "\u0120lighting": 12019, "\u0120neighbors": 12020, "\u0120Ub": 12021, "aro": 12022, "\u0120beef": 12023, "\u0120Uber": 12024, "Facebook": 12025, "armed": 12026, "itate": 12027, "\u0120Rating": 12028, "\u0120Quick": 12029, "\u0120occupied": 12030, "\u0120aims": 12031, "\u0120Additionally": 12032, "\u0120Interest": 12033, "\u0120dramatically": 12034, "\u0120heal": 12035, "\u0120painting": 12036, "\u0120engineers": 12037, "MM": 12038, "\u0120Must": 12039, "\u0120quantity": 12040, "Paul": 12041, "\u0120earnings": 12042, "\u0120Posts": 12043, "stra": 12044, "\u00e3\u0125\u00bc\u00e3\u0125": 12045, "\u0120stance": 12046, "\u0120dropping": 12047, "script": 12048, "\u0120dressed": 12049, "Make": 12050, "\u0120justify": 12051, "\u0120Ltd": 12052, "\u0120prompted": 12053, "\u0120scrut": 12054, "\u0120speeds": 12055, "\u0120Giants": 12056, "omer": 12057, "\u0120Editor": 12058, "\u0120describing": 12059, "\u0120Lie": 12060, "mented": 12061, "\u0120nowhere": 12062, "ocaly": 12063, "\u0120instruction": 12064, "fortable": 12065, "\u0120entities": 12066, "\u0120cm": 12067, "\u0120Natural": 12068, "\u0120inquiry": 12069, "\u0120pressed": 12070, "izont": 12071, "forced": 12072, "\u0120raises": 12073, "\u0120Netflix": 12074, "\u0120Side": 12075, "\u0120outer": 12076, "\u0120amongst": 12077, "ims": 12078, "owski": 12079, "\u0120climb": 12080, "never": 12081, "\u0120combine": 12082, "ding": 12083, "\u0120compr": 12084, "\u0120significance": 12085, "\u0120remembered": 12086, "\u0120Nevada": 12087, "\u0120Tel": 12088, "\u0120Scar": 12089, "\u0120Warriors": 12090, "\u0120Jane": 12091, "\u0120coup": 12092, "bas": 12093, "\u0120terminal": 12094, ",-": 12095, "OH": 12096, "\u0120tension": 12097, "\u0120wings": 12098, "\u0120Myster": 12099, "\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd": 12100, "\u0120Unlike": 12101, "valid": 12102, "vironments": 12103, "\u0120Ali": 12104, "\u0120naked": 12105, "books": 12106, "\u0120Mun": 12107, "\u0120Gulf": 12108, "\u0120density": 12109, "\u0120dimin": 12110, "\u0120desperate": 12111, "\u0120presidency": 12112, "\u01201986": 12113, "hy": 12114, "IND": 12115, "\u0120unlock": 12116, "imens": 12117, "\u0120handled": 12118, "\u0120Eb": 12119, "\u0120disappeared": 12120, "\u0120genre": 12121, "\u01201988": 12122, "\u0120determination": 12123, "Stream": 12124, "iko": 12125, "apters": 12126, "\u0120acknowledge": 12127, "Jan": 12128, "\u0120capitalism": 12129, "Pat": 12130, "\u01202020": 12131, "\u0120painful": 12132, "\u0120curve": 12133, "\u0120bombs": 12134, "storm": 12135, "\u0120Metal": 12136, "encer": 12137, "\u0120Fig": 12138, "\u0120Aaron": 12139, "anches": 12140, "\u0120inspiration": 12141, "\u0120exhaust": 12142, "tains": 12143, "ashi": 12144, "\u0120descript": 12145, "\u0120ritual": 12146, "\u0120Chelsea": 12147, "\u0120promotion": 12148, "\u0120Hung": 12149, "\u0120Ward": 12150, "iva": 12151, "\u0120ET": 12152, "\u0120toss": 12153, "allow": 12154, "\u0120Francis": 12155, "Dep": 12156, "\u0120happiness": 12157, "\u0120Glass": 12158, "\u0120beta": 12159, "\u0120strengthen": 12160, "NE": 12161, "oa": 12162, "\u0120buttons": 12163, "\u0120Murray": 12164, "\u0120kicked": 12165, "Quest": 12166, "\u0120Talk": 12167, "\u0120Several": 12168, "\u0120Zero": 12169, "\u0120drone": 12170, "ulk": 12171, "\u0120cam": 12172, "\u0120Mobile": 12173, "\u0120preventing": 12174, "\u0120retro": 12175, "\u0120Ax": 12176, "\u0120cruel": 12177, "\u0120float": 12178, ".),": 12179, "\u0120filing": 12180, "\u0120Grant": 12181, "\u0120Bor": 12182, "\u0120rib": 12183, "\u0120championship": 12184, "\u0120Merc": 12185, "\u0120styles": 12186, "\u0120cake": 12187, "\u0120builds": 12188, "\u0120Self": 12189, "iox": 12190, "\u0120epic": 12191, "oyd": 12192, "Bel": 12193, "\u0120Stew": 12194, ".(": 12195, "ahu": 12196, "\u0120Beyond": 12197, "\u0120outs": 12198, "\u0120solo": 12199, "\u0120Tree": 12200, "\u0120preserve": 12201, "\u0120tub": 12202, "ARE": 12203, "roc": 12204, "\u0120Impro": 12205, "\u0120Wright": 12206, "\u0120bund": 12207, "\u0120traged": 12208, "\u0120occasional": 12209, "bian": 12210, "Second": 12211, "rons": 12212, "\u0120interactions": 12213, "formed": 12214, "sing": 12215, "\u0120owns": 12216, "\u0120hockey": 12217, "General": 12218, "\u0120logical": 12219, "\u0120expend": 12220, "\u0120escal": 12221, "\u0120Griff": 12222, "\u0120Crown": 12223, "\u0120Reserve": 12224, "\u0120stopping": 12225, "\u0120excuse": 12226, "second": 12227, "\u0120operated": 12228, "\u0120reaches": 12229, "\u0120Malays": 12230, "\u0120pollution": 12231, "\u0120Brooklyn": 12232, "\u0120delete": 12233, "\u0120hash": 12234, "Block": 12235, "aha": 12236, "\u00e2\u0122\u00b3": 12237, "\u0120shorter": 12238, "piece": 12239, ">>>": 13163, "\u0120Mormon": 13164, "tor": 13165, "\u0120particles": 13166, "\u0120Bart": 13167, "ryption": 13168, "\u0120admin": 13169, "\u0120squee": 13170, "VIDIA": 13171, "\u0120creator": 13172, "iameter": 13173, "icular": 13174, "NBC": 13175, "\u0120grabbed": 13176, "\u0120nodd": 13177, "\u0120rated": 13178, "\u0120rotation": 13179, "\u0120grasp": 13180, "\u0120excessive": 13181, "\u0120EC": 13182, "\u0120Whit": 13183, "\u0120inventory": 13184, "aults": 13185, "\u0120FB": 13186, "\u0120ecosystem": 13187, "\u0120billions": 13188, "\u0120venture": 13189, "named": 13190, "\u0120defender": 13191, "oute": 13192, "Instead": 13193, "irable": 13194, "War": 13195, "\u0120assumption": 13196, "\u0120bite": 13197, "\u0120earthqu": 13198, "tail": 13199, "space": 13200, "\u0120gifts": 13201, "boys": 13202, "\u0120inevitable": 13203, "\u0120structural": 13204, "\u0120beneficial": 13205, "\u0120compelling": 13206, "hole": 13207, "ervation": 13208, "\u0120coat": 13209, "oj": 13210, "incarn": 13211, "\u0120Years": 13212, "\u0120determining": 13213, "\u0120rhetoric": 13214, "\u0120boundaries": 13215, "\u0120whites": 13216, "Ant": 13217, "addy": 13218, ")-": 13219, "raham": 13220, "etermin": 13221, "\u0120harvest": 13222, "\u0120Conc": 13223, "\u0120laptop": 13224, "\u0120Match": 13225, "\u0120enjoying": 13226, "cca": 13227, "ollar": 13228, "\u0120trips": 13229, "\u0120addiction": 13230, "\u0120Sak": 13231, "\u0120powered": 13232, "\u0120cous": 13233, "\u0120Russians": 13234, "iere": 13235, "\u0120retrie": 13236, "quality": 13237, "\u0120differ": 13238, "\u0120kingdom": 13239, "\u0120Laur": 13240, "\u0120Capitol": 13241, "\u0120conclusions": 13242, "\u0120Altern": 13243, "\u0120Nav": 13244, "\u0120transparent": 13245, "BER": 13246, "Group": 13247, "\u0120Complete": 13248, "\u0120infer": 13249, "\u0120intrig": 13250, "\u0120insane": 13251, "RO": 13252, "ophob": 13253, "isen": 13254, "qual": 13255, "Michael": 13256, "\u0120museum": 13257, "\u0120Pope": 13258, "\u0120reset": 13259, "rative": 13260, "five": 13261, "\u0120aggreg": 13262, "ittees": 13263, "ository": 13264, "\u0120carb": 13265, "\u0120Record": 13266, "\u0120decides": 13267, "\u0120Fix": 13268, "\u0120exceptions": 13269, "\u0120Commissioner": 13270, "uns": 13271, "\u0120Environmental": 13272, "\u0120legendary": 13273, "istence": 13274, "\u0120tunnel": 13275, "km": 13276, "\u0120insult": 13277, "\u0120troll": 13278, "\u0120shake": 13279, "\u0120detention": 13280, "ques": 13281, "\u0120Chrome": 13282, "\u0120Files": 13283, "\u0120subt": 13284, "\u0120prospects": 13285, "\u0120prol": 13286, "render": 13287, "proof": 13288, "\u0120performances": 13289, "Str": 13290, "\u0120href": 13291, "ername": 13292, "\u0120achievement": 13293, "\u0120fut": 13294, "Full": 13295, "\u0120Leban": 13296, "google": 13297, "\u00e3\u0125\u012a": 13298, "ampa": 13299, "Maybe": 13300, "\u0120projected": 13301, "\u0120Emb": 13302, "\u0120colleg": 13303, "\u0120awards": 13304, "\u0120\u00e2\u0136": 13305, "Gold": 13306, "\u0120Blake": 13307, "\u0120Raj": 13308, "ifting": 13309, "\u0120pending": 13310, "\u0120instinct": 13311, "\u0120developments": 13312, "Connect": 13313, "\u0120Mand": 13314, "\u0120WITH": 13315, "\u0120Philippines": 13316, "profile": 13317, "\u0120altogether": 13318, "\u0120Bund": 13319, "\u0120TD": 13320, "oooo": 13321, "amped": 13322, "iph": 13323, "\u0120steam": 13324, "\u0120oldest": 13325, "\u0120detection": 13326, "ulpt": 13327, "\u0120\u00e7": 13328, "\u0120Wayne": 13329, "2006": 13330, "fa": 13331, "\u0120circles": 13332, "\u0120Fu": 13333, "\u0120donors": 13334, "appropriate": 13335, "\u0120Dakota": 13336, "jamin": 13337, "\u0120motivated": 13338, "\u0120purchases": 13339, "\u0120Louisiana": 13340, "\u0120Spl": 13341, "\u0120globe": 13342, "\u0120105": 13343, "zip": 13344, "call": 13345, "\u0120departments": 13346, "\u0120sustainable": 13347, "105": 13348, "\u0120OP": 13349, "ifiers": 13350, "\u0120prevented": 13351, "\u0120incomp": 13352, "\u0120Commander": 13353, "\u0120dominated": 13354, "\u0120\u00c2\u00bb": 13355, "\u0120invested": 13356, "\u0120complexity": 13357, "\u0120incl": 13358, "\u0120ensuring": 13359, "\u0120realm": 13360, "ync": 13361, "\u0120Independent": 13362, "rained": 13363, "\u0120Jen": 13364, "\u0120Flight": 13365, "\u0120athe": 13366, "\u0120speculation": 13367, "\u0120TE": 13368, "ocate": 13369, "tic": 13370, "\u0120plaint": 13371, "herry": 13372, "\u0120toy": 13373, "\u0120111": 13374, "\u0120plates": 13375, "status": 13376, "\u0120Isa": 13377, "\u0120devoted": 13378, "Cop": 13379, "\u0120ES": 13380, "255": 13381, "urrency": 13382, "Main": 13383, "\u0120slaves": 13384, "\u0120pepper": 13385, "\u0120quotes": 13386, "\u0120ceiling": 13387, "\u0120Fish": 13388, "\u0120transformation": 13389, "\u0120fraction": 13390, "\u0120advantages": 13391, "\u0120toile": 13392, "\u0120stunning": 13393, "\u0120moist": 13394, "breaking": 13395, "si": 13396, "\u0120Location": 13397, "\u0120Medium": 13398, "\u0120texts": 13399, "\u0120ugly": 13400, "\u0120bio": 13401, ".\u00e2\u0122\u0136": 13402, "\u0120Based": 13403, "\u0120trains": 13404, "\u0120Wing": 13405, "\u0120Ancient": 13406, "\u0120Records": 13407, "\u0120Hope": 13408, "Special": 13409, "adesh": 13410, "obi": 13411, "[/": 13412, "\u0120temporarily": 13413, "Ver": 13414, "hu": 13415, "oser": 13416, "\u0120overnight": 13417, "\u0120mamm": 13418, "\u0120Treasury": 13419, "\u0120Venezuel": 13420, "\u0120Mega": 13421, "\u0120tar": 13422, "\u0120expects": 13423, "black": 13424, "orph": 13425, "\\\\\\\\": 13426, "\u0120acceptance": 13427, "\u0120radar": 13428, "sis": 13429, "\u0120junior": 13430, "\u0120frames": 13431, "\u0120observation": 13432, "acies": 13433, "Power": 13434, "\u0120Advanced": 13435, "Mag": 13436, "ologically": 13437, "\u0120Mechan": 13438, "\u0120sentences": 13439, "\u0120analysts": 13440, "aughters": 13441, "forcement": 13442, "\u0120vague": 13443, "\u0120clause": 13444, "\u0120directors": 13445, "\u0120evaluate": 13446, "\u0120cabinet": 13447, "Matt": 13448, "\u0120Classic": 13449, "Ang": 13450, "\u0120cler": 13451, "\u0120Buck": 13452, "\u0120researcher": 13453, "\u0120160": 13454, "\u0120poorly": 13455, "\u0120experiencing": 13456, "\u0120Ped": 13457, "\u0120Manhattan": 13458, "\u0120freed": 13459, "\u0120themes": 13460, "advant": 13461, "\u0120nin": 13462, "\u0120praise": 13463, "104": 13464, "\u0120Libya": 13465, "best": 13466, "\u0120trusted": 13467, "\u0120cease": 13468, "\u0120dign": 13469, "Direct": 13470, "\u0120bombing": 13471, "\u0120migration": 13472, "\u0120Sciences": 13473, "\u0120municipal": 13474, "\u0120Average": 13475, "\u0120glory": 13476, "\u0120revealing": 13477, "\u0120arena": 13478, "\u0120uncertainty": 13479, "\u0120battlefield": 13480, "iao": 13481, "God": 13482, "\u0120cinem": 13483, "rape": 13484, "elle": 13485, "apons": 13486, "\u0120listing": 13487, "\u0120waited": 13488, "\u0120spotted": 13489, "keley": 13490, "\u0120Audio": 13491, "eor": 13492, "arding": 13493, "idding": 13494, "igma": 13495, "\u0120Neg": 13496, "\u0120lone": 13497, "\u0120----": 13498, "exe": 13499, "deg": 13500, "\u0120transf": 13501, "\u0120wash": 13502, "\u0120slavery": 13503, "\u0120exploring": 13504, "\u0120WW": 13505, "atson": 13506, "\u0120encl": 13507, "lies": 13508, "\u0120Creek": 13509, "\u0120wooden": 13510, "Manager": 13511, "\u0120Brand": 13512, "ummy": 13513, "\u0120Arthur": 13514, "\u0120bureaucr": 13515, "\u0120blend": 13516, "arians": 13517, "Further": 13518, "\u0120supposedly": 13519, "\u0120winds": 13520, "\u01201979": 13521, "\u0120gravity": 13522, "\u0120analyses": 13523, "\u0120Travel": 13524, "\u0120Veter": 13525, "\u0120dumb": 13526, "\u0120alternate": 13527, "gal": 13528, "\u0120consumed": 13529, "\u0120effectiveness": 13530, ".''": 13531, "\u0120paths": 13532, "onda": 13533, "LA": 13534, "\u0120Strong": 13535, "\u0120enables": 13536, "\u0120escaped": 13537, "\u0120\"\"": 13538, "\u0120112": 13539, "\u01201983": 13540, "\u0120smiled": 13541, "\u0120tendency": 13542, "Fire": 13543, "\u0120pars": 13544, "\u0120Roc": 13545, "\u0120lake": 13546, "\u0120fitness": 13547, "\u0120Ath": 13548, "\u0120Horn": 13549, "\u0120hier": 13550, "\u0120impose": 13551, "mother": 13552, "\u0120pension": 13553, "icut": 13554, "borne": 13555, "iciary": 13556, "._": 13557, "\u0120SU": 13558, "\u0120polar": 13559, "isy": 13560, "engu": 13561, "itialized": 13562, "ATA": 13563, "write": 13564, "\u0120exercises": 13565, "\u0120Diamond": 13566, "otypes": 13567, "\u0120harmful": 13568, "onz": 13569, "\u0120printing": 13570, "story": 13571, "\u0120expertise": 13572, "\u0120Ger": 13573, "\u0120tragedy": 13574, "\u0120Fly": 13575, "\u0120divid": 13576, "ampire": 13577, "stock": 13578, "Mem": 13579, "\u0120reign": 13580, "\u0120unve": 13581, "\u0120amend": 13582, "\u0120Prophet": 13583, "\u0120mutual": 13584, "\u0120Fac": 13585, "\u0120replacing": 13586, "Har": 13587, "\u0120Circuit": 13588, "\u0120throat": 13589, "\u0120Shot": 13590, "\u0120batteries": 13591, "\u0120toll": 13592, "\u0120addressing": 13593, "\u0120Medicaid": 13594, "\u0120pupp": 13595, "\u0120Nar": 13596, "olk": 13597, "\u0120equity": 13598, "MR": 13599, "\u0120Hispan": 13600, "\u0120Large": 13601, "mid": 13602, "Dev": 13603, "\u0120exped": 13604, "\u0120demo": 13605, "\u0120Marshall": 13606, "ergus": 13607, "\u0120fiber": 13608, "\u0120divorce": 13609, "\u0120Create": 13610, "\u0120slower": 13611, "\u0120Parker": 13612, "\u0120Student": 13613, "\u0120Training": 13614, "Return": 13615, "\u0120Tru": 13616, "\u0120cub": 13617, "\u0120Reached": 13618, "\u0120panic": 13619, "\u0120quarters": 13620, "\u0120rect": 13621, "\u0120treating": 13622, "\u0120rats": 13623, "\u0120Christianity": 13624, "oler": 13625, "\u0120sacred": 13626, "\u0120declare": 13627, "ulative": 13628, "eting": 13629, "\u0120delivering": 13630, "estone": 13631, "\u0120tel": 13632, "\u0120Larry": 13633, "\u0120meta": 13634, "accept": 13635, "artz": 13636, "\u0120Roger": 13637, "handed": 13638, "\u0120header": 13639, "\u0120trapped": 13640, "\u0120Century": 13641, "\u0120knocked": 13642, "\u0120Oxford": 13643, "\u0120survivors": 13644, "bot": 13645, "\u0120demonstration": 13646, "\u0120dirt": 13647, "\u0120assists": 13648, "OME": 13649, "\u0120Draft": 13650, "ortunate": 13651, "folio": 13652, "pered": 13653, "usters": 13654, "gt": 13655, "\u0120Lock": 13656, "\u0120judicial": 13657, "verted": 13658, "\u0120secured": 13659, "outing": 13660, "\u0120Books": 13661, "\u0120hosting": 13662, "\u0120lifted": 13663, "length": 13664, "\u0120jer": 13665, "\u0120wheels": 13666, "\u0120Range": 13667, "umbnails": 13668, "\u0120diagnosis": 13669, "tech": 13670, "\u0120Stewart": 13671, "\u0120Pract": 13672, "\u0120nationwide": 13673, "\u0120dear": 13674, "\u0120obligations": 13675, "\u0120grows": 13676, "\u0120mandatory": 13677, "\u0120suspicious": 13678, "!'": 13679, "Apr": 13680, "Great": 13681, "\u0120mortgage": 13682, "\u0120prosecutor": 13683, "\u0120editorial": 13684, "\u0120Kr": 13685, "\u0120processed": 13686, "ungle": 13687, "\u0120flexibility": 13688, "Earlier": 13689, "\u0120Cart": 13690, "\u0120Sug": 13691, "\u0120focuses": 13692, "\u0120startup": 13693, "\u0120breach": 13694, "\u0120Tob": 13695, "cycle": 13696, "\u00e3\u0122\u012e": 13697, "rose": 13698, "\u0120bizarre": 13699, "\u00e3\u0122\u012f": 13700, "\u0120vegetables": 13701, "$$": 13702, "\u0120retreat": 13703, "oshi": 13704, "\u0120Shop": 13705, "\u0120Ground": 13706, "\u0120Stop": 13707, "\u0120Hawaii": 13708, "\u0120Ay": 13709, "Perhaps": 13710, "\u0120Beaut": 13711, "uffer": 13712, "enna": 13713, "\u0120productivity": 13714, "Fixed": 13715, "control": 13716, "\u0120absent": 13717, "\u0120Campaign": 13718, "Green": 13719, "\u0120identifying": 13720, "\u0120regret": 13721, "\u0120promoted": 13722, "\u0120Seven": 13723, "\u0120eru": 13724, "neath": 13725, "aughed": 13726, "\u0120Pin": 13727, "\u0120Living": 13728, "Cost": 13729, "omatic": 13730, "mega": 13731, "\u0120Nig": 13732, "ocy": 13733, "\u0120inbox": 13734, "\u0120empire": 13735, "\u0120horizont": 13736, "\u0120branches": 13737, "\u0120metaph": 13738, "Active": 13739, "edi": 13740, "\u0120Film": 13741, "\u0120Something": 13742, "\u0120mods": 13743, "incial": 13744, "\u0120Original": 13745, "Gen": 13746, "\u0120spirits": 13747, "\u0120earning": 13748, "Hist": 13749, "\u0120riders": 13750, "\u0120sacrific": 13751, "MT": 13752, "\u0120VA": 13753, "\u0120Salt": 13754, "\u0120occupation": 13755, "\u0120Mi": 13756, "\u0120disg": 13757, "lict": 13758, "\u0120nit": 13759, "\u0120nodes": 13760, "eem": 13761, "\u0120Pier": 13762, "\u0120hatred": 13763, "psy": 13764, "\u00e3\u0125\u012b": 13765, "\u0120theater": 13766, "\u0120sophisticated": 13767, "\u0120defended": 13768, "\u0120besides": 13769, "\u0120thoroughly": 13770, "\u0120Medicare": 13771, "\u0120blamed": 13772, "arently": 13773, "\u0120crying": 13774, "FOR": 13775, "priv": 13776, "\u0120singing": 13777, "\u0120Il": 13778, "\u0120cute": 13779, "oided": 13780, "olitical": 13781, "\u0120Neuro": 13782, "\u00e5\u00a4": 13783, "\u0120donation": 13784, "\u0120Eagles": 13785, "\u0120Give": 13786, "Tom": 13787, "\u0120substantially": 13788, "\u0120License": 13789, "\u0120Ja": 13790, "\u0120grey": 13791, "\u0120Animal": 13792, "\u0120ER": 13793, "\u0120Und": 13794, "\u0120keen": 13795, "\u0120conclude": 13796, "\u0120Mississippi": 13797, "Engine": 13798, "\u0120Studios": 13799, "Press": 13800, "overs": 13801, "llers": 13802, "\u0120350": 13803, "\u0120Rangers": 13804, "\u0120rou": 13805, "erto": 13806, "Ep": 13807, "issa": 13808, "ivan": 13809, "\u0120seal": 13810, "\u0120Regist": 13811, "display": 13812, "\u0120weaken": 13813, "uum": 13814, "\u0120Commons": 13815, "\u0120Say": 13816, "\u0120cultures": 13817, "\u0120laughed": 13818, "\u0120slip": 13819, "\u0120treatments": 13820, "izable": 13821, "mart": 13822, "\u0120Rice": 13823, "\u0120beast": 13824, "\u0120obesity": 13825, "\u0120Laure": 13826, "iga": 13827, "Which": 13828, "holder": 13829, "\u0120elderly": 13830, "\u0120pays": 13831, "\u0120complained": 13832, "\u0120crop": 13833, "\u0120proc": 13834, "\u0120explosive": 13835, "\u0120Fan": 13836, "\u0120Arsenal": 13837, "Author": 13838, "eful": 13839, "\u0120meals": 13840, "\u0120(-": 13841, "idays": 13842, "\u0120imagination": 13843, "\u0120annually": 13844, "\u0120ms": 13845, "asures": 13846, "Head": 13847, "ikh": 13848, "matic": 13849, "\u0120boyfriend": 13850, "\u0120Computer": 13851, "\u0120bump": 13852, "\u0120surge": 13853, "\u0120Craig": 13854, "\u0120Kirk": 13855, "Del": 13856, "mediate": 13857, "\u0120scenarios": 13858, "\u0120Mut": 13859, "\u0120Stream": 13860, "\u0120competitors": 13861, "\u00d9\u0126": 13862, "\u0120Stanford": 13863, "\u0120Resources": 13864, "azed": 13865, "bage": 13866, "\u0120organis": 13867, "\u0120Release": 13868, "\u0120separately": 13869, "\u0120habits": 13870, "\u0120measurements": 13871, "\u0120Close": 13872, "\u0120accompany": 13873, "\u0120gly": 13874, "\u0120tang": 13875, "\u0120Rou": 13876, "\u0120plugin": 13877, "\u0120convey": 13878, "\u0120Challenge": 13879, "oots": 13880, "jan": 13881, "\u0120curs": 13882, "\u0120Relations": 13883, "keeper": 13884, "\u0120approaching": 13885, "ping": 13886, "Speaking": 13887, "\u0120arrangement": 13888, "\u0120VI": 13889, "arettes": 13890, "\u0120affecting": 13891, "\u0120permits": 13892, "because": 13893, "\u0120useless": 13894, "\u0120Hus": 13895, "!!!!": 13896, "\u0120destroying": 13897, "Unfortunately": 13898, "\u0120fascinating": 13899, "Sem": 13900, "\u0120electoral": 13901, "\u0120transparency": 13902, "\u0120Chaos": 13903, "\u0120volunteer": 13904, "\u0120statistical": 13905, "\u0120activated": 13906, "rox": 13907, "Web": 13908, "HE": 13909, "\u0120Hampshire": 13910, "isive": 13911, "Map": 13912, "\u0120trash": 13913, "\u0120Lawrence": 13914, "stick": 13915, "Cr": 13916, "\u0120rings": 13917, "EXT": 13918, "\u0120operational": 13919, "opes": 13920, "Does": 13921, "\u0120Evans": 13922, "\u0120witnessed": 13923, "Port": 13924, "\u0120launching": 13925, "econom": 13926, "wear": 13927, "\u0120Particip": 13928, "umm": 13929, "cules": 13930, "\u0120RAM": 13931, "\u0120Tun": 13932, "\u0120assured": 13933, "\u0120binary": 13934, "\u0120betray": 13935, "\u0120exploration": 13936, "\u0120Fel": 13937, "\u0120admission": 13938, "itated": 13939, "Sy": 13940, "\u0120avoided": 13941, "\u0120Simulator": 13942, "\u0120celebrated": 13943, "\u0120Electric": 13944, "\u00a5\u0140": 13945, "\u0120cluster": 13946, "itzerland": 13947, "health": 13948, "Line": 13949, "\u0120Nash": 13950, "aton": 13951, "\u0120spare": 13952, "\u0120enterprise": 13953, "\u0120DIS": 13954, "cludes": 13955, "\u0120flights": 13956, "\u0120regards": 13957, "\u0120\u00c3\u0139": 13958, "half": 13959, "\u0120trucks": 13960, "\u0120contacts": 13961, "\u0120uncons": 13962, "\u0120Climate": 13963, "\u0120immense": 13964, "NEW": 13965, "occ": 13966, "ective": 13967, "\u0120embod": 13968, "\u0120patrol": 13969, "\u0120beside": 13970, "\u0120viable": 13971, "\u0120creep": 13972, "\u0120triggered": 13973, "verning": 13974, "\u0120comparable": 13975, "ql": 13976, "\u0120gaining": 13977, "asses": 13978, "\u0120();": 13979, "\u0120Grey": 13980, "\u0120MLS": 13981, "sized": 13982, "\u0120prosper": 13983, "\"?": 13984, "\u0120polling": 13985, "\u0120shar": 13986, "\u0120RC": 13987, "\u0120firearm": 13988, "orient": 13989, "\u0120fence": 13990, "\u0120variations": 13991, "giving": 13992, "\u0120Pi": 13993, "ospel": 13994, "\u0120pledge": 13995, "\u0120cure": 13996, "\u0120spy": 13997, "\u0120violated": 13998, "\u0120rushed": 13999, "\u0120stroke": 14000, "\u0120Blog": 14001, "sels": 14002, "\u0120Ec": 14003, ",''": 14004, "\u0120pale": 14005, "\u0120Collins": 14006, "terror": 14007, "\u0120Canadians": 14008, "\u0120tune": 14009, "\u0120laboratory": 14010, "\u0120nons": 14011, "tarian": 14012, "\u0120disability": 14013, "\u0120Gam": 14014, "\u0120singer": 14015, "alg": 14016, "\u0120Senior": 14017, "\u0120traded": 14018, "\u0120Warrior": 14019, "\u0120infring": 14020, "\u0120Franklin": 14021, "\u0120strain": 14022, "\u0120Swedish": 14023, "\u0120seventh": 14024, "\u0120Benn": 14025, "\u0120Tell": 14026, "\u0120syndrome": 14027, "\u0120wondered": 14028, "iden": 14029, "++++": 14030, "igo": 14031, "\u0120purple": 14032, "\u0120journalism": 14033, "\u0120rebel": 14034, "\u0120fu": 14035, "blog": 14036, "\u0120invite": 14037, "rencies": 14038, "\u0120Contact": 14039, "Israel": 14040, "\u0120Content": 14041, "\u0120cheer": 14042, "\u0120bedroom": 14043, "\u0120Engineering": 14044, "\u0120Queens": 14045, "\u0120dwell": 14046, "\u0120PlayStation": 14047, "\u0120Dim": 14048, "\u0120Colon": 14049, "lr": 14050, "\u0120operates": 14051, "\u0120motivation": 14052, "USA": 14053, "astered": 14054, "Core": 14055, "\u0120Truth": 14056, "olo": 14057, "OSE": 14058, "\u0120Memory": 14059, "\u0120predec": 14060, "\u0120anarch": 14061, "\u01201920": 14062, "\u0120Yam": 14063, "\u00c3\u00a8": 14064, "bid": 14065, "\u0120grateful": 14066, "\u0120excitement": 14067, "\u0120treasure": 14068, "\u0120longest": 14069, "ctive": 14070, "\u0120deserves": 14071, "\u0120reserves": 14072, "\u0120cops": 14073, "\u0120Ottawa": 14074, "\u0120Egyptian": 14075, "anked": 14076, "\u0120artif": 14077, "\u0120hypothesis": 14078, ":/": 14079, "\u0120purchasing": 14080, "\u0120lovely": 14081, "HP": 14082, "\u0120divide": 14083, "\u0120strictly": 14084, "\u0120questioning": 14085, "\u0120taxpayers": 14086, "\u0120Joy": 14087, "\u0120rolls": 14088, "\u0120Heavy": 14089, "\u0120ports": 14090, "\u0120magnetic": 14091, "\u0120inflamm": 14092, "\u0120brush": 14093, "tics": 14094, "\u00e2\u012a\u0134": 14095, "\u0120bottles": 14096, "ppy": 14097, "\u0120padd": 14098, "\u00e3\u0124\u00af": 14099, "million": 14100, "\u0120devastating": 14101, "\u0120compiled": 14102, "\u0120medication": 14103, "\u0120twelve": 14104, "\u0120Perry": 14105, "Space": 14106, "imb": 14107, "your": 14108, "\u0120leaked": 14109, "\u0120Tar": 14110, "\u0120unity": 14111, "\u0120infected": 14112, "\u0120traveled": 14113, "IDE": 14114, "\u0120McDonald": 14115, "txt": 14116, "\u0120Princ": 14117, "\u0120interven": 14118, "\u0120Taiwan": 14119, "\u0120Pow": 14120, "\u0120bearing": 14121, "\u0120Thread": 14122, "\u0120zones": 14123, "izards": 14124, "unks": 14125, "Chapter": 14126, "llor": 14127, "\u0120\u00c2\u00b7": 14128, "\u0120wounds": 14129, "\u0120discretion": 14130, "\u0120succeeded": 14131, "iking": 14132, "\u0120iconic": 14133, "Call": 14134, "\u0120screening": 14135, "\u0120Mis": 14136, "icts": 14137, "\u0120ministers": 14138, "\u0120separation": 14139, "Player": 14140, "\u0120bip": 14141, "\u0120beloved": 14142, "\u0120counting": 14143, "\u0120Eye": 14144, "around": 14145, "inging": 14146, "\u0120tablet": 14147, "\u0120offence": 14148, "inance": 14149, "have": 14150, "\u0120Info": 14151, "\u0120Ninja": 14152, "\u0120protective": 14153, "\u0120Cass": 14154, "Mac": 14155, "\u0120Quality": 14156, "North": 14157, "\u0120ic": 14158, "\u0120Cuba": 14159, "\u0120Chronicle": 14160, "\u0120Property": 14161, "\u0120fastest": 14162, "otos": 14163, "\u0120Germ": 14164, "OWN": 14165, "\u0120boom": 14166, "\u0120Stanley": 14167, "erguson": 14168, "\u0120clever": 14169, "\u0120enters": 14170, "mode": 14171, "terior": 14172, "\u0120Sens": 14173, "\u0120linear": 14174, "ARK": 14175, "\u0120comparing": 14176, "\u0120purely": 14177, "\u0120safer": 14178, "\u0120Potter": 14179, "\u0120cups": 14180, "RT": 14181, "\u0120gluc": 14182, "\u0120attributed": 14183, "\u0120dupl": 14184, "\u0120Pap": 14185, "\u0120precious": 14186, "\u0120pa": 14187, "ictionary": 14188, "\u0120Tig": 14189, "\u0120Too": 14190, "olutions": 14191, "stan": 14192, "\u0120robots": 14193, "\u0120lobb": 14194, "\u0120statute": 14195, "\u0120prevention": 14196, "western": 14197, "160": 14198, "\u0120Active": 14199, "\u0120Maria": 14200, "hal": 14201, "None": 14202, "ellar": 14203, "\u0120KB": 14204, "\u0120Partners": 14205, "\u0120Single": 14206, "\u0120Following": 14207, "ango": 14208, "acious": 14209, "\u0120thou": 14210, "\u0120kg": 14211, "\u0120influential": 14212, "\u0120Friends": 14213, "Sur": 14214, "ainted": 14215, "\u0120forums": 14216, "\u0120starter": 14217, "\u0120citizenship": 14218, "\u0120Election": 14219, "onge": 14220, "otation": 14221, "osph": 14222, ";;;;": 14223, "utical": 14224, "pur": 14225, "eren": 14226, "\u0120accusations": 14227, "bitious": 14228, "abbit": 14229, "\u0120Ord": 14230, "Posted": 14231, "irk": 14232, "\u0120sensitivity": 14233, "iche": 14234, "\u0120Amy": 14235, "\u0120Fab": 14236, "\u0120summit": 14237, "\u0120pedest": 14238, "\u0120rubber": 14239, "\u0120agricultural": 14240, "\u0120cancel": 14241, "AE": 14242, "\u0120inaug": 14243, "\u0120contam": 14244, "\u0120firmly": 14245, "iw": 14246, "stage": 14247, "\u0120Kan": 14248, "\u0120tier": 14249, "\u0120invention": 14250, "\u0120translated": 14251, "\u0120Rules": 14252, "Box": 14253, "Twitter": 14254, "IDS": 14255, "\u0120pizza": 14256, "\u0120debug": 14257, "\u0120Drop": 14258, "vs": 14259, "\u0120horses": 14260, "big": 14261, "\u0120boring": 14262, "\u0120hood": 14263, "\u0120McCain": 14264, "atched": 14265, "\u0120Bros": 14266, "\u0120skip": 14267, "\u0120essay": 14268, "stat": 14269, "\u0120Legends": 14270, "\u0120ammunition": 14271, "auc": 14272, "\u0120shooter": 14273, "\u0120unh": 14274, "\u0120supplied": 14275, "\u0120generic": 14276, "\u0120SK": 14277, "iban": 14278, "yrics": 14279, "\u0120255": 14280, "\u0120climbing": 14281, "Former": 14282, "\u0120flip": 14283, "\u0120jumping": 14284, "\u0120frustration": 14285, "\u0120Terry": 14286, "\u0120neighborhoods": 14287, "\u0120median": 14288, "bean": 14289, "\u0120brains": 14290, "Following": 14291, "\u0120shaped": 14292, "\u0120draws": 14293, "\u0120altered": 14294, "Jack": 14295, "\u0120recipes": 14296, "\u0120skilled": 14297, "wealth": 14298, "achi": 14299, "election": 14300, "\u0120behaviors": 14301, "deals": 14302, "\u0120Until": 14303, "Fe": 14304, "\u0120declaration": 14305, "marks": 14306, "\u0120Between": 14307, "celona": 14308, "\u0120reson": 14309, "\u0120bubble": 14310, "Among": 14311, "\u0120imperial": 14312, "GS": 14313, "\u0120feminist": 14314, "2005": 14315, "\u0120Kyle": 14316, "\u0120accounting": 14317, "\u0120Tele": 14318, "\u0120Tyr": 14319, "\u0120connecting": 14320, "\u0120rehab": 14321, "\u0120Pred": 14322, "sim": 14323, "\u0120meantime": 14324, "\u0120physician": 14325, "MW": 14326, "\u0120Campbell": 14327, "\u0120Brandon": 14328, "\u0120contributing": 14329, "\u0120Rule": 14330, "\u0120Weight": 14331, "\u0120Nap": 14332, "\u0120interactive": 14333, "\u0120vag": 14334, "\u0120helmet": 14335, "\u0120Comb": 14336, "four": 14337, "\u0120shipped": 14338, "\u0120completing": 14339, "\u0120PD": 14340, "PDATE": 14341, "\u0120spreading": 14342, "\u0120scary": 14343, "erving": 14344, "\u0120Gas": 14345, "\u0120frank": 14346, "school": 14347, "\u0120romantic": 14348, "\u0120stabil": 14349, "Rob": 14350, "\u0120accurately": 14351, "\u0120acute": 14352, "\u0120Hann": 14353, "\u0120symbols": 14354, "\u0120civilization": 14355, "\u0120AW": 14356, "\u0120lightning": 14357, "\u0120considers": 14358, "\u0120venue": 14359, "\u0120\u00d7": 14360, "\u0120oven": 14361, "\u0120SF": 14362, "his": 14363, "\u0120nu": 14364, "\u0120Learn": 14365, "\u0120peoples": 14366, "\u0120std": 14367, "\u0120slee": 14368, "\u0120slic": 14369, "\u0120Statistics": 14370, "\u0120corners": 14371, "\u0120Baker": 14372, "\u0120:)": 14373, "mentation": 14374, "olver": 14375, "\u0120laughing": 14376, "\u0120Todd": 14377, "onde": 14378, "\u0120Hills": 14379, "\u0120nuts": 14380, "\u0120Woman": 14381, "plane": 14382, "\u0120liver": 14383, "\u0120Inside": 14384, "Sorry": 14385, "\u0120agrees": 14386, "\u0120fundament": 14387, "\u0120Fisher": 14388, "\u0120auction": 14389, "\u0120threads": 14390, "glas": 14391, "\u0120Basic": 14392, "\u0120Nat": 14393, "\u0120lacking": 14394, "\u0120celebration": 14395, "ju": 14396, "\u0120silly": 14397, "Euro": 14398, "\u0120tatt": 14399, "ighty": 14400, "controlled": 14401, "Test": 14402, "\u0120Singh": 14403, "\u0120rage": 14404, "\u0120rhyth": 14405, "offic": 14406, "\u0120Phantom": 14407, "\u0120headlines": 14408, "\u0120responding": 14409, "\u0120Morning": 14410, "\u0120vitamin": 14411, "\u0120boots": 14412, "\u0120Site": 14413, "alin": 14414, "pi": 14415, "\u0120viral": 14416, "\u0120UC": 14417, "DER": 14418, "\u0120Sex": 14419, "\u0120stocks": 14420, "current": 14421, "\u0120churches": 14422, "\u0120Rare": 14423, "\u0120Murphy": 14424, "\u0120denial": 14425, "\u0120Gaming": 14426, "\u0120toug": 14427, "\u0120nick": 14428, "\u0120makers": 14429, "\u0120Ronald": 14430, "\u0120generous": 14431, "\u0120Doc": 14432, "\u0120Morris": 14433, "\u0120transformed": 14434, "\u0120Normal": 14435, "\u0120104": 14436, "\u0120Kickstarter": 14437, "\u0120Upon": 14438, "Online": 14439, "\u0120IRS": 14440, "\u0120wrap": 14441, "\u0120loving": 14442, "\u0120arrives": 14443, "\u0120Due": 14444, "\u0120heter": 14445, "\u0120Made": 14446, "\u0120rental": 14447, "\u0120belongs": 14448, "\u0120attorneys": 14449, "\u0120crops": 14450, "\u0120matched": 14451, "ulum": 14452, "oline": 14453, "109": 14454, "\u0120dispar": 14455, "\u0120buyers": 14456, "\u0120Cambridge": 14457, "\u0120ethics": 14458, "roups": 14459, "\u0120justified": 14460, "\u0120marginal": 14461, "\u0120respected": 14462, "winning": 14463, "\u0120nodded": 14464, "\u0120Serge": 14465, "\u0120Former": 14466, "Craft": 14467, "################": 14468, "\u0120Warner": 14469, "\u0120dash": 14470, "ete": 14471, "\u0120entert": 14472, "\u0120Escape": 14473, "outheast": 14474, "\u0120knees": 14475, "\u0120Bomb": 14476, "\u0120rug": 14477, "Pass": 14478, "\u0120attitudes": 14479, "government": 14480, "\u0120Prior": 14481, "\u0120qualities": 14482, "\u0120notification": 14483, "\u0120Phone": 14484, "lie": 14485, "\u0120anticipated": 14486, "\u0120Combat": 14487, "\u0120Barry": 14488, "\u01201982": 14489, "Users": 14490, "oner": 14491, "\u0120computing": 14492, "\u0120Connecticut": 14493, "\u0120lesser": 14494, "\u0120peers": 14495, "\u0120Cu": 14496, "\u0120technically": 14497, "\u0120submission": 14498, "\u0120Universal": 14499, "\u0120manually": 14500, "ourge": 14501, "\u0120respondents": 14502, "\u0120BTC": 14503, "\u0120Host": 14504, "\u0120fare": 14505, "\u0120Bird": 14506, "\u0120receipt": 14507, "also": 14508, "\u0120jack": 14509, "\u0120agriculture": 14510, "\u0120skull": 14511, "\u0120!=": 14512, "\u0120passive": 14513, "\u0120CI": 14514, "\u0120societies": 14515, "\u0120reminded": 14516, "\u0120interference": 14517, "Buy": 14518, "\u0120\u00e2\u013e": 14519, "gon": 14520, "\u0120scrutiny": 14521, "\u0120Witch": 14522, "\u0120conducting": 14523, "\u0120\u00e3\u0125": 14524, "\u0120exchanges": 14525, "\u0120Mitchell": 14526, "\u0120inhabit": 14527, "\u0120twist": 14528, "BD": 14529, "\u0120wherever": 14530, "groupon": 14531, "\u0120jokes": 14532, "\u0120Benjamin": 14533, "\u0120Random": 14534, "frame": 14535, "\u0120Lions": 14536, "\u0120highlighted": 14537, "\u0120Arkansas": 14538, "Ent": 14539, "\u0120pile": 14540, "\u0120prelim": 14541, "gs": 14542, "minded": 14543, "\u0120felony": 14544, "\u0120GA": 14545, "\u0120Luck": 14546, "\u0120practically": 14547, "\u0120Bos": 14548, "\u0120actress": 14549, "Dam": 14550, "\u0120Bou": 14551, "\u0120visa": 14552, "\u0120embedded": 14553, "\u0120hybrid": 14554, "\u0120earliest": 14555, "\u0120sooner": 14556, "social": 14557, "\u0120HA": 14558, "\u0120steep": 14559, "\u0120disadvant": 14560, "\u0120exploit": 14561, "\u0120Egg": 14562, "\u0120Ultra": 14563, "\u0120necessity": 14564, "Local": 14565, "iege": 14566, "\u0120dated": 14567, "\u0120masses": 14568, "\u0120subscription": 14569, "pless": 14570, "\u0120anonym": 14571, "\u0120presumably": 14572, "Blue": 14573, "Their": 14574, "asketball": 14575, "\u0120Philip": 14576, "\u0120comed": 14577, "loaded": 14578, "rane": 14579, "\u0120reflection": 14580, "China": 14581, "\u0120extends": 14582, "\u0120forming": 14583, "\u0120unders": 14584, "2001": 14585, "\u0120grat": 14586, "\u0120concentrations": 14587, "\u0120insulin": 14588, "\u0120secular": 14589, "\u0120whilst": 14590, "\u0120winners": 14591, "Advertisements": 14592, "\u0120deliberately": 14593, "\u0120Working": 14594, "\u0120sink": 14595, "etics": 14596, "dale": 14597, "\u0120mandate": 14598, "\u0120gram": 14599, "\u0120vacation": 14600, "\u0120warnings": 14601, "ripp": 14602, "\u0120THAT": 14603, "\u0120commentary": 14604, "\u0120intu": 14605, "\u0120aest": 14606, "\u0120reasoning": 14607, "\u0120breakdown": 14608, "\u0120Zombie": 14609, "\u0120-->": 14610, "\u0120Political": 14611, "cott": 14612, "\u0120thrust": 14613, "\u0120technological": 14614, "\u0120deciding": 14615, "\u0120trafficking": 14616, "Long": 14617, "Welcome": 14618, "prising": 14619, "\u0120Communications": 14620, "\u0120endors": 14621, "\u0120swift": 14622, "\u0120metabol": 14623, "coins": 14624, "resa": 14625, "\u0120HTTP": 14626, "\u0120enroll": 14627, "\u0120Happy": 14628, "usr": 14629, "intage": 14630, "\u0120[\"": 14631, "uably": 14632, "\u0120Material": 14633, "\u0120repeal": 14634, "Sept": 14635, "kh": 14636, "\u0120Modi": 14637, "\u0120underneath": 14638, "\u0120IL": 14639, "shore": 14640, "\u0120diagnosed": 14641, "aceutical": 14642, "\u0120shower": 14643, "aux": 14644, "\u0120Switch": 14645, "\u0120Strength": 14646, "\u0120jihad": 14647, "national": 14648, "\u0120trauma": 14649, "ussy": 14650, "oni": 14651, "\u0120consolid": 14652, "\u0120calories": 14653, "\u0120Flynn": 14654, "agged": 14655, "168": 14656, "\u0120Pink": 14657, "\u0120fulfill": 14658, "\u0120chains": 14659, "\u0120notably": 14660, "\u0120AV": 14661, "Life": 14662, "\u0120Chuck": 14663, "mus": 14664, "\u0120Urban": 14665, "\u0120Hend": 14666, "\u0120deposit": 14667, "\u0120Sad": 14668, "\u0120affair": 14669, "ORK": 14670, "ieval": 14671, "\u0120FDA": 14672, "\u0120trop": 14673, "\u0120Overall": 14674, "\u0120virtue": 14675, "\u0120satisfaction": 14676, "aund": 14677, "\u0120lun": 14678, "\u0120Switzerland": 14679, "\u0120Operation": 14680, "process": 14681, "\u0120shook": 14682, "\u0120counties": 14683, "leased": 14684, "\u0120Charlotte": 14685, "112": 14686, "\u0120transcript": 14687, "\u0120redd": 14688, "push": 14689, "\u0120Hey": 14690, "\u0120Analysis": 14691, "[\"": 14692, "\u0120alternatives": 14693, "ardless": 14694, "\u0120eleph": 14695, "\u0120prejud": 14696, "\u0120Leaf": 14697, "Having": 14698, "\u0120Hub": 14699, "\u0120expressions": 14700, "\u0120Volume": 14701, "\u0120shocking": 14702, "\u0120Reds": 14703, "\u0120readily": 14704, "\u0120planets": 14705, "adata": 14706, "\u0120collapsed": 14707, "\u0120Madrid": 14708, "\u0120irrit": 14709, "ipper": 14710, "\u0120Enc": 14711, "\u0120Wire": 14712, "\u0120buzz": 14713, "\u0120GP": 14714, "asha": 14715, "\u0120accidentally": 14716, "uru": 14717, "\u0120frustrated": 14718, "\u0120SA": 14719, "\u0120hungry": 14720, "\u0120Huff": 14721, "\u0120labels": 14722, "anto": 14723, "\u0120EP": 14724, "\u0120barriers": 14725, ")|": 14726, "\u0120Berkeley": 14727, "\u0120Jets": 14728, "\u0120pairs": 14729, "\u0120Lan": 14730, "James": 14731, "\u0120Bear": 14732, "\u0120humor": 14733, "\u0120Liberty": 14734, "\u0120magnitude": 14735, "\u0120aging": 14736, "\u0120Mason": 14737, "\u0120friendship": 14738, "umbling": 14739, "\u0120emerge": 14740, "\u0120newspapers": 14741, "\u0120ambitious": 14742, "\u0120Richards": 14743, "aternal": 14744, "\u01201981": 14745, "\u0120cookies": 14746, "\u0120sculpt": 14747, "\u0120pursuit": 14748, "Location": 14749, "\u0120scripts": 14750, "pc": 14751, "\u0120arrangements": 14752, "\u0120diameter": 14753, "\u0120loses": 14754, "amation": 14755, "\u0120liqu": 14756, "\u0120Jake": 14757, "arette": 14758, "\u0120understands": 14759, "\u0120Zen": 14760, "vm": 14761, "\u0120approve": 14762, "\u0120wip": 14763, "\u0120ultra": 14764, "\u0120intend": 14765, "\u0120DI": 14766, "ascular": 14767, "\u0120stays": 14768, "\u0120Kor": 14769, "\u0120Kl": 14770, "\u0120investing": 14771, "La": 14772, "\u0120believing": 14773, "bad": 14774, "mouth": 14775, "\u0120taxpayer": 14776, "\u00e3\u0125\u0125": 14777, "\u0120Quebec": 14778, "\u0120lap": 14779, "\u0120Swiss": 14780, "drop": 14781, "\u0120drain": 14782, "iri": 14783, "etc": 14784, "ften": 14785, "\u0120Nex": 14786, "\u0120straw": 14787, "\u0120screaming": 14788, "\u0120counted": 14789, "\u0120damaging": 14790, "\u0120ambassador": 14791, "century": 14792, "\u0120prox": 14793, "\u0120arrests": 14794, "uv": 14795, "ilateral": 14796, "\u0120Charg": 14797, "\u0120prescribed": 14798, "\u0120independently": 14799, "\u0120fierce": 14800, "\u0120Baby": 14801, "\u0120brave": 14802, "\u0120suits": 14803, "=>": 14804, "\u0120baseline": 14805, "\u0120Rate": 14806, "\u0120islands": 14807, "\u0120((": 14808, "green": 14809, "ixels": 14810, "\u0120namely": 14811, "\u0120Village": 14812, "than": 14813, "amy": 14814, "Version": 14815, "gmail": 14816, "entials": 14817, "\u0120Sud": 14818, "\u0120Melbourne": 14819, "\u0120arriving": 14820, "\u0120quantum": 14821, "eff": 14822, "ropolitan": 14823, "Tri": 14824, "\u0120funeral": 14825, "\u0120IR": 14826, "\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124": 14827, "\u0120Cob": 14828, "itably": 14829, "\u0120turb": 14830, "\u0120combo": 14831, "Review": 14832, "\u0120deployment": 14833, "uity": 14834, "\u0120Bott": 14835, "\u0120invisible": 14836, "\u0120rendering": 14837, "\u0120unlocked": 14838, "\u0120aqu": 14839, "\u0120Vladimir": 14840, "\u0120pad": 14841, "\u0120Brain": 14842, "\u0120Legacy": 14843, "dragon": 14844, "\u0120Kurdish": 14845, "\u0120sounded": 14846, "\u0120detained": 14847, "\u0120DM": 14848, "gary": 14849, "\u0120daughters": 14850, "\u0120disturbing": 14851, "uka": 14852, "\u0120Parad": 14853, "\u0120tast": 14854, "\u0120unfortunate": 14855, "\u0120ul": 14856, "emin": 14857, "\u0120attendance": 14858, "trl": 14859, "\u0120parks": 14860, "\u0120Memorial": 14861, "\u0120Alice": 14862, "othy": 14863, "guard": 14864, "\u0120Dise": 14865, "\u0120Shan": 14866, "\u0120Forum": 14867, "Rich": 14868, "\u0120shifted": 14869, "uez": 14870, "\u0120lighter": 14871, "\u0120Magn": 14872, "\u0120cod": 14873, "Sch": 14874, "hammad": 14875, "Pub": 14876, "350": 14877, "\u0120Pokemon": 14878, "\u0120prototype": 14879, "\u0120unre": 14880, "Base": 14881, "\u0120Students": 14882, "\u0120Reply": 14883, "\u0120Communist": 14884, "\u0120gau": 14885, "\u0120Tyler": 14886, "IZ": 14887, "\u0120participated": 14888, "\u0120suprem": 14889, "\u0120Details": 14890, "\u0120vessels": 14891, "rod": 14892, "\u0120tribe": 14893, "keep": 14894, "\u0120assumptions": 14895, "\u0120pound": 14896, "\u0120crude": 14897, "\u0120Available": 14898, "\u0120swimming": 14899, "\u0120inclusion": 14900, "\u0120advances": 14901, "culation": 14902, "\u0120conservation": 14903, "\u0120overd": 14904, "\u0120Buffalo": 14905, "Article": 14906, "edge": 14907, "\u0120awa": 14908, "\u0120Madison": 14909, "\u0120sidew": 14910, "\u0120catast": 14911, "\u0120Krist": 14912, "ucle": 14913, "\u0120Highway": 14914, "\u0120Terror": 14915, "\u0120activation": 14916, "\u0120unconscious": 14917, "\u0120Satan": 14918, "\u0120Susan": 14919, "illery": 14920, "\u0120arranged": 14921, "iop": 14922, "\u0120rumors": 14923, "urring": 14924, "think": 14925, "\u0120Keith": 14926, "\u0120Kind": 14927, "\u0120avoiding": 14928, "byn": 14929, "nut": 14930, "\u0120Speaker": 14931, "rus": 14932, "names": 14933, "\u0120guilt": 14934, "\u0120Olympics": 14935, "\u0120sail": 14936, "\u0120Mes": 14937, "levant": 14938, "\u0120Columbus": 14939, "aft": 14940, "City": 14941, "South": 14942, "\u0120Harvey": 14943, "\u0120Pun": 14944, "Several": 14945, "\u0120mentally": 14946, "\u0120impress": 14947, "mount": 14948, "\u0120Ubuntu": 14949, "\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136": 14950, "\u0120Superman": 14951, "\u0120MPs": 14952, "\u0120intentions": 14953, "\u0120Racing": 14954, "\u0120likelihood": 14955, "\u0120240": 14956, "Total": 14957, "\u0120toys": 14958, "\u0120Watson": 14959, "\u0120urge": 14960, "Lear": 14961, "\u0120Paper": 14962, "\u0120occurring": 14963, "\u0120Beng": 14964, "\u0120Cert": 14965, "\u0120stones": 14966, "Tim": 14967, "\u0120Twin": 14968, "zb": 14969, "\u0120Dynam": 14970, "\u0120politician": 14971, "kens": 14972, "\u0120Enterprise": 14973, "UTERS": 14974, "\u0120abol": 14975, "\u0120refresh": 14976, "\u0120arbitrary": 14977, "pection": 14978, "\u0120troubles": 14979, "\u0120});": 14980, "tv": 14981, "\u0120pilots": 14982, "\u0120distribute": 14983, "\u0120audit": 14984, "\u0120pause": 14985, "original": 14986, "\u0120rivals": 14987, "\u00c2\u00a3": 14988, "Fig": 14989, "TL": 14990, "abil": 14991, "rying": 14992, "Lin": 14993, "ioned": 14994, "lon": 14995, "\u0120fancy": 14996, "\u0120crashed": 14997, "\u0120tract": 14998, "\u0120shed": 14999, "\u0120consume": 15000, "Based": 15001, "download": 15002, "init": 15003, "\u0120voltage": 15004, "Introdu": 15005, "\u0120condemned": 15006, "\u0120Finance": 15007, "respect": 15008, "\u0120excluded": 15009, "\u0120establishing": 15010, "heric": 15011, "\u0120heritage": 15012, "\u0120spectacular": 15013, "\u0120unst": 15014, "\u0120Snowden": 15015, "\u0120Lane": 15016, "San": 15017, "\u0120protections": 15018, "struction": 15019, "incinn": 15020, "\u0120macro": 15021, "Custom": 15022, "iosity": 15023, "\u0120esp": 15024, "\u0120functioning": 15025, "\u0120mush": 15026, "\u0120puzzle": 15027, "\u0120ethical": 15028, "Mal": 15029, "\u0120governing": 15030, "\u0120Ferguson": 15031, "\u0120restored": 15032, "\u0120stressed": 15033, "\u0120Counter": 15034, "\u0120Kas": 15035, "clip": 15036, "ANS": 15037, "\u0120seiz": 15038, "UK": 15039, "byss": 15040, "oldown": 15041, "api": 15042, "\u0120permanently": 15043, "ounters": 15044, "West": 15045, "Through": 15046, "Light": 15047, "atoes": 15048, "\u0120neat": 15049, "\u0120cord": 15050, "urer": 15051, "\u0120severely": 15052, "\u0120Aven": 15053, "\u0120interrog": 15054, "\u0120triple": 15055, "Given": 15056, "Number": 15057, "\u0120arise": 15058, "\u0120sher": 15059, "plant": 15060, "\u0120flower": 15061, "\u0120Cou": 15062, "\u0120ate": 15063, "\u0120newer": 15064, "bul": 15065, "\u0120meanwhile": 15066, "\u0120Lair": 15067, "\u0120adjustment": 15068, "\u0120Copyright": 15069, "\u0120divers": 15070, "iological": 15071, "\u0120gamers": 15072, "oat": 15073, "\u0120historically": 15074, "\u0120analog": 15075, "\u0120longtime": 15076, "\u0120prescription": 15077, "\u0120Mist": 15078, "\u0120Hyper": 15079, "\u0120Maine": 15080, "\u0120Deity": 15081, "\u0120multipl": 15082, "\u0120Reincarn": 15083, "\u0120Hyd": 15084, "\u0120Pic": 15085, "Sil": 15086, "rants": 15087, "\u0120Cris": 15088, ".;": 15089, "({": 15090, "ependence": 15091, "\u0120recy": 15092, "ateur": 15093, "\u0120quad": 15094, "\u0120glob": 15095, "\u0120conced": 15096, "team": 15097, "\u0120capitalist": 15098, "\u0120Lot": 15099, "\u0120royal": 15100, "\u0120Cyber": 15101, "\u0120blacks": 15102, "metic": 15103, "riv": 15104, "\u0120Danny": 15105, "\u0120spo": 15106, "\u0120RO": 15107, "\u0120animated": 15108, "rypted": 15109, "\u0120Deputy": 15110, "\u0120rendered": 15111, "FE": 15112, "\u0120streak": 15113, "\u0120clouds": 15114, "\u0120Doug": 15115, "~~~~~~~~": 15116, "\u0120discour": 15117, "\u0120Veh": 15118, "\u0120psychology": 15119, "\u0120Journey": 15120, "\u0120crystal": 15121, "\u0120Frost": 15122, "\u0120suspicion": 15123, "\u0120relate": 15124, "orus": 15125, "\u0120Crypt": 15126, "\u0120NVIDIA": 15127, "comed": 15128, "uting": 15129, "incinnati": 15130, "\u0120vulnerability": 15131, "ostic": 15132, "\u0120isolation": 15133, "\u0120cooling": 15134, "\u0120Coalition": 15135, "\u0120119": 15136, "Four": 15137, "\u0120Deal": 15138, "\u0120\u00e2\u012b": 15139, "semble": 15140, "rament": 15141, "\u0120Barcelona": 15142, "\u0120102": 15143, "\u0120cocaine": 15144, "ocalypse": 15145, "Feb": 15146, "ogenic": 15147, "\u0120mutation": 15148, "\u0120cryptoc": 15149, "\u0120Kel": 15150, "\u0120Git": 15151, "ais": 15152, "\u0120sisters": 15153, "ANK": 15154, "\u0120activate": 15155, "Ter": 15156, "\u0120dread": 15157, "ylon": 15158, "\u0120propri": 15159, "Aust": 15160, "\u0120Default": 15161, "\u0120outdoor": 15162, "\u0120sheer": 15163, "ceive": 15164, "\u0120gently": 15165, "\u00d0\u00be": 15166, "Program": 15167, "\u0120\u00e2\u0128\u0134": 15168, "\u0120vegan": 15169, "\u0120Crus": 15170, "\u0120responsibilities": 15171, "\u0120HR": 15172, "OLD": 15173, "\u0120prevents": 15174, "\u0120stiff": 15175, "\u0120Were": 15176, "\u0120athletic": 15177, "\u0120Score": 15178, "\u0120):": 15179, "\u0120columns": 15180, "\u0120Loc": 15181, "available": 15182, "\u0120Fram": 15183, "\u0120Sessions": 15184, "\u0120companion": 15185, "\u0120packs": 15186, "140": 15187, "\u0120Knights": 15188, "\u0120fart": 15189, "\u0120streams": 15190, "\u0120shore": 15191, "\u0120appeals": 15192, "\u0120Performance": 15193, "haul": 15194, "\u0120Stra": 15195, "\u0120Nag": 15196, "103": 15197, "\u0120Transportation": 15198, "BB": 15199, "Ev": 15200, "zan": 15201, "Public": 15202, "\u0120twin": 15203, "ulsion": 15204, "Mult": 15205, "\u0120electro": 15206, "\u0120statue": 15207, "ationally": 15208, "\u0120Nort": 15209, "\u0120inspection": 15210, "/*": 15211, "igue": 15212, "\u0120compassion": 15213, "\u0120Tales": 15214, "\u0120Stein": 15215, "\u0120Screen": 15216, "\u0120Bug": 15217, "\u0120Lion": 15218, "girl": 15219, "\u0120withdrawal": 15220, "\u0120objectives": 15221, "\u0120bloody": 15222, "\u0120preliminary": 15223, "\u0120jacket": 15224, "\u0120dimensions": 15225, "\u0120Cool": 15226, "\u0120Occup": 15227, "\u0120wreck": 15228, "\u0120doubled": 15229, "anking": 15230, "\u01201975": 15231, "\u0120glasses": 15232, "\u0120Wang": 15233, "prov": 15234, "Path": 15235, "connected": 15236, "\u0120Multi": 15237, "\u0120Norway": 15238, "agonist": 15239, "\u0120feared": 15240, "\u0120touching": 15241, "\u0120arguably": 15242, "\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af": 15243, "\u0120NCAA": 15244, "chem": 15245, "\u0120spat": 15246, "\u0120WWE": 15247, "\u0120Cel": 15248, "igger": 15249, "\u0120attacker": 15250, "\u0120Join": 15251, "object": 15252, "etta": 15253, "\u0120eliminated": 15254, "det": 15255, "\u0120destruct": 15256, "\u0120Lucas": 15257, "ctuary": 15258, "180": 15259, "\u0120Brady": 15260, "\u0120Blues": 15261, "Bay": 15262, "aukee": 15263, "\u0120timeline": 15264, "\u0120delegates": 15265, "written": 15266, "ufficient": 15267, "\u0120shapes": 15268, "Copyright": 15269, "ouble": 15270, "service": 15271, "\u0120pione": 15272, "\u0120colleges": 15273, "\u0120rows": 15274, "\u0120spite": 15275, "\u0120assessed": 15276, "360": 15277, "\u0120lease": 15278, "\u0120confidential": 15279, "cker": 15280, "\u0120Manning": 15281, "\u0120Voice": 15282, "\u0120sealed": 15283, "\u0120calculate": 15284, "NO": 15285, "\u0120Assistant": 15286, "\u0120teenager": 15287, "ulent": 15288, "atherine": 15289, "\u0120mock": 15290, "\u0120diamond": 15291, "\u0120fest": 15292, "\u0120switched": 15293, "\u0120resume": 15294, "\u0120Puerto": 15295, "\u0120lanes": 15296, "iration": 15297, "\u0120Similarly": 15298, "\u0120rod": 15299, "\u0120Sel": 15300, "\u0120Palace": 15301, "\u0120Limited": 15302, "eous": 15303, "\u0120variant": 15304, "\u0120ward": 15305, "\u0120))": 15306, "Show": 15307, "OOK": 15308, "Alex": 15309, "\u0120Nep": 15310, "bris": 15311, "\u0120Wikipedia": 15312, "\u0120exceptional": 15313, "\u0120manages": 15314, "\u0120Draw": 15315, "Again": 15316, "\u0120copper": 15317, "utt": 15318, "\u0120exports": 15319, "\u0120portfolio": 15320, "\u0120elevated": 15321, "Rated": 15322, "\u0120Otherwise": 15323, "\u0120Tact": 15324, "\u0120Shel": 15325, "\u0120TX": 15326, "\"\u00e2\u0122\u0136": 15327, "\u0120resur": 15328, "\u0120Wa": 15329, "venant": 15330, "\u0120monetary": 15331, "people": 15332, "Email": 15333, "\u0120fifty": 15334, "\u0120Sweet": 15335, "\u0120Malaysia": 15336, "\u0120confusing": 15337, "\u0120Rio": 15338, "uda": 15339, "utenant": 15340, "\");": 15341, "\u0120praised": 15342, "\u0120volumes": 15343, "turn": 15344, "\u0120mature": 15345, "\u0120nonprofit": 15346, "\u0120passionate": 15347, "\u0120Private": 15348, "\u0120103": 15349, "\u0120descend": 15350, "\u00e7\u00a5\u0140": 15351, "uffy": 15352, "headed": 15353, "Whether": 15354, "rien": 15355, "zech": 15356, "beit": 15357, "\u0120chrom": 15358, "\u0120McM": 15359, "\u0120dancing": 15360, "\u0120eleg": 15361, "\u0120Noticed": 15362, "115": 15363, "\u0120advocacy": 15364, "ENTS": 15365, "ambling": 15366, "\u0120Minor": 15367, "\u0120Finn": 15368, "\u0120priorities": 15369, "\u0120thereof": 15370, "\u0120Stage": 15371, "\u0120Rogers": 15372, "\u0120substitute": 15373, "\u0120Jar": 15374, "\u0120Jefferson": 15375, "\u0120lightly": 15376, "102": 15377, "\u0120Lisa": 15378, "uits": 15379, "ysical": 15380, "\u0120shifts": 15381, "\u0120drones": 15382, "\u0120workplace": 15383, "\u0120resid": 15384, "ensed": 15385, "ahn": 15386, "\u0120preferences": 15387, "server": 15388, "\u0120debates": 15389, "doc": 15390, "\u0120Gods": 15391, "\u0120helicopter": 15392, "\u0120honour": 15393, "\u0120considerably": 15394, "eded": 15395, "\u0120Female": 15396, "\u0120Anne": 15397, "\u0120reun": 15398, "\u0120Face": 15399, "\u0120Hallow": 15400, "\u0120Budget": 15401, "\u0120condemn": 15402, "\u0120tender": 15403, "Prof": 15404, "ocratic": 15405, "\u0120Turner": 15406, "\u0120Agric": 15407, "\u01201976": 15408, "\u0120apt": 15409, "disc": 15410, "\u0120Fighter": 15411, "\u0120Aur": 15412, "\u0120garbage": 15413, "input": 15414, "\u0120Karl": 15415, "\u0120Oliver": 15416, "\u0120Language": 15417, "kn": 15418, "Non": 15419, "\u0120Clar": 15420, "\u0120traditions": 15421, "\u0120advertisement": 15422, "\u0120Sor": 15423, "\u0120archive": 15424, "\u0120villages": 15425, "750": 15426, "\u0120implementing": 15427, "waukee": 15428, "\u0120dietary": 15429, "\u0120switching": 15430, "Republic": 15431, "\u0120velocity": 15432, "\u0120cit": 15433, "\u0120Awards": 15434, "\u0120financing": 15435, "\u0120lasted": 15436, ")]": 15437, "\u0120reminder": 15438, "Person": 15439, "\u0120precision": 15440, "\u0120designers": 15441, "\u0120Fried": 15442, "\u0120Border": 15443, "\u0120tragic": 15444, "\u0120wield": 15445, "\u0120initiatives": 15446, "\u0120Tank": 15447, "wer": 15448, "\u0120joins": 15449, "Ro": 15450, "inery": 15451, "\u0120arrow": 15452, "\u0120generating": 15453, "founder": 15454, "\u0120searches": 15455, "\u0120randomly": 15456, "Access": 15457, "\u0120batch": 15458, "\u0120posed": 15459, "lat": 15460, "\u0120pursuing": 15461, "asa": 15462, "\u0120testified": 15463, "forming": 15464, "\u0120Shar": 15465, "wiki": 15466, "\u0120Either": 15467, "Sometimes": 15468, "\u0120senators": 15469, "\u0120Johnny": 15470, "\u0120Taliban": 15471, "\u0120GPS": 15472, "\":\"/": 15473, "\u00e3\u0123\u00ae\u00e5": 15474, "\u0120analyzed": 15475, "\u0120Rubio": 15476, "\u0120Movement": 15477, "opard": 15478, "iii": 15479, "Stand": 15480, "fight": 15481, "\u0120ignoring": 15482, "iang": 15483, "\u0120GN": 15484, "soever": 15485, "\u0120STAT": 15486, "\u0120refusing": 15487, "\u0120sweat": 15488, "\u0120bay": 15489, "PORT": 15490, "irmed": 15491, "aky": 15492, "\u0120dispro": 15493, "\u0120labeled": 15494, "\u0120108": 15495, "Hello": 15496, "\u0120pleasant": 15497, "aba": 15498, "\u0120triumph": 15499, "\u0120aboard": 15500, "\u0120incom": 15501, "\u0120Crow": 15502, "lett": 15503, "\u0120folk": 15504, "\u0120chase": 15505, "``": 15506, "\u0120Brus": 15507, "\u0120teens": 15508, "cue": 15509, "\u0120terrain": 15510, "hyd": 15511, "ilight": 15512, "ORY": 15513, "Support": 15514, "ews": 15515, "lli": 15516, "raints": 15517, "\u0120Cand": 15518, "\u0120abused": 15519, "achment": 15520, "larg": 15521, "Bas": 15522, "\u0120Cancer": 15523, "\u01201978": 15524, "\u0120supporter": 15525, "access": 15526, "\u0120Termin": 15527, "\u0120Tampa": 15528, "\u0120ANY": 15529, "\u0120newest": 15530, "\u0120Criminal": 15531, "edu": 15532, "\u01201930": 15533, "\u0120admits": 15534, "\u0120ende": 15535, "\u0120failures": 15536, "urate": 15537, "fulness": 15538, "cycl": 15539, "\u0120Subject": 15540, "\u0120infinite": 15541, "three": 15542, "WA": 15543, "pit": 15544, "\u0120Install": 15545, "Rad": 15546, "iliation": 15547, "GM": 15548, "\u0120continent": 15549, "\u0120accommodate": 15550, "\u0120Clay": 15551, "\u0120pup": 15552, "\u0120Function": 15553, "\u0120hammer": 15554, "\u0120Alberta": 15555, "\u0120revised": 15556, "\u0120minorities": 15557, "\u0120measurement": 15558, "Connell": 15559, "\u0120disable": 15560, "\u0120Mix": 15561, "Incre": 15562, "\u0120fork": 15563, "\u0120Rosen": 15564, "\u0120implies": 15565, "umblr": 15566, "ANG": 15567, "\u0120proteins": 15568, "\u0120aggression": 15569, "\u0120facilitate": 15570, "SN": 15571, "\u0120illegally": 15572, "uer": 15573, "\u0120academ": 15574, "\u0120puzz": 15575, "\u0120Shift": 15576, "pay": 15577, "ollo": 15578, "\u0120audiences": 15579, "Build": 15580, "\u0120noble": 15581, "\u0120syntax": 15582, "\u00e2\u013a\u0127": 15583, "\u0120beam": 15584, "\u0120Bed": 15585, "\u0120Ald": 15586, "\u0120origins": 15587, "video": 15588, "\u01201977": 15589, "\u0120Assault": 15590, "\u0120garage": 15591, "Team": 15592, "\u0120verdict": 15593, "\u0120dwar": 15594, "\u0120Virtual": 15595, "event": 15596, "Keep": 15597, "\u0120sentiment": 15598, "\u0120wildlife": 15599, "shirt": 15600, "\u0120burg": 15601, "\u0120recommendation": 15602, "represent": 15603, "\u0120gallery": 15604, "owners": 15605, "\u0120scholar": 15606, "\u0120convenience": 15607, "\u0120Swift": 15608, "\u0120convinc": 15609, "Cap": 15610, "\u0120warfare": 15611, "\u0120Visual": 15612, "\u0120constitute": 15613, "\u0120abort": 15614, "\u0120Weather": 15615, "\u0120Looking": 15616, "\u0120Hem": 15617, "\u0120martial": 15618, "\u0120incoming": 15619, "etition": 15620, "\u0120tolerance": 15621, "\u0120Created": 15622, "\u0120flows": 15623, "\u0120Elder": 15624, "\u0120souls": 15625, "\u0120foul": 15626, "\u0120Pain": 15627, "\u0120CAN": 15628, "\u0120220": 15629, "bc": 15630, "hend": 15631, "\u0120genius": 15632, "Real": 15633, "\u0120Wr": 15634, "ometer": 15635, "pad": 15636, "\u0120limiting": 15637, "\u0120Si": 15638, "\u0120Lore": 15639, "\u0120Adventures": 15640, "\u0120varied": 15641, "Disc": 15642, "fin": 15643, "\u0120Personal": 15644, "Chris": 15645, "\u0120invented": 15646, "\u0120dive": 15647, "\u0120Rise": 15648, "\u0120oz": 15649, "\u0120Comics": 15650, "\u0120expose": 15651, "\u0120Reb": 15652, "letters": 15653, "site": 15654, "imated": 15655, "\u0120hacking": 15656, "\u0120educated": 15657, "\u0120Nobody": 15658, "\u0120depri": 15659, "\u0120incentive": 15660, "\u00e3\u0124\u00b7": 15661, "\u0120oversight": 15662, "\u0120tribes": 15663, "\u0120Belgium": 15664, "\u0120licensing": 15665, "ourt": 15666, "Product": 15667, "ahl": 15668, "\u0120Gem": 15669, "\u0120specialist": 15670, "\u0120cra": 15671, "anners": 15672, "\u0120Corbyn": 15673, "\u01201973": 15674, "READ": 15675, "\u0120summar": 15676, "\u0120overlook": 15677, "\u0120Application": 15678, "\u0120inappropriate": 15679, "\u0120downloaded": 15680, "Que": 15681, "\u0120Bears": 15682, "\u0120thumb": 15683, "\u0120Character": 15684, "\u0120Reincarnated": 15685, "\u0120Sid": 15686, "\u0120demonstrates": 15687, "sky": 15688, "\u0120Bloomberg": 15689, "\u0120Array": 15690, "\u0120Results": 15691, "\u0120Fourth": 15692, "\u0120EDT": 15693, "\u0120Oscar": 15694, "cend": 15695, "\u0120106": 15696, "\u0120NULL": 15697, "\u0120HERE": 15698, "match": 15699, "\u0120Brun": 15700, "\u0120glucose": 15701, "ieg": 15702, "egu": 15703, "\u0120certified": 15704, "\u0120relie": 15705, "\u0120humanitarian": 15706, "\u0120prayers": 15707, "King": 15708, "\u0120nan": 15709, "hou": 15710, "108": 15711, "ulu": 15712, "\u0120renewable": 15713, "\u0120distinguish": 15714, "\u0120dense": 15715, "\u0120Vent": 15716, "\u0120Package": 15717, "\u0120Boss": 15718, "\u0120editors": 15719, "\u0120migr": 15720, "Tra": 15721, "\u0120Peters": 15722, "\u0120Arctic": 15723, "2004": 15724, "\u0120Cape": 15725, "\u0120locally": 15726, "\u0120lasting": 15727, "\u0120handy": 15728, ".).": 15729, "Pan": 15730, "\u0120RES": 15731, "Index": 15732, "\u0120tensions": 15733, "\u0120formerly": 15734, "\u0120ideological": 15735, "\u0120sensors": 15736, "\u0120dealers": 15737, "\u0120defines": 15738, "Sk": 15739, "\u0120proceeds": 15740, "\u0120proxy": 15741, "azines": 15742, "\u0120Bash": 15743, "\u0120Pad": 15744, "\u0120Craft": 15745, "ealous": 15746, "\u0120sheets": 15747, "ometry": 15748, "June": 15749, "clock": 15750, "TT": 15751, "\u0120Theatre": 15752, "\u0120Buzz": 15753, "\u0120chapters": 15754, "\u0120millenn": 15755, "\u0120dough": 15756, "\u0120Congressional": 15757, "\u0120imagined": 15758, "avior": 15759, "\u0120clinic": 15760, "\u01201945": 15761, "\u0120holder": 15762, "root": 15763, "olester": 15764, "\u0120restart": 15765, "BN": 15766, "\u0120Hamas": 15767, "\u0120Job": 15768, "\u0120orb": 15769, "\u0120ram": 15770, "\u0120disclose": 15771, "\u0120translate": 15772, "\u0120immigrant": 15773, "\u0120annoying": 15774, "\u0120treaty": 15775, "anium": 15776, "\u0120Tea": 15777, "\u0120Legion": 15778, "\u0120crowds": 15779, "\u0120Bec": 15780, "\u0120Aer": 15781, "ohyd": 15782, "Bro": 15783, "Looking": 15784, "\u0120lbs": 15785, "\u0120aggress": 15786, "\u0120seam": 15787, "\u0120intercept": 15788, "\u0120MI": 15789, "mercial": 15790, "activ": 15791, "\u0120Cit": 15792, "\u0120dimension": 15793, "\u0120consistency": 15794, "\u0120rushing": 15795, "\u0120Douglas": 15796, "\u0120trim": 15797, "Install": 15798, "icker": 15799, "\u0120shy": 15800, "106": 15801, "\u0120mentions": 15802, "pelled": 15803, "\u0120Tak": 15804, "cost": 15805, "\u0120classroom": 15806, "\u0120fortune": 15807, "driven": 15808, "\u0120unle": 15809, "\u0120Wheel": 15810, "\u0120investor": 15811, "\u0120Masters": 15812, "kit": 15813, "\u0120associations": 15814, "\u0120Evolution": 15815, "oping": 15816, "uscript": 15817, "\u0120provincial": 15818, "\u0120Walter": 15819, "avi": 15820, "SO": 15821, "\u0120unlimited": 15822, "English": 15823, "\u0120Cards": 15824, "\u0120Ebola": 15825, "nered": 15826, "\u0120revenge": 15827, "\u0120outright": 15828, "umper": 15829, "\u0120fitting": 15830, "\u0120Solid": 15831, "\u0120formally": 15832, "\u0120problematic": 15833, "\u0120hazard": 15834, "\u0120encryption": 15835, "\u0120straightforward": 15836, "\u0120AK": 15837, "\u0120pse": 15838, "\u0120Orb": 15839, "\u0120Chamber": 15840, "\u0120Mak": 15841, "Contents": 15842, "\u0120loyalty": 15843, "\u0120lyrics": 15844, "\u0120Sym": 15845, "\u0120welcomed": 15846, "\u0120cooked": 15847, "\u0120monop": 15848, "\u0120nurse": 15849, "\u0120misleading": 15850, "\u0120eternal": 15851, "\u0120shifting": 15852, "\u0120+=": 15853, "Vis": 15854, "\u0120institutional": 15855, "illary": 15856, "\u0120pant": 15857, "VERT": 15858, "\u0120ACC": 15859, "\u0120Enh": 15860, "\u0120incon": 15861, "\u0120REUTERS": 15862, "\u0120donated": 15863, "\u00e2\u0122\u00a6\u00e2\u0122\u00a6\u00e2\u0122\u00a6\u00e2\u0122\u00a6": 15864, "Intern": 15865, "\u0120exhibit": 15866, "\u0120tire": 15867, "\u0120Ric": 15868, "\u0120Champion": 15869, "\u0120Muhammad": 15870, "NING": 15871, "\u0120Soccer": 15872, "\u0120mobility": 15873, "\u0120varying": 15874, "\u0120Movie": 15875, "\u0120lord": 15876, "oak": 15877, "Field": 15878, "\u0120vector": 15879, "usions": 15880, "\u0120scrap": 15881, "\u0120enabling": 15882, "make": 15883, "Tor": 15884, ".*": 15885, "||": 15886, "\u0120Website": 15887, "\u0120NPC": 15888, "\u0120socialist": 15889, "\u0120Billy": 15890, "\u0120Additional": 15891, "\u0120cargo": 15892, "\u0120farms": 15893, "\u0120Soon": 15894, "\u0120Prize": 15895, "\u0120midnight": 15896, "\u0120900": 15897, "seen": 15898, "\u0120Spot": 15899, "\u0120sheep": 15900, "\u0120sponsored": 15901, "\u0120Hi": 15902, "\u0120Jump": 15903, "\u01201967": 15904, "Microsoft": 15905, "\u0120Agent": 15906, "\u0120charts": 15907, "dir": 15908, "\u0120adjacent": 15909, "\u0120tricks": 15910, "\u0120manga": 15911, "\u0120exagger": 15912, "/>": 15913, "football": 15914, "\u0120FCC": 15915, "GC": 15916, "\u0120Tier": 15917, "andra": 15918, "OUND": 15919, "%),": 15920, "\u0120fruits": 15921, "VC": 15922, "\u0120AA": 15923, "Rober": 15924, "\u0120midst": 15925, "\u00e2\u0139": 15926, "anka": 15927, "\u0120legislature": 15928, "\u0120Neil": 15929, "\u0120tourists": 15930, "\"\"": 15931, "\u0120Warning": 15932, "\u0120Nevertheless": 15933, "\u0120Official": 15934, "\u0120Whatever": 15935, "\u0120mold": 15936, "\u0120drafted": 15937, "\u0120substances": 15938, "\u0120breed": 15939, "\u0120tags": 15940, "\u0120Task": 15941, "\u0120verb": 15942, "\u0120manufactured": 15943, "comments": 15944, "\u0120Polish": 15945, "Prov": 15946, "\u0120determines": 15947, "Obama": 15948, "kers": 15949, "\u0120utterly": 15950, "\u0120sect": 15951, "sche": 15952, "\u0120Gates": 15953, "\u0120Chap": 15954, "\u0120aluminum": 15955, "\u0120zombie": 15956, "\u0120Touch": 15957, "\u0120UP": 15958, "\u0120satisfy": 15959, "\u0120predomin": 15960, "ascript": 15961, "\u0120elaborate": 15962, "\u01201968": 15963, "\u0120measuring": 15964, "\u0120Vari": 15965, "anyahu": 15966, "\u0120sir": 15967, "ulates": 15968, "idges": 15969, "ickets": 15970, "\u0120Spencer": 15971, "TM": 15972, "oubted": 15973, "\u0120prey": 15974, "\u0120installing": 15975, "\u0120Cab": 15976, "reed": 15977, "reated": 15978, "Supp": 15979, "\u0120wrist": 15980, "\u0120Kerry": 15981, "107": 15982, "\u0120Kle": 15983, "\u0120Rachel": 15984, "\u0120cotton": 15985, "\u0120ARE": 15986, "\u0120Ele": 15987, "Control": 15988, "\u0120loads": 15989, "\u0120Dod": 15990, "anas": 15991, "bone": 15992, "\u0120classical": 15993, "\u0120Regional": 15994, "\u0120Integ": 15995, "VM": 15996, "\u0120desires": 15997, "\u0120autism": 15998, "supported": 15999, "\u0120Message": 16000, "\u0120compact": 16001, "writer": 16002, "\u0120109": 16003, "\u0120Hurricane": 16004, "cision": 16005, "\u0120cycles": 16006, "\u0120drill": 16007, "\u0120colleague": 16008, "\u0120maker": 16009, "German": 16010, "\u0120mistaken": 16011, "Sun": 16012, "\u0120Gay": 16013, "\u0120whatsoever": 16014, "\u0120sells": 16015, "\u0120Airl": 16016, "liv": 16017, "\u0120Option": 16018, "\u0120solved": 16019, "\u0120sectors": 16020, "\u0120horizontal": 16021, "\u0120equation": 16022, "\u0120Skill": 16023, "\u0120Bio": 16024, "gement": 16025, "\u0120Snap": 16026, "\u0120Legal": 16027, "\u0120trademark": 16028, "\u0120makeup": 16029, "\u0120assembled": 16030, "\u0120saves": 16031, "\u0120Halloween": 16032, "\u0120Vermont": 16033, "\u0120FROM": 16034, "\u0120farming": 16035, "\u0120Podcast": 16036, "acceptable": 16037, "\u0120Higher": 16038, "\u0120asleep": 16039, "ullivan": 16040, "\u0120referen": 16041, "\u0120Lev": 16042, "\u0120bullets": 16043, "oko": 16044, "HC": 16045, "\u0120stairs": 16046, "\u0120maintains": 16047, "\u0120Lower": 16048, "\u0120Vi": 16049, "\u0120marine": 16050, "\u0120acres": 16051, "\u0120coordinator": 16052, "\u0120Joh": 16053, "\u0120counterparts": 16054, "\u0120Brothers": 16055, "\u0120indict": 16056, "bra": 16057, "\u0120chunk": 16058, "\u0120cents": 16059, "Home": 16060, "\u0120Month": 16061, "\u0120accordingly": 16062, "ifles": 16063, "\u0120Germans": 16064, "\u0120Syn": 16065, "Hub": 16066, "\u0120eyeb": 16067, "\u00e2\u0136\u0122\u00e2\u0136\u0122\u00e2\u0136\u0122\u00e2\u0136\u0122": 16068, "\u0120ranges": 16069, "\u0120Holland": 16070, "\u0120Robot": 16071, "fc": 16072, "Mike": 16073, "\u0120plasma": 16074, "\u0120swap": 16075, "\u0120athlete": 16076, "\u0120Rams": 16077, ",'\"": 16078, "\u0120infections": 16079, "\u0120corrid": 16080, "\u0120vib": 16081, "\u0120patches": 16082, "\u0120traditionally": 16083, "\u0120revelation": 16084, "\u0120sweep": 16085, "\u0120glance": 16086, "\u0120inex": 16087, "2003": 16088, "\u0120Raw": 16089, "working": 16090, "osures": 16091, "\u0120Dat": 16092, "\u0120Lynch": 16093, "\u0120leverage": 16094, "\u0120Reid": 16095, "\u0120correlation": 16096, "iances": 16097, "avascript": 16098, "\u0120repository": 16099, "retty": 16100, "\u01201972": 16101, "240": 16102, "\u0120oun": 16103, "pol": 16104, "\u0120Reed": 16105, "\u0120tactical": 16106, "isite": 16107, "Apple": 16108, "\u0120Quinn": 16109, "\u0120raped": 16110, "illo": 16111, "Europe": 16112, "\u0120algorithms": 16113, "\u0120Rodrig": 16114, "iu": 16115, "\u0120illum": 16116, "\u0120fame": 16117, "\u0120introducing": 16118, "\u0120delays": 16119, "\u0120Raiders": 16120, "\u0120whistle": 16121, "\u0120novels": 16122, "\u0120Really": 16123, "\u0120deriv": 16124, "\u0120publications": 16125, "\u0120Neither": 16126, "\u0120Commerce": 16127, "\u0120aston": 16128, "language": 16129, "Notes": 16130, "\u0120Roth": 16131, "\u0120Fear": 16132, "\u0120mate": 16133, "\u0120parade": 16134, "\u0120QB": 16135, "\u0120maneu": 16136, "\u0120Cincinnati": 16137, "mitting": 16138, "\u0120waist": 16139, "\u0120Rew": 16140, "\u0120discont": 16141, "\u00d0\u00b0": 16142, "\u0120staring": 16143, "\u0120alias": 16144, "\u0120securities": 16145, "\u0120toilet": 16146, "\u0120Jedi": 16147, "\u0120unlaw": 16148, "vised": 16149, "////////": 16150, "](": 16151, "\u0120Weiss": 16152, "\u0120prest": 16153, "\u0120Compan": 16154, "\u0120memo": 16155, "\u0120Grace": 16156, "July": 16157, "\u0120Elite": 16158, "center": 16159, "\u0120Stay": 16160, "\u0120galaxy": 16161, "\u0120tooth": 16162, "\u0120Settings": 16163, "\u0120subjected": 16164, "\u00e3\u0124\u00a6": 16165, "\u0120lineback": 16166, "\u0120retailers": 16167, "\u0120Want": 16168, "\u0120dangers": 16169, "Air": 16170, "\u0120voluntary": 16171, "eway": 16172, "\u0120interpreted": 16173, "otine": 16174, "\u00c3\u00a7": 16175, "\u0120pel": 16176, "Service": 16177, "\u0120Eventually": 16178, "\u0120careers": 16179, "\u0120threaten": 16180, "\u0120memor": 16181, "\u0120Bradley": 16182, "ancies": 16183, "sn": 16184, "\u0120Unknown": 16185, "National": 16186, "\u0120shadows": 16187, "ailand": 16188, "\u0120Dash": 16189, "Everyone": 16190, "izzard": 16191, "March": 16192, "=(": 16193, "\u0120pulls": 16194, "\u0120stranger": 16195, "\u0120backwards": 16196, "\u0120Bernard": 16197, "imensional": 16198, "\u0120chron": 16199, "\u0120theoretical": 16200, "ktop": 16201, "\u0120ware": 16202, "\u0120Investig": 16203, "\u0120Initi": 16204, "\u0120Operations": 16205, "oven": 16206, "ocide": 16207, "*/": 16208, "\u0120flames": 16209, "\u0120Cash": 16210, "shit": 16211, "\u0120cab": 16212, "\u0120Analy": 16213, "\u0120Seah": 16214, "\u0120defining": 16215, "\u0120ordering": 16216, "\u0120immun": 16217, "\u0120persistent": 16218, "ACH": 16219, "Russian": 16220, "mans": 16221, "\u0120hind": 16222, "\u0120photography": 16223, "\u00c2\u00a9": 16224, "\u0120hug": 16225, "\u0120107": 16226, "\u0120Hence": 16227, "iots": 16228, "udeau": 16229, "\u0120subsidies": 16230, "\u0120routinely": 16231, "\u0120Device": 16232, "itic": 16233, "\u0120disgust": 16234, "lander": 16235, "\u01201940": 16236, "\u0120assignment": 16237, "\u0120Besides": 16238, "wick": 16239, "\u0120Dust": 16240, "usc": 16241, "structed": 16242, "111": 16243, "develop": 16244, "\u0120fond": 16245, "\u0120intersection": 16246, "\u0120dignity": 16247, "\u0120commissioner": 16248, "Without": 16249, "reach": 16250, "\u0120cartoon": 16251, "\u0120scales": 16252, "\u00e3\u0125\u0143": 16253, "FIG": 16254, "\u0120surveys": 16255, "\u0120Indonesia": 16256, "\u0120artwork": 16257, "\u0120unch": 16258, "\u0120cycling": 16259, "unct": 16260, "auer": 16261, "orate": 16262, "\u0120Obviously": 16263, "\u0120characterized": 16264, "feld": 16265, "\u0120affirm": 16266, "\u0120innings": 16267, "\u0120\u00e9": 16268, "\u0120aliens": 16269, "\u0120cloth": 16270, "etooth": 16271, "\u0120Certain": 16272, "\u00c2\u00a7": 16273, "\u0120digest": 16274, "know": 16275, "\u0120XL": 16276, "\u0120predictions": 16277, "\u0120din": 16278, "WAR": 16279, "\u0120aftermath": 16280, "Example": 16281, "\u0120Success": 16282, "\u0120Thr": 16283, "IGN": 16284, "\u0120miner": 16285, "Bus": 16286, "\u0120clarity": 16287, "heimer": 16288, "\u0120OUT": 16289, "\u0120Send": 16290, "\u0120Circle": 16291, "\u0120Diet": 16292, "\u0120pronounced": 16293, "\u0120creators": 16294, "\u0120earthquake": 16295, "attery": 16296, "geons": 16297, "\u0120od": 16298, "\u0120laying": 16299, "orp": 16300, "Ult": 16301, "project": 16302, "\u0120undermin": 16303, "\u0120sequel": 16304, "Sam": 16305, "\u0120Darkness": 16306, "\u0120reception": 16307, "bull": 16308, "YS": 16309, "\u0120Vir": 16310, "\u0120sequences": 16311, "\u0120Coin": 16312, "\u0120outfit": 16313, "\u0120Wait": 16314, "119": 16315, "\u0120delivers": 16316, "......": 16317, "\u0120blown": 16318, "\u0120Esc": 16319, "\u0120Math": 16320, "perm": 16321, "\u0120Ul": 16322, "\u0120glim": 16323, "\u0120facial": 16324, "\u0120greenhouse": 16325, "\u0120tokens": 16326, "/-": 16327, "\u0120Annual": 16328, "\u0120ONE": 16329, "\u0120teenage": 16330, "\u0120Physical": 16331, "\u0120Lang": 16332, "\u0120Celt": 16333, "\u0120sued": 16334, "ividually": 16335, "\u0120patience": 16336, "chair": 16337, "regular": 16338, "\u0120aug": 16339, "inv": 16340, "except": 16341, "\u0120Lil": 16342, "\u0120nest": 16343, "fd": 16344, "sum": 16345, "\u0120Chase": 16346, "Russia": 16347, "\u0120Jennifer": 16348, "\u0120offseason": 16349, "Overall": 16350, "Fore": 16351, "\u0120riot": 16352, "Aud": 16353, "former": 16354, "\u0120defenders": 16355, "\u0120CT": 16356, "iotic": 16357, "ribly": 16358, "\u0120automated": 16359, "\u0120penis": 16360, "\u0120insist": 16361, "\u0120diagram": 16362, "\u0120SQL": 16363, "\u0120Garc": 16364, "\u0120witch": 16365, "client": 16366, "ierra": 16367, "ambers": 16368, "\u0120recount": 16369, "far": 16370, "Very": 16371, "osterone": 16372, "\u0120appreciated": 16373, "\u0120Perfect": 16374, "Section": 16375, "\u0120doses": 16376, "ocaust": 16377, "\u0120costly": 16378, "\u0120grams": 16379, "\u0120Shi": 16380, "\u0120wrestling": 16381, "\u01201971": 16382, "\u0120trophy": 16383, "\u0120nerve": 16384, "\u0120Kaz": 16385, "\u0120Experience": 16386, "\u0120pledged": 16387, "\u0120playback": 16388, "\u0120creativity": 16389, "bye": 16390, "\u0120attackers": 16391, "\u0120holders": 16392, "\u0120Coach": 16393, "\u0120PhD": 16394, "\u0120transfers": 16395, "\u0120colored": 16396, "\u0120Hindu": 16397, "\u0120drown": 16398, "\u0120listened": 16399, "\u0120WA": 16400, "iasm": 16401, "PO": 16402, "\u0120appealing": 16403, "\u0120disclosed": 16404, "\u0120Chicken": 16405, "agging": 16406, "\u0120pleaded": 16407, "\u0120navigation": 16408, "\u0120Returns": 16409, "\u0120[[": 16410, "ROR": 16411, "EA": 16412, "\u0120photographer": 16413, "\u0120Rider": 16414, "ippers": 16415, "\u0120slice": 16416, "\u0120erect": 16417, "\u0120hed": 16418, "issance": 16419, "\u0120Vikings": 16420, "urious": 16421, "\u0120appet": 16422, "oubtedly": 16423, "Child": 16424, "\u0120authentic": 16425, "oos": 16426, "\u0120Making": 16427, "\u0120announcing": 16428, "\u0120bod": 16429, "\u0120meter": 16430, "\u0120Nine": 16431, "\u0120Rogue": 16432, "\u0120workforce": 16433, "\u0120renewed": 16434, "\u0120organisations": 16435, "acs": 16436, "PLE": 16437, "Short": 16438, "\u0120compounds": 16439, "\u0120Visit": 16440, "\u0120envelop": 16441, "earth": 16442, "\u0120supportive": 16443, "ggle": 16444, "\u0120Brussels": 16445, "\u0120Guild": 16446, "Create": 16447, "REL": 16448, "\u0120averaged": 16449, "\u01201969": 16450, "riages": 16451, "\u0120lengthy": 16452, "\u0120forgot": 16453, "Okay": 16454, "\u0120Erd": 16455, "\u0120dealer": 16456, "\u0120recession": 16457, "DD": 16458, "\u0120desperately": 16459, "\u0120hunger": 16460, "\u0120sticks": 16461, "\u0120mph": 16462, "\u0120Faith": 16463, "\u0120intentionally": 16464, "\u0120demol": 16465, "ueller": 16466, "\u0120Sale": 16467, "\u0120debris": 16468, "spring": 16469, "\u0120leap": 16470, ">>>>": 16471, "\u0120containers": 16472, "selling": 16473, "ranean": 16474, "attering": 16475, "\u0120commented": 16476, "\u0120CM": 16477, "onut": 16478, "\u0120woods": 16479, "especially": 16480, "\u0120organize": 16481, "ivic": 16482, "\u0120Woods": 16483, "anga": 16484, "squ": 16485, "\u0120maj": 16486, "amon": 16487, "\u0120axis": 16488, "\u01201974": 16489, "\u0120Denmark": 16490, "\u0120warrior": 16491, "\u0120Pand": 16492, "\u0120outlined": 16493, "\u0120BO": 16494, "insula": 16495, "zilla": 16496, "ebook": 16497, "\u0120dare": 16498, "\u0120searched": 16499, "\u0120navigate": 16500, "Sn": 16501, "writing": 16502, "\u0120united": 16503, "Japan": 16504, "\u0120Hebrew": 16505, "\u0120flame": 16506, "\u0120relies": 16507, "\u0120catching": 16508, "\u0120Sho": 16509, "\u0120imprisonment": 16510, "\u0120pockets": 16511, "\u0120closure": 16512, "\u0120Fam": 16513, "tim": 16514, "adequ": 16515, "Activity": 16516, "\u0120recruiting": 16517, "\u0120WATCH": 16518, "\u0120Argentina": 16519, "dest": 16520, "\u0120apologize": 16521, "oro": 16522, "\u0120lacks": 16523, "\u0120tuned": 16524, "\u0120Griffin": 16525, "\u0120infamous": 16526, "\u0120celebrity": 16527, "sson": 16528, "\u0120----------------------------------------------------------------": 16529, "\u0120Isis": 16530, "\u0120Display": 16531, "\u0120credibility": 16532, "\u0120economies": 16533, "\u0120headline": 16534, "\u0120Cowboys": 16535, "\u0120indef": 16536, "\u0120lately": 16537, "\u0120incentives": 16538, "button": 16539, "\u0120Mob": 16540, "Aut": 16541, "\u0120resigned": 16542, "\u0120Om": 16543, "camp": 16544, "\u0120profiles": 16545, "\u0120schemes": 16546, "olphins": 16547, "ayed": 16548, "Clinton": 16549, "enh": 16550, "\u0120Yahoo": 16551, "\u0120abst": 16552, "\u0120ank": 16553, "suits": 16554, "\u0120wished": 16555, "\u0120Marco": 16556, "udden": 16557, "\u0120sphere": 16558, "\u0120Bishop": 16559, "\u0120incorporated": 16560, "\u0120Plant": 16561, "114": 16562, "\u0120hated": 16563, "pic": 16564, "\u0120donate": 16565, "\u0120lined": 16566, "\u0120beans": 16567, "\u0120stealing": 16568, "\u0120costume": 16569, "\u0120sheriff": 16570, "\u0120forty": 16571, "\u0120intact": 16572, "\u0120adapted": 16573, "\u0120travelling": 16574, "bart": 16575, "\u0120nicely": 16576, "\u0120dried": 16577, "\u0120scal": 16578, "osity": 16579, "NOTE": 16580, "\u0120Bh": 16581, "\u0120Broncos": 16582, "\u0120Ign": 16583, "\u0120intimate": 16584, "\u0120chemistry": 16585, "\u0120optimal": 16586, "Deb": 16587, "\u0120Generation": 16588, "\u0120],": 16589, "ichi": 16590, "\u0120Wii": 16591, "\u0120YOUR": 16592, "ventions": 16593, "Write": 16594, "\u0120popul": 16595, "unning": 16596, "\u0120Wor": 16597, "Vol": 16598, "\u0120queen": 16599, "heads": 16600, "KK": 16601, "\u0120analyze": 16602, "opic": 16603, "earchers": 16604, "\u0120dot": 16605, "legraph": 16606, "astically": 16607, "\u0120upgrades": 16608, "\u0120cares": 16609, "\u0120extending": 16610, "\u0120freeze": 16611, "\u0120inability": 16612, "\u0120organs": 16613, "\u0120pretend": 16614, "\u0120outlet": 16615, "113": 16616, "olan": 16617, "\u0120Mall": 16618, "uling": 16619, "talk": 16620, "\u0120expressing": 16621, "\u0120Always": 16622, "\u0120Begin": 16623, "files": 16624, "\u0120licenses": 16625, "%%": 16626, "\u0120Mitt": 16627, "\u0120filters": 16628, "\u0120Milwaukee": 16629, "GN": 16630, "\u0120unfold": 16631, "Mo": 16632, "\u0120nutrition": 16633, "ppo": 16634, "Bo": 16635, "\u0120founding": 16636, "\u0120undermine": 16637, "\u0120easiest": 16638, "\u0120Czech": 16639, "\u0120Mack": 16640, "\u0120sexuality": 16641, "\u0120Nixon": 16642, "Win": 16643, "\u0120Arn": 16644, "\u0120Kin": 16645, "\u00e3\u0124\u00a3": 16646, "icer": 16647, "\u0120fortun": 16648, "\u0120surfaces": 16649, "aghd": 16650, "\u0120carriers": 16651, "\u0120PART": 16652, "\u0120Tib": 16653, "\u0120interval": 16654, "\u0120frustrating": 16655, "\u0120Ship": 16656, "\u0120Armed": 16657, "ffe": 16658, "\u0120boats": 16659, "\u0120Abraham": 16660, "inis": 16661, "\u0120suited": 16662, "thread": 16663, "iov": 16664, "abul": 16665, "\u0120Venezuela": 16666, "\u0120tom": 16667, "super": 16668, "\u0120castle": 16669, "although": 16670, "ioxide": 16671, "eches": 16672, "\u0120evolutionary": 16673, "\u0120negotiate": 16674, "\u0120confronted": 16675, "Remember": 16676, "\u0120170": 16677, "Such": 16678, "\u0120911": 16679, "mult": 16680, "\u0120Abyss": 16681, "urry": 16682, "kees": 16683, "spec": 16684, "\u0120Barbara": 16685, "\u0120belonging": 16686, "\u0120villain": 16687, "istani": 16688, "\u0120accountable": 16689, "\u0120portions": 16690, "\u0120Decl": 16691, "Ur": 16692, "\u0120Kate": 16693, "gre": 16694, "\u0120magazines": 16695, "UCK": 16696, "\u0120regulate": 16697, "omon": 16698, "\u0120Almost": 16699, "\u0120overview": 16700, "\u0120scram": 16701, "\u0120loot": 16702, "\u0120Fitz": 16703, "\u0120characteristic": 16704, "\u0120Snake": 16705, "say": 16706, "\u0120Rico": 16707, "\u0120trait": 16708, "\u0120Joined": 16709, "aucus": 16710, "\u0120adaptation": 16711, "\u0120Airlines": 16712, "\u0120archae": 16713, "\u0120Ide": 16714, "\u0120bikes": 16715, "\u0120literary": 16716, "\u0120influences": 16717, "\u0120Used": 16718, "Creat": 16719, "\u0120plea": 16720, "\u0120Defence": 16721, "\u0120Assass": 16722, "\u0120pond": 16723, "ULT": 16724, ")\"": 16725, "\u0120evaluated": 16726, "\u0120obtaining": 16727, "\u0120demographic": 16728, "\u0120vigil": 16729, "aley": 16730, "\u0120spouse": 16731, "\u0120Seahawks": 16732, "respons": 16733, "\u0120Belt": 16734, "umatic": 16735, "\u0120rises": 16736, "runner": 16737, "\u0120Michelle": 16738, "\u0120potent": 16739, "race": 16740, "\u0120PAC": 16741, "Find": 16742, "olesterol": 16743, "ISS": 16744, "\u0120Introduced": 16745, "resses": 16746, "ignment": 16747, "Os": 16748, "\u0120Tu": 16749, "\u0120Dex": 16750, "icides": 16751, "\u0120sparked": 16752, "\u0120Laura": 16753, "\u0120Bryant": 16754, "\u0120smiling": 16755, "\u0120Nexus": 16756, "\u0120defendants": 16757, "\u0120Catal": 16758, "\u0120dishes": 16759, "shaped": 16760, "\u0120prolong": 16761, "mt": 16762, "($": 16763, "\u00e3\u0122\u0124": 16764, "\u0120calculations": 16765, "\u0120Same": 16766, "\u0120piv": 16767, "HH": 16768, "\u0120cancelled": 16769, "\u0120grin": 16770, "\u0120territories": 16771, "istically": 16772, "Come": 16773, "\u0120Parent": 16774, "Project": 16775, "\u0120neglig": 16776, "\u0120Privacy": 16777, "\u0120ammo": 16778, "LECT": 16779, "olutely": 16780, "\u0120Epic": 16781, "\u0120misunder": 16782, "wal": 16783, "April": 16784, "mos": 16785, "pathy": 16786, "\u0120Carson": 16787, "\u0120albums": 16788, "\u0120Easy": 16789, "\u0120pistol": 16790, "<<": 16791, "\u0120\\(": 16792, "target": 16793, "help": 16794, "\u0120interpre": 16795, "conscious": 16796, "\u0120Housing": 16797, "\u0120Joint": 16798, "127": 16799, "\u0120beers": 16800, "science": 16801, "\u0120Firefox": 16802, "effective": 16803, "\u0120Cabin": 16804, "\u0120Okay": 16805, "\u0120Applic": 16806, "\u0120spacecraft": 16807, "\u0120SR": 16808, "vet": 16809, "\u0120Strange": 16810, "SB": 16811, "\u0120corps": 16812, "iberal": 16813, "efficient": 16814, "\u0120prevalence": 16815, "\u0120economists": 16816, "118": 16817, "Thread": 16818, "ordable": 16819, "ODE": 16820, "\u0120Cant": 16821, "=-=-": 16822, "ifiable": 16823, "\u0120Around": 16824, "\u0120pole": 16825, "\u0120willingness": 16826, "CLA": 16827, "\u0120Kid": 16828, "\u0120complement": 16829, "\u0120scattered": 16830, "\u0120inmates": 16831, "\u0120bleeding": 16832, "every": 16833, "\u0120queue": 16834, "\u0120Train": 16835, "\u0120hij": 16836, "\u0120melee": 16837, "pleted": 16838, "\u0120digit": 16839, "\u0120gem": 16840, "official": 16841, "\u0120lifting": 16842, "\u00d0\u00b5": 16843, "Requ": 16844, "itutes": 16845, "\u0120packaging": 16846, "\u0120Workers": 16847, "hran": 16848, "\u0120Lebanon": 16849, "olesc": 16850, "\u0120punished": 16851, "\u0120Juan": 16852, "\u0120jam": 16853, "\u0120Document": 16854, "\u0120mapping": 16855, "icates": 16856, "\u0120inevitably": 16857, "\u0120vanilla": 16858, "\u0120Ton": 16859, "\u0120watches": 16860, "\u0120leagues": 16861, "\u0120initiated": 16862, "degree": 16863, "portion": 16864, "\u0120recalls": 16865, "\u0120ruin": 16866, "\u0120melt": 16867, "IAN": 16868, "\u0120hem": 16869, "Exp": 16870, "\u0120baking": 16871, "\u0120Colomb": 16872, "atible": 16873, "\u0120radius": 16874, "plug": 16875, "\u0120IF": 16876, "etically": 16877, "\u0120fict": 16878, "HER": 16879, "\u0120Tap": 16880, "atinum": 16881, "\u0120ink": 16882, "\u0120coh": 16883, "\u0120Wizard": 16884, "both": 16885, "tex": 16886, "\u0120spends": 16887, "\u0120Currently": 16888, "\u0120Pit": 16889, "\u0120neurons": 16890, "ignt": 16891, "\u0120rall": 16892, "\u0120buses": 16893, "building": 16894, "\u0120adjustments": 16895, "\u0120cried": 16896, "iblical": 16897, "atted": 16898, "\u0120Zion": 16899, "\u0120Matter": 16900, "\u0120meditation": 16901, "\u0120Dennis": 16902, "\u0120ours": 16903, "\u0120Tab": 16904, "\u0120rankings": 16905, "ortal": 16906, "\u0120advers": 16907, "\u0120surrender": 16908, "\u0120Gob": 16909, "cium": 16910, "omas": 16911, "imeter": 16912, "\u0120multiplayer": 16913, "\u0120heroin": 16914, "\u0120optimistic": 16915, "\u0120indicator": 16916, "\u0120Brig": 16917, "\u0120grocery": 16918, "\u0120applicant": 16919, "\u0120Rocket": 16920, "vid": 16921, "Exception": 16922, "pent": 16923, "\u0120organizing": 16924, "\u0120encounters": 16925, "\u0120TOD": 16926, "\u0120jewel": 16927, "Save": 16928, "\u0120Christie": 16929, "\u0120heating": 16930, "\u0120lazy": 16931, "\u0120CP": 16932, "\u0120cousin": 16933, "Config": 16934, "\u0120regener": 16935, "\u0120nearest": 16936, "\u0120achieving": 16937, "ENS": 16938, "throw": 16939, "\u0120Richmond": 16940, "antle": 16941, "2002": 16942, "\u0120anten": 16943, "bird": 16944, "133": 16945, "\u0120narc": 16946, "raint": 16947, "unny": 16948, "\u0120Hispanic": 16949, "ournaments": 16950, "\u0120prophe": 16951, "\u0120Thailand": 16952, "\u0120Ti": 16953, "\u0120injection": 16954, "\u0120inherit": 16955, "ravis": 16956, "\u0120medi": 16957, "\u0120whoever": 16958, "\u0120DEBUG": 16959, "GP": 16960, "\u0120Hud": 16961, "Card": 16962, "prom": 16963, "\u0120por": 16964, "\u0120overhead": 16965, "Law": 16966, "\u0120violate": 16967, "\u0120heated": 16968, "\u0120descriptions": 16969, "\u0120achievements": 16970, "\u0120Beer": 16971, "\u0120Quant": 16972, "Was": 16973, "\u0120eighth": 16974, "\u0120Iv": 16975, "\u0120specialized": 16976, "UPDATE": 16977, "\u0120Delta": 16978, "Pop": 16979, "Jul": 16980, "\u0120Ask": 16981, "ophy": 16982, "\u0120newsletters": 16983, "\u0120Tool": 16984, "\u0120gard": 16985, "\u0120Confeder": 16986, "\u0120GMT": 16987, "\u0120Abbott": 16988, "\u0120immunity": 16989, "\u0120VM": 16990, "Islam": 16991, "\u0120implicit": 16992, "wd": 16993, "\u01201944": 16994, "ravity": 16995, "ometric": 16996, "\u0120surviving": 16997, "urai": 16998, "\u0120Prison": 16999, "\u0120rust": 17000, "\u0120Sketch": 17001, "\u0120bees": 17002, "\u0120Theory": 17003, "\u0120merit": 17004, "Tex": 17005, "chat": 17006, "\u0120mim": 17007, "\u0120paste": 17008, "\u0120Koch": 17009, "\u0120ignorance": 17010, "\u0120Shoot": 17011, "\u0120basement": 17012, "United": 17013, "\u0120Advis": 17014, "height": 17015, "\u0120foster": 17016, "\u0120detain": 17017, "information": 17018, "\u0120neural": 17019, "';": 17020, "\u0120proves": 17021, "allery": 17022, "\u0120invitation": 17023, "umbers": 17024, "\u0120cattle": 17025, "\u0120bicycle": 17026, "zi": 17027, "\u0120consultant": 17028, "\u0120apology": 17029, "\u0120Tiger": 17030, "\u0120123": 17031, "999": 17032, "\u0120individually": 17033, "rt": 17034, "igion": 17035, "\u0120Brazilian": 17036, "\u0120disturb": 17037, "\u0120entrepreneurs": 17038, "\u0120forests": 17039, "cerpt": 17040, "plates": 17041, "pher": 17042, "clipse": 17043, "\u0120twitter": 17044, "\u0120acids": 17045, "ographical": 17046, "hum": 17047, "\u0120Bald": 17048, "ifully": 17049, "\u0120compiler": 17050, "\u0120DA": 17051, "\u0120donor": 17052, "asi": 17053, "\u0120tribal": 17054, "lash": 17055, "\u0120Config": 17056, "\u0120applicants": 17057, "\u0120salaries": 17058, "135": 17059, "Putin": 17060, "\u0120Focus": 17061, "irs": 17062, "\u0120misconduct": 17063, "\u0120Haz": 17064, "\u0120eaten": 17065, "Mobile": 17066, "Muslim": 17067, "\u0120Marcus": 17068, "viol": 17069, "\u0120favorable": 17070, "\u0120stub": 17071, "adin": 17072, "\u0120Hob": 17073, "\u0120faithful": 17074, "\u0120electronics": 17075, "\u0120vacuum": 17076, "wait": 17077, "backed": 17078, "economic": 17079, "dist": 17080, "\u0120tenure": 17081, "\u0120sincere": 17082, "\u0120Together": 17083, "\u0120Wave": 17084, "\u0120progression": 17085, "\u0120denying": 17086, "\u0120distress": 17087, "braska": 17088, "third": 17089, "\u0120mixing": 17090, "\u0120colonial": 17091, "\u0120privately": 17092, "\u0120unrest": 17093, "aternity": 17094, "\u0120premises": 17095, "anti": 17096, "gregation": 17097, "\u0120licence": 17098, "\u0120Hind": 17099, "\u0120Samuel": 17100, "\u0120convincing": 17101, "\u0120Ace": 17102, "\u0120Rust": 17103, "\u0120Netanyahu": 17104, "\u0120handles": 17105, "\u0120Patch": 17106, "oriented": 17107, "aho": 17108, "\u0120Gonz": 17109, "\u0120hackers": 17110, "claimer": 17111, "\u0120customs": 17112, "\u0120Gran": 17113, "fighters": 17114, "\u0120luc": 17115, "\u0120manuscript": 17116, "arenthood": 17117, "\u0120devil": 17118, "\u0120warriors": 17119, "\u0120offenders": 17120, "William": 17121, "\u0120holidays": 17122, "\u0120nightmare": 17123, "\u0120lever": 17124, "ifferent": 17125, "Stat": 17126, "\u0120exhibition": 17127, "puted": 17128, "\u0120Pure": 17129, "\u0120alpha": 17130, "\u0120enthusiasm": 17131, "\u0120Representatives": 17132, "EAR": 17133, "\u0120Typ": 17134, "\u0120wheat": 17135, "\u0120Alf": 17136, "\u0120correction": 17137, "\u0120evangel": 17138, "ATT": 17139, "Miss": 17140, "\u0120soup": 17141, "\u0120implied": 17142, "param": 17143, "\u0120sexy": 17144, "\u0120Lux": 17145, "\u0120republic": 17146, "patch": 17147, "ablish": 17148, "\u0120icons": 17149, "\u0120fathers": 17150, "\u0120GET": 17151, "\u0120Carib": 17152, "\u0120regulated": 17153, "\u0120Cohen": 17154, "\u0120Bobby": 17155, "\u0120ner": 17156, "\u0120bent": 17157, "ventory": 17158, "\u0120Along": 17159, "\u0120EST": 17160, "\u0120Wallace": 17161, "\u0120murders": 17162, "rise": 17163, "kell": 17164, "\u0120Commonwealth": 17165, "\u0120nasty": 17166, "eta": 17167, "\u0120MIT": 17168, "\u0120administered": 17169, "\u0120genuinely": 17170, "Editor": 17171, "nick": 17172, "\u0120hydro": 17173, "********************************": 17174, "\u0120Ble": 17175, "\u0120fines": 17176, "\u0120gorge": 17177, "ausible": 17178, "rh": 17179, "\u0120apple": 17180, "mentioned": 17181, "\u0120rope": 17182, "otyp": 17183, "HR": 17184, "\u0120disappointing": 17185, "\u0120cage": 17186, "nik": 17187, "\u0120doubts": 17188, "\u0120FREE": 17189, "prints": 17190, "\u0120MUST": 17191, "\u0120vendors": 17192, "\u0120Inqu": 17193, "\u0120liberals": 17194, "\u0120contractor": 17195, "\u0120upside": 17196, "children": 17197, "\u0120tricky": 17198, "\u0120regulators": 17199, "charged": 17200, "liter": 17201, "\u0120***": 17202, "\u0120rebell": 17203, "lang": 17204, "\u0120locals": 17205, "\u0120physicians": 17206, "\u0120hey": 17207, "arse": 17208, "tm": 17209, "\u0120Lex": 17210, "\u0120behavioral": 17211, "successful": 17212, "FX": 17213, "\u0120brick": 17214, "ovic": 17215, "\u0120conform": 17216, "\u0120reviewing": 17217, "\u0120insights": 17218, "\u0120biology": 17219, "\u0120Remove": 17220, "\u0120Extra": 17221, "\u0120committing": 17222, "induced": 17223, "ignty": 17224, "igm": 17225, "\u0120atomic": 17226, "Common": 17227, "\u0120EM": 17228, "\u0120Pere": 17229, "\u0120Items": 17230, "eh": 17231, "\u0120preserved": 17232, "\u0120Hood": 17233, "\u0120prisoner": 17234, "\u0120bankruptcy": 17235, "\u0120gren": 17236, "ushes": 17237, "\u0120exploitation": 17238, "\u0120signatures": 17239, "\u0120finan": 17240, "],\"": 17241, "\u0120MR": 17242, "\u0120meg": 17243, "remlin": 17244, "\u0120musicians": 17245, "\u0120selecting": 17246, "\u0120examining": 17247, "INK": 17248, "lated": 17249, "Hi": 17250, "\u0120artic": 17251, "\u0120pets": 17252, "\u0120impair": 17253, "\u0120MAN": 17254, "\u0120tablets": 17255, "include": 17256, "Range": 17257, "\u0120caut": 17258, "\u0120logs": 17259, "\u0120mounting": 17260, "\u0120unaware": 17261, "\u0120dynamics": 17262, "\u0120Palestine": 17263, "\u0120Quarter": 17264, "\u0120Purple": 17265, "\u0120ma": 17266, "\u0120Import": 17267, "\u0120collections": 17268, "ciation": 17269, "\u0120successor": 17270, "\u0120clone": 17271, "\u0120aiming": 17272, "\u0120possessed": 17273, "\u0120sticking": 17274, "\u0120shaking": 17275, "\u0120locate": 17276, "\u0120Hockey": 17277, "Turn": 17278, "170": 17279, "\u0120fifteen": 17280, "\u0120Harrison": 17281, "\u0120continuously": 17282, "\u0120TC": 17283, "\u0120Valent": 17284, "\u0120Rescue": 17285, "\u0120bypass": 17286, "amount": 17287, "\u0120mast": 17288, "\u0120protects": 17289, "\u0120artistic": 17290, "\u0120sometime": 17291, "\u0120shoe": 17292, "\u0120shouted": 17293, "ificant": 17294, "etitive": 17295, "\u0120Register": 17296, "\u0120Jin": 17297, "\u0120concentrated": 17298, "lington": 17299, "onies": 17300, "\u0120generator": 17301, "yrim": 17302, "\u0120Armen": 17303, "\u0120clearing": 17304, "ido": 17305, "\u0120TW": 17306, "alph": 17307, "\u0120ladies": 17308, "Hard": 17309, "\u0120dialog": 17310, "\u0120inputs": 17311, "\u00e6\u013e": 17312, "\u0120poses": 17313, "\u0120slots": 17314, "\u0120Premium": 17315, "\u0120leaks": 17316, "\u0120bosses": 17317, "\u0120113": 17318, "course": 17319, "Acc": 17320, "\u0120Newton": 17321, "\u0120Austria": 17322, "\u0120Mage": 17323, "\u0120teaches": 17324, "abad": 17325, "\u0120wears": 17326, "\u0120cyl": 17327, "\u0120curse": 17328, "\u0120Sales": 17329, "\u0120Wings": 17330, "\u0120psy": 17331, "\u0120gaps": 17332, "\u0120Iceland": 17333, "\u0120Pinterest": 17334, "\u0120landlord": 17335, "\u0120definitions": 17336, "\u0120Ker": 17337, "\u0120sufficiently": 17338, "\u0120Pence": 17339, "\u0120Architect": 17340, "\u0120surpass": 17341, "\u0120114": 17342, "\u0120superhero": 17343, "\u0120Disease": 17344, "\u0120priests": 17345, "\u0120Culture": 17346, "\u0120definitive": 17347, "\u0120secretly": 17348, "\u0120Dance": 17349, "install": 17350, "chief": 17351, "\u0120Jessica": 17352, "Would": 17353, "Updated": 17354, "\u0120locker": 17355, "\u0120Kay": 17356, "\u0120memorial": 17357, "\u00e8\u00a6": 17358, "fat": 17359, "\u0120disgu": 17360, "\u0120flavors": 17361, "\u0120Baseball": 17362, "\u0120Resistance": 17363, "\u0120kicks": 17364, "\u0120env": 17365, "\u0120teenagers": 17366, "Dark": 17367, "\u0120CAR": 17368, "\u0120halt": 17369, "\u0120LG": 17370, "\u0120Gabriel": 17371, "\u0120fever": 17372, "\u0120satur": 17373, "\u0120mall": 17374, "\u0120affiliate": 17375, "\u0120Sleep": 17376, "\u0120Specific": 17377, "\u0120Vel": 17378, "\u0120jar": 17379, "\u0120Sacred": 17380, "\u0120Edwards": 17381, "\u0120ACL": 17382, "\u0120retained": 17383, "\u0120Giant": 17384, "\u0120limitation": 17385, "inces": 17386, "\u0120refusal": 17387, "\u0120Tale": 17388, "\u0120Butler": 17389, "\u0120accidents": 17390, "\u0120CSS": 17391, "\u0120imported": 17392, "\u0120Copy": 17393, "\u00ce\u00b1": 17394, "ERT": 17395, "zel": 17396, "\u0120divisions": 17397, "hots": 17398, "\u0120Alb": 17399, "\u0120DS": 17400, "Loader": 17401, "Washington": 17402, "atisf": 17403, "\u0120Creative": 17404, "\\.": 17405, "\u0120Autom": 17406, "redict": 17407, "\u0120receptor": 17408, "\u0120Carlos": 17409, "Method": 17410, "oka": 17411, "\u0120malicious": 17412, "\u0120stepping": 17413, ",[": 17414, "\u0120Dad": 17415, "\u0120attraction": 17416, "\u0120Effects": 17417, "\u0120Pirate": 17418, "\u0120Cer": 17419, "\u0120Industry": 17420, "\u0120Rud": 17421, "\u0120charter": 17422, "\u0120dining": 17423, "\u0120insists": 17424, "\u0120configure": 17425, "\u0120(#": 17426, "\u0120Simple": 17427, "\u0120Scroll": 17428, "UTC": 17429, "175": 17430, "\u0120Kon": 17431, "\u0120marketplace": 17432, "\u0120\u00e3\u0124": 17433, "\u0120refres": 17434, "\u0120gates": 17435, "erred": 17436, "\u0120Pod": 17437, "\u0120behave": 17438, "Frank": 17439, "node": 17440, "\u0120endorsed": 17441, "hett": 17442, "asive": 17443, "\u0120Homeland": 17444, "\u0120rides": 17445, "\u0120Leave": 17446, "erness": 17447, "\u0120flooding": 17448, "AFP": 17449, "\u0120risen": 17450, "\u0120continually": 17451, "\u0120unanim": 17452, "\u0120Contract": 17453, "\u0120Pas": 17454, "\u0120guided": 17455, "\u0120Chile": 17456, "bd": 17457, "\u0120succ": 17458, "ptic": 17459, "\u0120committees": 17460, "\u0120Luther": 17461, "\u0120Anyone": 17462, "\u0120sab": 17463, "124": 17464, "\u0120pixel": 17465, "\u0120Bak": 17466, "\u0120Tag": 17467, "\u0120Bennett": 17468, "Enter": 17469, "small": 17470, "\u0120Presidential": 17471, "\u0120pul": 17472, "\u0120contrace": 17473, "archive": 17474, "\u0120coastal": 17475, "\u0120Kids": 17476, "192": 17477, "\u00e2\u0122\u00b2": 17478, "icky": 17479, "INGTON": 17480, "\u0120wolf": 17481, "\u0120Stalin": 17482, "Tur": 17483, "idget": 17484, "amas": 17485, "\u0120Unless": 17486, "\u0120sponsor": 17487, "\u0120morph": 17488, "\u0120Choose": 17489, "\u0120runner": 17490, "\u0120unbel": 17491, "\u0120mud": 17492, "\u0120Mana": 17493, "\u0120dubbed": 17494, "\u0120godd": 17495, "urers": 17496, "window": 17497, "\u0120relied": 17498, "\u0120celebrating": 17499, "osc": 17500, "\u0120135": 17501, "\u0120lobbying": 17502, "\u0120incomplete": 17503, "\u0120restriction": 17504, "\u0120incap": 17505, "itus": 17506, "\u0120expectation": 17507, "\u0120Apollo": 17508, "\u0120intens": 17509, "\u0120sync": 17510, "GH": 17511, "\u0120manipulation": 17512, "BY": 17513, "\u0120spear": 17514, "\u0120breasts": 17515, "\u0120volcan": 17516, "ilia": 17517, "Material": 17518, "\u0120formats": 17519, "\u0120Bast": 17520, "\u0120parliamentary": 17521, "\u0120snake": 17522, "\u0120servants": 17523, "\u0120Trudeau": 17524, "\u0120Grim": 17525, "\u0120Arabic": 17526, "\u0120SCP": 17527, "\u0120Boys": 17528, "station": 17529, "\u0120prospective": 17530, "orde": 17531, "initialized": 17532, "\u0120bored": 17533, "ABLE": 17534, "\u0120accessed": 17535, "\u0120taxi": 17536, "\u0120Shell": 17537, "aiden": 17538, "ursed": 17539, "inates": 17540, "\u0120Insurance": 17541, "\u0120Pete": 17542, "September": 17543, "650": 17544, "\u0120adventures": 17545, "\u0120Cover": 17546, "\u0120tribute": 17547, "\u0120sketch": 17548, "\u0120empower": 17549, "\u0120\u00d8": 17550, "\u0120Glenn": 17551, "\u0120Daw": 17552, "=\\\"": 17553, "\u0120Politics": 17554, "\u0120guides": 17555, "\u0120dioxide": 17556, "\u0120Gore": 17557, "\u0120Bright": 17558, "\u0120Sierra": 17559, "\u0120valued": 17560, "cond": 17561, "\u0120pointer": 17562, "Select": 17563, "\u0120risky": 17564, "\u0120absorb": 17565, "images": 17566, "\u0120refuses": 17567, "\u0120bonuses": 17568, "___": 17569, "\u0120hilar": 17570, "\u0120Features": 17571, "220": 17572, "\u0120Collector": 17573, "Foot": 17574, "\u01201964": 17575, "culus": 17576, "\u0120dawn": 17577, "\u0120workout": 17578, "\u0120LO": 17579, "\u0120philosophical": 17580, "\u0120Sandy": 17581, "\u0120Youth": 17582, "\u0120liable": 17583, "Af": 17584, "blue": 17585, "\u0120overturn": 17586, "lessness": 17587, "\u0120Tribune": 17588, "\u0120Ing": 17589, "\u0120factories": 17590, "\u0120catches": 17591, "\u0120prone": 17592, "\u0120matrix": 17593, "\u0120login": 17594, "\u0120inacc": 17595, "\u0120exert": 17596, "sys": 17597, "\u0120needle": 17598, "\u0120Qur": 17599, "\u0120notified": 17600, "oulder": 17601, "tx": 17602, "\u0120reminds": 17603, "\u0120publishers": 17604, "\u0120nort": 17605, "\u0120git": 17606, "\u0120flies": 17607, "\u0120Emily": 17608, "\u0120flowing": 17609, "\u0120Alien": 17610, "\u0120Strateg": 17611, "\u0120hardest": 17612, "\u0120modification": 17613, "API": 17614, "\u0120MY": 17615, "\u0120crashes": 17616, "stairs": 17617, "number": 17618, "\u0120urging": 17619, "channel": 17620, "\u0120Falcon": 17621, "\u0120inhabitants": 17622, "\u0120terrifying": 17623, "\u0120utilize": 17624, "\u0120banner": 17625, "\u0120cigarettes": 17626, "\u0120senses": 17627, "\u0120Holmes": 17628, "\u0120practition": 17629, "\u0120Phillips": 17630, "otto": 17631, "\u0120compile": 17632, "Model": 17633, "\u0120Ko": 17634, "\u0120[]": 17635, "Americans": 17636, "\u0120Terms": 17637, "\u0120medications": 17638, "\u0120Ana": 17639, "\u0120fundamentally": 17640, "\u0120Notice": 17641, "\u0120weaker": 17642, "\u01200000": 17643, "\u0120garlic": 17644, "\u0120outbreak": 17645, "\u0120economist": 17646, "\u0120Birth": 17647, "\u0120obstacles": 17648, "arcer": 17649, "\u0120Orthodox": 17650, "\u0120placebo": 17651, "\u0120Crew": 17652, "aspberry": 17653, "\u0120Angels": 17654, "\u0120discharge": 17655, "\u0120destructive": 17656, "117": 17657, "\u0120Rising": 17658, "\u0120dairy": 17659, "late": 17660, "\u0120collision": 17661, "\u0120Tigers": 17662, "eanor": 17663, "ocumented": 17664, "\u0120Invalid": 17665, "\u0120dont": 17666, "\u0120Liter": 17667, "\u0120Va": 17668, "\u0120hydrogen": 17669, "\u0120variants": 17670, "\u0120Browns": 17671, "\u01201965": 17672, "\u0120indigenous": 17673, "\u0120trades": 17674, "\u0120remainder": 17675, "\u0120swept": 17676, "\u0120Impact": 17677, "\u0120redist": 17678, "\u0120unint": 17679, "graduate": 17680, "\u00e3\u0125\u0137": 17681, "\u0120WILL": 17682, "\u00e3\u0123\u00ae\u00e7": 17683, "\u0120Critical": 17684, "\u0120fisher": 17685, "\u0120vicious": 17686, "\u0120reversed": 17687, "Year": 17688, "\u0120Sox": 17689, "\u0120shootings": 17690, "\u0120filming": 17691, "\u0120touchdowns": 17692, "aires": 17693, "mel": 17694, "\u0120grandfather": 17695, "\u0120affection": 17696, "ingle": 17697, "\u0120overly": 17698, "Additional": 17699, "\u0120supreme": 17700, "\u0120Grad": 17701, "\u0120sporting": 17702, "\u0120mercy": 17703, "\u0120Brooks": 17704, "ounty": 17705, "\u0120performs": 17706, "\u0120tightly": 17707, "\u0120demons": 17708, "\u0120killings": 17709, "\u0120faction": 17710, "\u0120Nova": 17711, "auts": 17712, "\u0120undoubtedly": 17713, "arin": 17714, "\u0120underway": 17715, "rak": 17716, "\u0120liv": 17717, "\u0120Region": 17718, "\u0120briefing": 17719, "sers": 17720, "cloud": 17721, "\u0120Mik": 17722, "usp": 17723, "\u0120prediction": 17724, "azor": 17725, "\u0120portable": 17726, "\u0120Gand": 17727, "\u0120presenting": 17728, "\u01201080": 17729, "\u00c2\u00bb": 17730, "ushi": 17731, "\u0120Spark": 17732, "thereum": 17733, "\u0120justification": 17734, "\u0120Ny": 17735, "\u0120contractors": 17736, "mingham": 17737, "\u0120Style": 17738, "\u00e5\u0127": 17739, "\u0120Chronicles": 17740, "\u0120Picture": 17741, "\u0120proving": 17742, "\u0120wives": 17743, "sett": 17744, "\u0120molecules": 17745, "\u0120Fairy": 17746, "\u0120consisting": 17747, "\u0120pier": 17748, "alone": 17749, "inition": 17750, "\u0120nucle": 17751, "json": 17752, "\u0120gotta": 17753, "\u0120mobil": 17754, "\u0120verbal": 17755, "arium": 17756, "\u0120monument": 17757, "ucked": 17758, "\u0120256": 17759, "Tech": 17760, "minecraft": 17761, "\u0120Track": 17762, "\u0120tile": 17763, "\u0120compatibility": 17764, "asis": 17765, "\u0120sadd": 17766, "\u0120instructed": 17767, "\u0120Mueller": 17768, "\u0120lethal": 17769, "\u0120hormone": 17770, "\u0120orche": 17771, "else": 17772, "\u0120skelet": 17773, "\u0120entertaining": 17774, "\u0120minimize": 17775, "again": 17776, "\u0120undergo": 17777, "\u0120constraints": 17778, "\u0120cigarette": 17779, "\u0120Islamist": 17780, "\u0120travels": 17781, "\u0120Panthers": 17782, "lings": 17783, "Care": 17784, "\u0120lawsuits": 17785, "uras": 17786, "\u0120cryst": 17787, "\u0120lowered": 17788, "\u0120aerial": 17789, "\u0120combinations": 17790, "\u0120haun": 17791, "\u0120cha": 17792, "\u0120vine": 17793, "\u0120quantities": 17794, "\u0120linking": 17795, "bank": 17796, "\u0120soy": 17797, "Bill": 17798, "\u0120Angela": 17799, "\u0120recipient": 17800, "\u0120Protest": 17801, "\u0120socket": 17802, "\u0120solidarity": 17803, "\u0120\u00e2\u0128": 17804, "mill": 17805, "\u0120varies": 17806, "\u0120Pakistani": 17807, "Dragon": 17808, "\u0120une": 17809, "\u0120horizon": 17810, "\u00c2\u0142\u00c2\u0142\u00c2\u0142\u00c2\u0142\u00c2\u0142\u00c2\u0142\u00c2\u0142\u00c2\u0142": 17811, "\u0120provinces": 17812, "\u0120frankly": 17813, "\u0120enacted": 17814, "notes": 17815, "['": 17816, "\u0120192": 17817, "ocracy": 17818, "\u0120endorsement": 17819, "\u0120overtime": 17820, "True": 17821, "Lab": 17822, "licted": 17823, "\u0120DNC": 17824, "\u0120beats": 17825, "\u0120Jamie": 17826, "152": 17827, "\u0120INT": 17828, "Contact": 17829, "\u0120accounted": 17830, "hash": 17831, "\u0120Packers": 17832, "pires": 17833, "\u0120lesbian": 17834, "\u0120amendments": 17835, "\u0120hopeful": 17836, "\u0120Finland": 17837, "\u0120spotlight": 17838, "\u0120configured": 17839, "\u0120troubled": 17840, "\u0120gaze": 17841, "\u0120Calgary": 17842, "\u0120reliability": 17843, "\u0120insurg": 17844, "swer": 17845, "buy": 17846, "\u0120Skin": 17847, "\u0120pixels": 17848, "\u0120handgun": 17849, "\u0120paras": 17850, "\u0120categor": 17851, "\u0120EL": 17852, "\u0120Rex": 17853, "Indeed": 17854, "\u0120kinda": 17855, "\u0120conjunction": 17856, "\u0120Bryan": 17857, "\u0120Manufact": 17858, "yang": 17859, "Plus": 17860, "SQL": 17861, "ishment": 17862, "\u0120dominate": 17863, "\u0120nail": 17864, "\u0120oath": 17865, "\u0120erupt": 17866, "\u0120Fine": 17867, "itbart": 17868, "\u0120Chip": 17869, "\u0120Abd": 17870, "\u0120Nam": 17871, "\u0120buyer": 17872, "\u0120dissent": 17873, "Leaks": 17874, "Contin": 17875, "\u0120rider": 17876, "\u0120Someone": 17877, "\u0120illusion": 17878, "cin": 17879, "\u0120Boeing": 17880, "\u0120inadequ": 17881, "ovation": 17882, "iants": 17883, "\u0120rebuild": 17884, "450": 17885, "\u0120Destiny": 17886, "SW": 17887, "\u0120Till": 17888, "Hit": 17889, "iaz": 17890, "\u0120Bangl": 17891, "achers": 17892, "\u0120Reform": 17893, "\u0120segments": 17894, "\u0120systematic": 17895, "dc": 17896, "\u0120Conservatives": 17897, "\u0120portal": 17898, "hor": 17899, "\u0120Dragonbound": 17900, "\u0120dragged": 17901, "omo": 17902, "\u0120thee": 17903, "advert": 17904, "\u0120Reports": 17905, "\u0120Et": 17906, "\u0120barrels": 17907, "August": 17908, "\u0120comparisons": 17909, "\u0120hex": 17910, "\u0120anthrop": 17911, "\"[": 17912, "borough": 17913, "abi": 17914, "\u0120pictured": 17915, "playing": 17916, "\u0120Address": 17917, "\u0120Mirror": 17918, "Smith": 17919, "\u0120tires": 17920, "\u0120NPR": 17921, "AAAA": 17922, "\u0120classification": 17923, "\u0120Than": 17924, "\u0120Harm": 17925, "\u0120RA": 17926, "\u0120rejection": 17927, "mination": 17928, "\u0120ranged": 17929, "\u0120Falls": 17930, "DI": 17931, "Host": 17932, "\u00e3\u0124\u00b4": 17933, "\u0120Example": 17934, "listed": 17935, "thirds": 17936, "\u0120safegu": 17937, "brand": 17938, "\u0120probable": 17939, "Canada": 17940, "ITION": 17941, "\u0120Qaeda": 17942, "\u0120chick": 17943, "\u0120imports": 17944, "hit": 17945, "loc": 17946, "WW": 17947, "\u0120blew": 17948, "\u0120anytime": 17949, "\u0120wholes": 17950, "iked": 17951, "\u0120calculation": 17952, "create": 17953, "\u0120Ori": 17954, "\u0120upgraded": 17955, "\u0120appar": 17956, "utory": 17957, "\u0120Mol": 17958, "Brit": 17959, "\u0120Jong": 17960, "INAL": 17961, "\u0120Starting": 17962, "\u0120dice": 17963, "urtle": 17964, "\u0120relying": 17965, "closure": 17966, "\u0120profitable": 17967, "\u0120slaughter": 17968, "\u0120Manual": 17969, "caster": 17970, "\u0120\"$": 17971, "\u0120feather": 17972, "\u0120Simply": 17973, "ieves": 17974, "\u0120deterior": 17975, "\u0120PCI": 17976, "\u0120stamp": 17977, "\u0120flaws": 17978, "\u0120shade": 17979, "hammer": 17980, "\u0120passport": 17981, "\u0120conting": 17982, "amel": 17983, "\u0120observers": 17984, "\u0120neglect": 17985, "\u0120RB": 17986, "\u0120Brotherhood": 17987, "\u0120skeptical": 17988, "family": 17989, "usk": 17990, "\u0120emotionally": 17991, "\u00e2\u013b": 17992, "\u0120Beta": 17993, "asonable": 17994, "idity": 17995, "\u0120Mul": 17996, "\u0120kicking": 17997, "\u0120Carm": 17998, "ollah": 17999, "VERTIS": 18000, "\u0120Athen": 18001, "\u0120ladder": 18002, "\u0120Bullet": 18003, "\u00e5\u00a3": 18004, "0001": 18005, "\u0120Wildlife": 18006, "\u0120Mask": 18007, "\u0120Nan": 18008, "Rev": 18009, "\u0120unacceptable": 18010, "legal": 18011, "\u0120crowded": 18012, "agi": 18013, "\u0120Cox": 18014, "je": 18015, "\u0120morality": 18016, "\u0120fuels": 18017, "\u0120cables": 18018, "\u0120mankind": 18019, "\u0120Caribbean": 18020, "\u0120anchor": 18021, "\u0120byte": 18022, "\u0120Often": 18023, "\u0120Oz": 18024, "\u0120crafted": 18025, "\u0120historian": 18026, "\u0120Wu": 18027, "\u0120towers": 18028, "\u0120Citizens": 18029, "\u0120helm": 18030, "\u0120credentials": 18031, "\u0120singular": 18032, "\u0120Jesse": 18033, "\u0120tackles": 18034, "\u0120contempt": 18035, "\u0120afore": 18036, "\u0120Shadows": 18037, "\u0120nil": 18038, "\u0120urgent": 18039, "apple": 18040, "blood": 18041, "\u0120von": 18042, "\u0120offline": 18043, "\u0120breathe": 18044, "\u0120jumps": 18045, "\u0120irrelevant": 18046, "oxic": 18047, "omal": 18048, "important": 18049, "Jim": 18050, "\u0120gloves": 18051, "arming": 18052, "depth": 18053, "\u0120talents": 18054, "ookie": 18055, "\u0120SB": 18056, "\u0120palm": 18057, "uffs": 18058, "esta": 18059, "IGH": 18060, "\u0120canon": 18061, "\u0120Verizon": 18062, "\u0120Ple": 18063, "\u0120coupled": 18064, "velt": 18065, "\u0120fundraising": 18066, "\u0120Getting": 18067, "\u0120DLC": 18068, "\u0120mathematical": 18069, "\u0120HS": 18070, "\u0120Cardinals": 18071, "telling": 18072, "\u0120sponsors": 18073, "\u0120\u00cf": 18074, "\u0120Bulls": 18075, "option": 18076, "\u0120propose": 18077, "\u0120memorable": 18078, "\u0120embraced": 18079, "\u0120declining": 18080, "Health": 18081, "eda": 18082, "\u0120};": 18083, "\u0120spam": 18084, "mile": 18085, "\u0120pitcher": 18086, "\u0120Eight": 18087, "\u0120caring": 18088, "utic": 18089, "role": 18090, "\u0120airline": 18091, "ernandez": 18092, "\u0120Athlet": 18093, "\u0120certification": 18094, "uxe": 18095, "riger": 18096, "\u0120empir": 18097, "\u0120sensation": 18098, "\u0120dism": 18099, "\u0120bolt": 18100, "\u0120evolve": 18101, "House": 18102, "\u0120consultation": 18103, "\u0120Duty": 18104, "\u0120touches": 18105, "\u0120Nathan": 18106, "\u0120faint": 18107, "had": 18108, "\"(": 18109, "\u0120Consumer": 18110, "\u0120Extreme": 18111, "\u0120127": 18112, "\u0120Herm": 18113, "\u0120Sacrament": 18114, "izoph": 18115, "\u0120anxious": 18116, "ulously": 18117, "\u0120socially": 18118, "\u0120UTC": 18119, "\u0120solving": 18120, "\u0120Letter": 18121, "History": 18122, "educ": 18123, "Price": 18124, "));": 18125, "\u0120reload": 18126, "amic": 18127, "\u0120pork": 18128, "\u0120discourse": 18129, "\u0120tournaments": 18130, "airo": 18131, "\u0120Kur": 18132, "\u0120Costa": 18133, "\u0120violating": 18134, "\u0120interfere": 18135, "\u0120recreational": 18136, "uffle": 18137, "\u0120speeches": 18138, "\u0120needing": 18139, "\u0120remembers": 18140, "\u0120credited": 18141, "nia": 18142, "focused": 18143, "amera": 18144, "\u0120bru": 18145, "umbs": 18146, "\u0120Cuban": 18147, "\u0120preceding": 18148, "\u0120nonsense": 18149, "acial": 18150, "\u0120smartphones": 18151, "\u0120Stories": 18152, "Sports": 18153, "\u0120Emergency": 18154, "ouncing": 18155, "efined": 18156, "\u0120ber": 18157, "\u0120consulting": 18158, "\u0120masters": 18159, "heastern": 18160, ".\"[": 18161, "\u0120Running": 18162, "\u0120suscept": 18163, "\u0120Feng": 18164, "America": 18165, "prises": 18166, "stitial": 18167, "\u0120Weekly": 18168, "\u0120Greater": 18169, "modules": 18170, "ifter": 18171, "Graphics": 18172, "uler": 18173, "\u0120wholly": 18174, "\u0120suppress": 18175, "\u0120concealed": 18176, "\u0120happily": 18177, "\u0120accepts": 18178, "\u0120Enjoy": 18179, "\u0120rivers": 18180, "\u0120Except": 18181, "225": 18182, "\u0120NHS": 18183, "\u0120McConnell": 18184, "\u0120pussy": 18185, "ferred": 18186, "utable": 18187, "\u0120attain": 18188, "\u0120>=": 18189, "\u0120deposits": 18190, "rophic": 18191, "\u0120notorious": 18192, "\u0120Shaw": 18193, "ilitation": 18194, "\u0120epidemic": 18195, "allic": 18196, "\u0120smallest": 18197, "ovich": 18198, "\u0120accessories": 18199, "perties": 18200, "\u0120surplus": 18201, "\u0120Mech": 18202, "\u0120ambig": 18203, "\u0120Immigration": 18204, "\u0120chim": 18205, "eval": 18206, "\u0120practicing": 18207, "\u0120Mystery": 18208, "\u0120domains": 18209, "\u0120Silicon": 18210, "apps": 18211, "\u0120kilometers": 18212, "ea": 18213, "\u0120Smash": 18214, "\u0120warranty": 18215, "\u0120nost": 18216, "sil": 18217, "rev": 18218, "Jon": 18219, "\u0120Dublin": 18220, "\u0120tastes": 18221, "\u0120bout": 18222, "great": 18223, "error": 18224, "\u0120switches": 18225, "\u0120Bapt": 18226, "DO": 18227, "oki": 18228, "\u0120sourced": 18229, "produ": 18230, "\u0120attachment": 18231, "\u0120Issue": 18232, "\u0120Question": 18233, "Join": 18234, "\u0120fitted": 18235, "\u0120unlawful": 18236, "^^": 18237, "erek": 18238, "\u0120authentication": 18239, "\u0120stole": 18240, "\u0120accountability": 18241, "label": 18242, "Search": 18243, "\u0120albeit": 18244, "atican": 18245, "funded": 18246, "\u0120Adding": 18247, "\u0120IQ": 18248, "\u0120submar": 18249, "lit": 18250, "aque": 18251, "\u0120Learning": 18252, "\u0120integer": 18253, "Master": 18254, "\u0120Chrom": 18255, "\u0120premier": 18256, "Op": 18257, "\u0120Liu": 18258, "\u0120blessed": 18259, "\u0120Globe": 18260, "\u0120Response": 18261, "\u0120legitim": 18262, "\u0120Merkel": 18263, "\u0120disposal": 18264, "\u00c2\u00b4": 18265, "\u0120gauge": 18266, "peat": 18267, "\u0120induced": 18268, "\u0120questionable": 18269, "arthy": 18270, "\u0120Vit": 18271, "\u0120Feed": 18272, "Until": 18273, "Ut": 18274, "worthy": 18275, "RY": 18276, "\u0120Herald": 18277, "\u0120Hammer": 18278, "\u0120medal": 18279, "\u0120Rivers": 18280, "\u0120Hack": 18281, "\u0120clarify": 18282, "\u0120tracked": 18283, "\u0120autonomous": 18284, "\u0120tenant": 18285, "\u0120Qatar": 18286, "erie": 18287, "\u0120grim": 18288, "\u0120Monitor": 18289, "\u0120resistant": 18290, "\u0120Spec": 18291, "\u0120Wells": 18292, "NAS": 18293, "148": 18294, "\u0120miners": 18295, "iotics": 18296, "\u0120misses": 18297, "116": 18298, "gian": 18299, "git": 18300, "\u0120Eyes": 18301, "pres": 18302, "\u0120graduated": 18303, "\u0120angel": 18304, "\u0120synchron": 18305, "\u0120efficiently": 18306, "\u0120transmitted": 18307, "Harry": 18308, "\u0120globally": 18309, "ENCE": 18310, "\u0120Montana": 18311, "raged": 18312, "\u0120Prevention": 18313, "\u0120piss": 18314, "\u0120Ll": 18315, "\u0120shelf": 18316, "\u0120BJP": 18317, "\u0120Testament": 18318, "\u0120Late": 18319, "iker": 18320, "\u0120Happ": 18321, "\u0120Julian": 18322, "hall": 18323, "\u0120spont": 18324, "\u0120shutdown": 18325, "\u0120inconsistent": 18326, "\u0120subscribers": 18327, "\u0120skeleton": 18328, "\u0120Nebraska": 18329, "\u0120inspire": 18330, "\u0120Void": 18331, "Feed": 18332, "\u0120angles": 18333, "\u0120Springs": 18334, "\u0120benchmark": 18335, "\u0120vaccines": 18336, "izophren": 18337, "sexual": 18338, "uffed": 18339, "\u0120shine": 18340, "\u0120Kath": 18341, "\u0120gesture": 18342, "inea": 18343, "\u0120rip": 18344, "\u0120oppression": 18345, "\u0120conscience": 18346, "bt": 18347, "\u0120Lum": 18348, "\u0120incidence": 18349, "\u0120Fa": 18350, "wr": 18351, "\u0120mineral": 18352, "\u0120Spurs": 18353, "alky": 18354, "\u0120thunder": 18355, "\u0120opio": 18356, "Being": 18357, "\u0120Palm": 18358, "\u0120wasted": 18359, "\u0120lb": 18360, "iaries": 18361, "\u0120Initiative": 18362, "\u0120curric": 18363, "\u0120marker": 18364, "\u0120McL": 18365, "\u0120extensions": 18366, "\u0120Pv": 18367, "\u0120Arms": 18368, "\u0120offerings": 18369, "\u0120defenses": 18370, "\u0120vendor": 18371, "\u0120contradict": 18372, "\u0120Colin": 18373, "\u0120reddit": 18374, "\u0120peripher": 18375, "122": 18376, "\u0120sins": 18377, "Edit": 18378, "ICT": 18379, "Soft": 18380, "\u0120Shah": 18381, "\u0120administrator": 18382, "\u0120Trip": 18383, "\u0120pornography": 18384, "\u0120tuition": 18385, "inence": 18386, "\u0120Progress": 18387, "\u0120catalog": 18388, "\u0120suite": 18389, "\u0120hike": 18390, "\u0120reproductive": 18391, "engine": 18392, "\u0120drought": 18393, "\u0120Noah": 18394, "\u0120230": 18395, "\u0120dude": 18396, "\u0120relaxed": 18397, "\u0120partition": 18398, "\u0120participant": 18399, "\u0120telesc": 18400, "\u0120feas": 18401, "\u0120FF": 18402, "owner": 18403, "\u0120sweeping": 18404, "\u0120lenses": 18405, "\u0120matchup": 18406, "\u0120Repl": 18407, "ournals": 18408, "\u0120credible": 18409, "\u0120grandmother": 18410, "\u0120thermal": 18411, "\u0120subscribing": 18412, "\u0120identities": 18413, "colm": 18414, "UCT": 18415, "\u0120reluctant": 18416, "users": 18417, "\u0120Cort": 18418, "\u0120assisted": 18419, "OSS": 18420, "ATIONS": 18421, "ISH": 18422, "\u0120pharmaceutical": 18423, "icable": 18424, "adian": 18425, "\u0120Sonic": 18426, "\u0120Fury": 18427, "\u0120Mong": 18428, "AH": 18429, "\u0120Psychology": 18430, "\u0120phosph": 18431, "\u0120treats": 18432, "\u0143\u0136": 18433, "\u0120steadily": 18434, "\u0120Hello": 18435, "\u0120relates": 18436, "\u0120clue": 18437, "Expl": 18438, "auth": 18439, "\u0120revision": 18440, "\u0120eld": 18441, "osion": 18442, "\u0120bron": 18443, "144": 18444, "rikes": 18445, "\u0120mines": 18446, "\u0120blanket": 18447, "\u0120Fail": 18448, "eled": 18449, "\u0120Imagine": 18450, "\u0120Planned": 18451, "aic": 18452, "Request": 18453, "Mad": 18454, "\u0120Horse": 18455, "\u0120Eagle": 18456, "\u0120capac": 18457, "157": 18458, "\u0120ling": 18459, "\u0120Nice": 18460, "\u0120Parenthood": 18461, "minster": 18462, "ogs": 18463, "ensitive": 18464, "Nothing": 18465, "\u0120carn": 18466, "Fin": 18467, "\u0120PE": 18468, "\u0120rifles": 18469, "\u0120LP": 18470, "Sand": 18471, "\u0120guiActive": 18472, "\u0120tourist": 18473, "CNN": 18474, "\u0120unveiled": 18475, "\u0120predecessor": 18476, "}{": 18477, "uber": 18478, "\u0120offshore": 18479, "\u0120optical": 18480, "\u0120Rot": 18481, "\u0120Pearl": 18482, "eton": 18483, "\u0120stared": 18484, "\u0120farther": 18485, "atility": 18486, "contin": 18487, "\u0120Gy": 18488, "\u0120Foster": 18489, "\u0120Coc": 18490, "rients": 18491, "\u0120designing": 18492, "\u0120Economy": 18493, "ONG": 18494, "Women": 18495, "\u0120Nancy": 18496, "erver": 18497, "\u0120mascul": 18498, "\u0120casualties": 18499, "\u0120225": 18500, "\u0120Sullivan": 18501, "\u0120Choice": 18502, "\u0120aster": 18503, "ws": 18504, "\u0120hotels": 18505, "\u0120considerations": 18506, "\u0120couch": 18507, "\u0120Strip": 18508, "\u0120Gn": 18509, "\u0120manipulate": 18510, "lied": 18511, "\u0120synthetic": 18512, "\u0120assaulted": 18513, "\u0120offenses": 18514, "\u0120Drake": 18515, "\u0120impe": 18516, "October": 18517, "\u0120Heritage": 18518, "hl": 18519, "\u0120Blair": 18520, "Unlike": 18521, "\u0120grief": 18522, "\u0120450": 18523, "\u0120opted": 18524, "\u0120resignation": 18525, "ilo": 18526, "\u0120verse": 18527, "\u0120Tomb": 18528, "\u0120upt": 18529, "\u0120aired": 18530, "\u0120Hook": 18531, "\u0120MLB": 18532, "\u0120assumes": 18533, "outed": 18534, "\u0120Vers": 18535, "\u0120inferior": 18536, "\u0120bundle": 18537, "\u0120DNS": 18538, "ographer": 18539, "\u0120multip": 18540, "\u0120Souls": 18541, "\u0120illustrated": 18542, "\u0120tactic": 18543, "\u0120dressing": 18544, "\u0120duo": 18545, "Conf": 18546, "\u0120relent": 18547, "\u0120cant": 18548, "\u0120scarce": 18549, "\u0120candy": 18550, "\u0120CF": 18551, "\u0120affiliated": 18552, "\u0120sprint": 18553, "ylan": 18554, "\u0120Garcia": 18555, "\u0120junk": 18556, "Print": 18557, "exec": 18558, "Crit": 18559, "\u0120portrait": 18560, "iries": 18561, "\u0120OFF": 18562, "\u0120disputes": 18563, "WR": 18564, "Love": 18565, "\u00e3\u0123\u0126": 18566, "\u0120Reyn": 18567, "\u0120hipp": 18568, "opath": 18569, "\u0120floors": 18570, "\u0120Feel": 18571, "\u0120worries": 18572, "\u0120settlements": 18573, "\u0120Pos": 18574, "\u0120mosque": 18575, "\u0120finals": 18576, "\u0120crushed": 18577, "\u0120Probably": 18578, "\u0120Bot": 18579, "\u0120Mans": 18580, "\u0120Period": 18581, "\u0120sovereignty": 18582, "\u0120seller": 18583, "\u0120apost": 18584, "\u0120amateur": 18585, "\u0120dorm": 18586, "\u0120consuming": 18587, "\u0120armour": 18588, "\u0120Roose": 18589, "\u0120intensive": 18590, "\u0120eliminating": 18591, "\u0120Sunni": 18592, "\u0120Aleppo": 18593, "jin": 18594, "\u0120advise": 18595, "pal": 18596, "\u0120Halo": 18597, "\u0120descent": 18598, "\u0120simpler": 18599, "\u0120booth": 18600, "STR": 18601, "Later": 18602, "\u0120Cave": 18603, "===": 18604, "\u0120mol": 18605, "\u0120fist": 18606, "\u0120shotgun": 18607, "supp": 18608, "\u0120robbery": 18609, "Effect": 18610, "\u0120obscure": 18611, "\u0120Professional": 18612, "\u0120embassy": 18613, "\u0120militant": 18614, "\u0120incarcer": 18615, "\u0120generates": 18616, "\u0120launches": 18617, "\u0120administrators": 18618, "\u0120shaft": 18619, "\u0120circular": 18620, "\u0120freshman": 18621, "\u0120Wes": 18622, "\u0120Joel": 18623, "\u0120Drew": 18624, "\u0120Duncan": 18625, "\u0120Apparently": 18626, "sight": 18627, "\u0120Internal": 18628, "\u0120Individual": 18629, "\u0120FE": 18630, "\u0120bore": 18631, "\u0120Mt": 18632, "\u0120broadly": 18633, "\u0120Options": 18634, "ountain": 18635, "ipes": 18636, "\u0120Videos": 18637, "204": 18638, "\u0120hills": 18639, "\u0120simulation": 18640, "\u0120disappointment": 18641, "itan": 18642, "\u0120Laboratory": 18643, "\u0120upward": 18644, "\u0120boundary": 18645, "\u0120darker": 18646, "hart": 18647, "\u0120dominance": 18648, "Cong": 18649, "\u0120Oracle": 18650, "\u0120Lords": 18651, "\u0120scholarship": 18652, "\u0120Vincent": 18653, "ede": 18654, "\u0120Rah": 18655, "\u0120encourages": 18656, "rov": 18657, "\u0120quo": 18658, "\u0120premise": 18659, "\u0120Crisis": 18660, "\u0120Holocaust": 18661, "\u0120rhythm": 18662, "\u0120metric": 18663, "club": 18664, "\u0120transported": 18665, "\u0120nod": 18666, "\u0120Pist": 18667, "\u0120ancestors": 18668, "\u0120Freder": 18669, "thumbnails": 18670, "\u0120CE": 18671, "OND": 18672, "Phil": 18673, "venge": 18674, "\u0120Products": 18675, "castle": 18676, "\u0120qualifying": 18677, "\u0120Karen": 18678, "VERTISEMENT": 18679, "\u0120mighty": 18680, "\u0120explanations": 18681, "\u0120fixing": 18682, "Di": 18683, "\u0120declaring": 18684, "\u0120anonymity": 18685, "\u0120juven": 18686, "\u0120Nord": 18687, "\u0120Doom": 18688, "\u0120Actually": 18689, "Ok": 18690, "phis": 18691, "\u0120Desert": 18692, "\u0120116": 18693, "IK": 18694, "\u0120FM": 18695, "\u0120incomes": 18696, "VEL": 18697, "okers": 18698, "\u0120pecul": 18699, "\u0120lightweight": 18700, "gue": 18701, "\u0120accent": 18702, "\u0120increment": 18703, "\u0120Chan": 18704, "\u0120complaining": 18705, "\u0120Baghd": 18706, "\u0120midfielder": 18707, "\u0120overhaul": 18708, "Process": 18709, "\u0120Hollow": 18710, "\u0120Titans": 18711, "Small": 18712, "manuel": 18713, "\u0120Unity": 18714, "\u0120Events": 18715, "Sty": 18716, "\u0120disproportion": 18717, "nesty": 18718, "enes": 18719, "\u0120Cod": 18720, "\u0120demonstrations": 18721, "\u0120Crimson": 18722, "\u0120OH": 18723, "\u0120enrolled": 18724, "\u0120cel": 18725, "\u0120Brett": 18726, "\u0120aide": 18727, "\u0120heels": 18728, "\u0120broadband": 18729, "\u0120marking": 18730, "\u0120wizard": 18731, "\u0120NJ": 18732, "\u0120Chiefs": 18733, "\u0120ingredient": 18734, "\u0120dug": 18735, "\u0120Shut": 18736, "urchase": 18737, "endor": 18738, "\u0120farmer": 18739, "\u0120Goldman": 18740, "129": 18741, "155": 18742, "Order": 18743, "\u0120lion": 18744, "iably": 18745, "\u0120stain": 18746, "array": 18747, "ilitary": 18748, "\u0120FAQ": 18749, "\u0120exploded": 18750, "\u0120McCarthy": 18751, "\u0120Tweet": 18752, "\u0120Greens": 18753, "eking": 18754, "ln": 18755, "ensen": 18756, "\u0120motorcycle": 18757, "\u0120particle": 18758, "\u0120cholesterol": 18759, "Bron": 18760, "\u0120stair": 18761, "\u0120oxid": 18762, "\u0120desirable": 18763, "ibles": 18764, "\u0120theor": 18765, "forcing": 18766, "\u0120promotional": 18767, "ovo": 18768, "boot": 18769, "\u0120Bonus": 18770, "rawling": 18771, "\u0120shortage": 18772, "\u0120Psy": 18773, "\u0120recruited": 18774, "\u0120infants": 18775, "\u0120testosterone": 18776, "\u0120deduct": 18777, "\u0120distinctive": 18778, "\u0120firmware": 18779, "built": 18780, "145": 18781, "\u0120explored": 18782, "\u0120factions": 18783, "\u0120vide": 18784, "\u0120tattoo": 18785, "\u0120financially": 18786, "\u0120fatigue": 18787, "\u0120proceeding": 18788, "constitutional": 18789, "\u0120miser": 18790, "\u0120chairs": 18791, "gging": 18792, "ipple": 18793, "\u0120dent": 18794, "\u0120disreg": 18795, "\u00e7\u0136": 18796, "stant": 18797, "llo": 18798, "bps": 18799, "akening": 18800, "\u0120abnormal": 18801, "\u0120ERA": 18802, "\u00e5\u00a3\u00ab": 18803, "\u0120HBO": 18804, "\u0120MAR": 18805, "\u0120concess": 18806, "\u0120servant": 18807, "\u0120aspir": 18808, "lav": 18809, "\u0120Panel": 18810, "amo": 18811, "\u0120precip": 18812, "\u0120recordings": 18813, "\u0120proceeded": 18814, "\u0120colony": 18815, "\u0120Tang": 18816, "ablo": 18817, "\u0120stripped": 18818, "Left": 18819, "too": 18820, "\u0120potatoes": 18821, "\u0120finest": 18822, "%).": 18823, "\u0120crap": 18824, "\u0120Zach": 18825, "abases": 18826, "\u0120Goth": 18827, "\u0120billionaire": 18828, "wolf": 18829, "\u0120sanction": 18830, "SK": 18831, "\u0120logged": 18832, "Po": 18833, "eyed": 18834, "unal": 18835, "\u0120cricket": 18836, "\u0120armies": 18837, "\u0120uncovered": 18838, "Cloud": 18839, "\u00c3\u00b3n": 18840, "\u0120rebounds": 18841, "\u0120mes": 18842, "Oper": 18843, "Pac": 18844, "\u0120nationally": 18845, "\u0120inserted": 18846, "pict": 18847, "\u0120governance": 18848, "\u00d0\u00b8": 18849, "\u0120privileges": 18850, "GET": 18851, "\u0120favorites": 18852, "imity": 18853, "\u0120lover": 18854, "them": 18855, "empl": 18856, "\u0120gorgeous": 18857, "Ann": 18858, "\u0120slipped": 18859, "\u0120veto": 18860, "Bob": 18861, "\u0120slim": 18862, "ucc": 18863, "\u0120Fame": 18864, "uddenly": 18865, "\u0120denies": 18866, "\u0120Maur": 18867, "\u0120distances": 18868, "\u0120wanna": 18869, "tar": 18870, "\u0120SER": 18871, "\u0120\u00e2\u012a": 18872, "\u0120lemon": 18873, "athetic": 18874, "\u0120literal": 18875, "\u0120distinguished": 18876, "\u0120answering": 18877, "GI": 18878, "\u0120religions": 18879, "\u0120Philos": 18880, "\u0120Lay": 18881, "\u0120compos": 18882, "irements": 18883, "\u0120Kos": 18884, "inez": 18885, "rolling": 18886, "\u0120youngest": 18887, "andise": 18888, "\u0120Born": 18889, "\u0120altar": 18890, "amina": 18891, "\u0120Boot": 18892, "voc": 18893, "\u0120digging": 18894, "\u0120pressures": 18895, "\u0120len": 18896, "264": 18897, "\u0120assassination": 18898, "\u0120Birmingham": 18899, "\u0120Myth": 18900, "\u0120sovereign": 18901, "\u0120Artist": 18902, "\u0120Photograph": 18903, "\u0120depicted": 18904, "\u0120dispens": 18905, "orthy": 18906, "\u0120ambul": 18907, "integ": 18908, "\u0120Cele": 18909, "\u0120Tibet": 18910, "\u0120hierarchy": 18911, "\u0120cu": 18912, "\u0120preseason": 18913, "\u0120Peterson": 18914, "\u0120colours": 18915, "\u0120worrying": 18916, "\u0120backers": 18917, "\u0120Palmer": 18918, "\u0120\u00ce\u00bc": 18919, "\u0120contributor": 18920, "\u0120hearings": 18921, "\u0120urine": 18922, "\u0120\u00d9": 18923, "ourgeois": 18924, "Similar": 18925, "\u0120Zimmer": 18926, "something": 18927, "\u0120USC": 18928, "\u0120strengths": 18929, "\u0120FI": 18930, "\u0120logging": 18931, "Asked": 18932, "\u0120Thai": 18933, "inqu": 18934, "\u0120Walt": 18935, "\u0120crews": 18936, "itism": 18937, "301": 18938, "\u0120sharply": 18939, "umed": 18940, "\u0120redirect": 18941, "rators": 18942, "Inf": 18943, "\u0120Weapons": 18944, "\u0120teasp": 18945, "1999": 18946, "Live": 18947, "\u0120Especially": 18948, "\u0120Ster": 18949, "\u0120Veterans": 18950, "\u0120intro": 18951, "otherapy": 18952, "\u0120malware": 18953, "\u0120breeding": 18954, "\u0120molecular": 18955, "\u0120Route": 18956, "\u0120Comment": 18957, "ochem": 18958, "\u0120ain": 18959, "Season": 18960, "\u0120linebacker": 18961, "\u00c4\u00ab": 18962, "\u0120Economics": 18963, "esar": 18964, "\u0120Lives": 18965, "\u0120Emma": 18966, "\u0120kin": 18967, "\u0120Territ": 18968, "\u0120planted": 18969, "oton": 18970, "\u0120Butter": 18971, "\u0120Spons": 18972, "PER": 18973, "\u0120dungeon": 18974, "\u0120symbolic": 18975, "\u0120filmed": 18976, "\u0120diets": 18977, "\u0120concludes": 18978, "\u0120certainty": 18979, "\u0120Format": 18980, "\u0120strangers": 18981, "format": 18982, "\u0120Phase": 18983, "\u0120copied": 18984, "\u0120metres": 18985, "lda": 18986, "\u0120Users": 18987, "\u0120deliberate": 18988, "\u0120washed": 18989, "\u0120Lance": 18990, "imation": 18991, "\u0120improper": 18992, "\u0120Genesis": 18993, "ickr": 18994, "\u0120Kush": 18995, "\u0120realise": 18996, "\u0120embarrassing": 18997, "alking": 18998, "bucks": 18999, "\u0120verified": 19000, "\u0120outline": 19001, "years": 19002, "\u0120Income": 19003, "202": 19004, "\u0120zombies": 19005, "Final": 19006, "\u0120Millenn": 19007, "\u0120modifications": 19008, "\u0120Vision": 19009, "\u0120Moses": 19010, "verb": 19011, "iterranean": 19012, "\u0120Jet": 19013, "\u0120naval": 19014, "\u0120Agg": 19015, "\u0120url": 19016, "\u0120victories": 19017, "\u0120nonetheless": 19018, "\u0120injust": 19019, "\u0120Fact": 19020, "\u00e7\u013c": 19021, "\u0120insufficient": 19022, "review": 19023, "facebook": 19024, "\u0120negotiating": 19025, "\u0120guarantees": 19026, "imen": 19027, "utenberg": 19028, "\u0120gambling": 19029, "\u0120congr": 19030, "Loading": 19031, "\u0120nevertheless": 19032, "\u0120presidents": 19033, "\u0120Industrial": 19034, "\u0120118": 19035, "\u0120poured": 19036, "\u0120Tory": 19037, "\u0120175": 19038, "\u0120:=": 19039, "Scott": 19040, "angered": 19041, "Tok": 19042, "\u0120organizers": 19043, "Mat": 19044, "\u0120Growth": 19045, "\u0120adul": 19046, "\u0120ensures": 19047, "\u0120117": 19048, "\u00e9\u00be\u012f\u00e5": 19049, "\u0120massacre": 19050, "\u0120grades": 19051, "before": 19052, "ADVERTISEMENT": 19053, "\u0120Slow": 19054, "\u0120MMA": 19055, "\u00e2\u0122\u0136\"": 19056, "\u0120Vatican": 19057, "Qaeda": 19058, "\u0120owe": 19059, "6666": 19060, "\u0120Sorry": 19061, "\u0120Grass": 19062, "\u0120backgrounds": 19063, "\u0120exhausted": 19064, "\u0120clan": 19065, "\u0120compromised": 19066, "\u0120Elf": 19067, "\u0120Isaac": 19068, "enson": 19069, "Invest": 19070, "IFA": 19071, "\u0120interrupted": 19072, "\u00e3\u0125\u012b\u00e3\u0125\u00a9": 19073, "\u0120twisted": 19074, "\u0120Dragons": 19075, "Mode": 19076, "\u0120Kremlin": 19077, "\u0120fertil": 19078, "heres": 19079, "phan": 19080, "\u0120Node": 19081, "fed": 19082, "\u0120Orc": 19083, "\u0120unwilling": 19084, "Cent": 19085, "\u0120priorit": 19086, "\u0120graduates": 19087, "\u0120subjective": 19088, "\u0120issuing": 19089, "\u0120Lt": 19090, "\u0120viewer": 19091, "\u0120woke": 19092, "Thus": 19093, "brook": 19094, "\u0120depressed": 19095, "\u0120bracket": 19096, "\u0120Gor": 19097, "\u0120Fighting": 19098, "\u0120striker": 19099, "Report": 19100, "\u0120Portugal": 19101, "\u0120neo": 19102, "wed": 19103, "199": 19104, "\u0120fleeing": 19105, "shadow": 19106, "identified": 19107, "USE": 19108, "Steam": 19109, "\u0120stretched": 19110, "\u0120revelations": 19111, "arted": 19112, "\u0120Dw": 19113, "\u0120alignment": 19114, "eston": 19115, "\u0120Jared": 19116, "Sep": 19117, "\u0120blogs": 19118, "update": 19119, "gom": 19120, "risk": 19121, "\u0120clash": 19122, "\u0120Hour": 19123, "\u0120runtime": 19124, "\u0120unwanted": 19125, "\u0120scam": 19126, "\u0120rack": 19127, "\u0120enlight": 19128, "onest": 19129, "\u0120Ferr": 19130, "\u0120convictions": 19131, "\u0120piano": 19132, "\u0120circulation": 19133, "\u0120Welcome": 19134, "\u0120backlash": 19135, "\u0120Wade": 19136, "\u0120receivers": 19137, "otive": 19138, "Jeff": 19139, "\u0120networking": 19140, "\u0120Prep": 19141, "\u0120Explorer": 19142, "\u0120lecture": 19143, "\u0120uploaded": 19144, "\u0120Meat": 19145, "BLE": 19146, "\u0120Nazis": 19147, "\u0120Synd": 19148, "stud": 19149, "roots": 19150, "rians": 19151, "\u0120portrayed": 19152, "\u0120??": 19153, "\u0120Buddha": 19154, "sun": 19155, "Robert": 19156, "\u0120Complex": 19157, "\u0120oversee": 19158, "\u0120stealth": 19159, "Title": 19160, "\u0120Jobs": 19161, "\u0120Kum": 19162, "\u0120appreciation": 19163, "\u0120MOD": 19164, "\u0120basics": 19165, "\u0120clips": 19166, "\u0120nursing": 19167, "\u0120proposition": 19168, "\u0120realised": 19169, "\u0120NYC": 19170, "\u0120allocated": 19171, "rium": 19172, "aran": 19173, "\u0120Production": 19174, "\u0120Vote": 19175, "\u0120smugg": 19176, "\u0120hunter": 19177, "azer": 19178, "\u0120Changes": 19179, "\u0120fluct": 19180, "yon": 19181, "Array": 19182, "\u0120kits": 19183, "Water": 19184, "\u0120uncommon": 19185, "\u0120resting": 19186, "ells": 19187, "would": 19188, "\u0120pursued": 19189, "\u0120assertion": 19190, "ometown": 19191, "\u0120Mosul": 19192, "\u0120Platform": 19193, "iolet": 19194, "\u0120shareholders": 19195, "\u0120trails": 19196, "Pay": 19197, "\u0120Enforcement": 19198, "types": 19199, "\u0120Anonymous": 19200, "\u0120satisfying": 19201, "ilogy": 19202, "\u0120('": 19203, "wave": 19204, "city": 19205, "Steve": 19206, "\u0120confrontation": 19207, "\u0120Eld": 19208, "Capt": 19209, "ahan": 19210, "htm": 19211, "\u0120Ctrl": 19212, "ONS": 19213, "230": 19214, "ifa": 19215, "holding": 19216, "\u0120delicate": 19217, "\u0120jaw": 19218, "\u0120Going": 19219, "orum": 19220, "Sal": 19221, "\u0120dull": 19222, "\u0120Beth": 19223, "\u0120prisons": 19224, "\u0120ego": 19225, "\u0120Elsa": 19226, "avorite": 19227, "\u0120Gang": 19228, "\u0120Nuclear": 19229, "\u0120spider": 19230, "atsu": 19231, "\u0120sampling": 19232, "\u0120absorbed": 19233, "\u0120Pharm": 19234, "ieth": 19235, "\u0120bucket": 19236, "\u0120Recomm": 19237, "OF": 19238, "\u0120Factory": 19239, "ANCE": 19240, "\u0120bacter": 19241, "Has": 19242, "\u0120Observ": 19243, "121": 19244, "\u0120premiere": 19245, "Develop": 19246, "\u0120currencies": 19247, "Cast": 19248, "\u0120accompanying": 19249, "\u0120Nashville": 19250, "\u0120fatty": 19251, "\u0120Brend": 19252, "\u0120locks": 19253, "\u0120centered": 19254, "\u0120UT": 19255, "aughs": 19256, "orie": 19257, "\u0120Affordable": 19258, "vance": 19259, "DL": 19260, "emet": 19261, "\u0120throne": 19262, "\u0120Bluetooth": 19263, "\u0120naming": 19264, "ifts": 19265, "ADE": 19266, "\u0120corrected": 19267, "\u0120promptly": 19268, "\u0120STR": 19269, "\u0120genome": 19270, "\u0120cope": 19271, "\u0120valley": 19272, "\u0120rounded": 19273, "\u0120Kend": 19274, "alion": 19275, "pers": 19276, "\u0120tourism": 19277, "\u0120stark": 19278, "vl": 19279, "\u0120blowing": 19280, "\u0120Schedule": 19281, "std": 19282, "\u0120unhappy": 19283, "\u0120litigation": 19284, "cedes": 19285, "\u0120android": 19286, "\u0120integral": 19287, "erers": 19288, "uded": 19289, "tax": 19290, "\u0120reiter": 19291, "\u0120Motors": 19292, "ociated": 19293, "\u0120wonders": 19294, "\u0120Apost": 19295, "ucking": 19296, "\u0120Roosevelt": 19297, "fram": 19298, "\u0120yields": 19299, "\u0120constitutes": 19300, "awk": 19301, "Interest": 19302, "\u0120interim": 19303, "\u0120breakthrough": 19304, "\u0120Cher": 19305, "\u0120prosec": 19306, "\u0120Dj": 19307, "\u0120MT": 19308, "Resp": 19309, "\u0120PT": 19310, "\u0120sperm": 19311, "edit": 19312, "BT": 19313, "Linux": 19314, "country": 19315, "league": 19316, "\u0120dick": 19317, "\u0120oct": 19318, "\u0120inserting": 19319, "\u0120scra": 19320, "\u0120Brewing": 19321, "\u01201966": 19322, "\u0120runners": 19323, "\u0120plun": 19324, "idy": 19325, "\u0120Dian": 19326, "\u0120dysfunction": 19327, "\u0120exclusion": 19328, "\u0120disgr": 19329, "\u0120incorporate": 19330, "\u0120reconc": 19331, "\u0120nominated": 19332, "\u0120Archer": 19333, "draw": 19334, "achelor": 19335, "\u0120writings": 19336, "\u0120shallow": 19337, "\u0120hast": 19338, "\u0120BMW": 19339, "\u0120RS": 19340, "\u0120thigh": 19341, "\u01201963": 19342, "\u0120lamb": 19343, "\u0120favored": 19344, "agle": 19345, "\u0120cooler": 19346, "\u0120Hours": 19347, "\u0120GU": 19348, "\u0120Origin": 19349, "\u0120glimpse": 19350, "--------------------": 19351, "Lim": 19352, "\u0120cheek": 19353, "\u0120jealous": 19354, "-'": 19355, "\u0120harness": 19356, "\u0120Poison": 19357, "\u0120disabilities": 19358, "neapolis": 19359, "\u0120outlook": 19360, "\u0120notify": 19361, "\u0120Indianapolis": 19362, "\u0120abrupt": 19363, "nsic": 19364, "\u0120encrypted": 19365, "\u0120forfe": 19366, "reath": 19367, "\u0120rabb": 19368, "\u0120foundations": 19369, "\u0120compliment": 19370, "\u0120Interview": 19371, "\u0120Swe": 19372, "\u0120adolesc": 19373, "\u0120monitors": 19374, "\u0120Sacramento": 19375, "\u0120timely": 19376, "\u0120contempl": 19377, "\u0120positioned": 19378, "\u0120posters": 19379, "phies": 19380, "iovascular": 19381, "void": 19382, "\u0120Fifth": 19383, "\u0120investigative": 19384, "OUN": 19385, "\u0120integrate": 19386, "\u0120INC": 19387, "isha": 19388, "iblings": 19389, "\u0120Request": 19390, "\u0120Rodriguez": 19391, "\u0120slides": 19392, "\u0120DX": 19393, "\u0120feminism": 19394, "\u0120datas": 19395, "\u0120bend": 19396, "irus": 19397, "\u0120Nigeria": 19398, "Fox": 19399, "Change": 19400, "\u0120airplane": 19401, "\u0120Laden": 19402, "\u0120publicity": 19403, "ixty": 19404, "\u0120commitments": 19405, "\u0120aggregate": 19406, "\u0120displaying": 19407, "\u0120Arrow": 19408, "\u0120122": 19409, "\u0120respects": 19410, "android": 19411, "six": 19412, "\u0120Sha": 19413, "\u0120restoration": 19414, ")\\": 19415, "WS": 19416, "oys": 19417, "\u0120illustrate": 19418, "without": 19419, "126": 19420, "\u0120\u00e2\u0136\u0124": 19421, "\u0120pickup": 19422, "nels": 19423, "\u0120....": 19424, "food": 19425, "\u0120Fen": 19426, ")?": 19427, "\u0120phenomena": 19428, "\u0120companions": 19429, "\u0120Write": 19430, "\u0120spill": 19431, "\u0120bridges": 19432, "\u0120Updated": 19433, "\u0120Fo": 19434, "\u0120insects": 19435, "ASHINGTON": 19436, "\u0120scare": 19437, "iltr": 19438, "\u0120Zhang": 19439, "\u0120severity": 19440, "\u0120indul": 19441, "149": 19442, "\u0120Coffee": 19443, "\u0120norms": 19444, "\u0120pulse": 19445, "\u0120FT": 19446, "\u0120horrific": 19447, "\u0120Destroy": 19448, "\u0120JSON": 19449, "\u0120olive": 19450, "\u0120discusses": 19451, "Rest": 19452, "Elect": 19453, "\u0120Winn": 19454, "\u0120Surviv": 19455, "\u0120Hait": 19456, "Sure": 19457, "oped": 19458, "\u0120rooted": 19459, "\u0120Ske": 19460, "\u0120Bronze": 19461, "\u0120lol": 19462, "Default": 19463, "\u0120commodity": 19464, "redited": 19465, "\u0120libertarian": 19466, "\u0120forbidden": 19467, "\u0120gran": 19468, "\u00e0\u00a8": 19469, "\u0120lag": 19470, "enz": 19471, "drive": 19472, "\u0120mathematics": 19473, "\u0120wires": 19474, "\u0120critically": 19475, "\u0120carbohyd": 19476, "\u0120Chancellor": 19477, "\u0120Eddie": 19478, "\u0120banning": 19479, "\u0120Fri": 19480, "\u0120complications": 19481, "etric": 19482, "\u0120Bangladesh": 19483, "\u0120bandwidth": 19484, "Stop": 19485, "\u0120Originally": 19486, "\u0120halfway": 19487, "ynasty": 19488, "shine": 19489, "\u0120tales": 19490, "rities": 19491, "avier": 19492, "\u0120spinning": 19493, "\u0120WHO": 19494, "\u0120neighbourhood": 19495, "bach": 19496, "\u0120commerce": 19497, "\u0120Sle": 19498, "BU": 19499, "\u0120entrepreneur": 19500, "\u0120peculiar": 19501, "\u0120Comments": 19502, "fre": 19503, "320": 19504, "ICS": 19505, "\u0120imagery": 19506, "\u0120Canon": 19507, "\u0120Electronic": 19508, "short": 19509, "((": 19510, "Dig": 19511, "\u0120commem": 19512, "uced": 19513, "\u0120inclined": 19514, "\u0120Summon": 19515, "\u0120cliff": 19516, "\u0120Mediterranean": 19517, "\u0120poetry": 19518, "\u0120prosperity": 19519, "\u0120Rece": 19520, "\u0120pills": 19521, "member": 19522, "\u0120finale": 19523, "unc": 19524, "\u0120Gig": 19525, "\u00e4\u00bd": 19526, "\u0120lod": 19527, "\u0120backward": 19528, "-+": 19529, "\u0120Forward": 19530, "\u0120thri": 19531, "sure": 19532, "\u0120soap": 19533, "\u0120FX": 19534, "RES": 19535, "\u0120Sexual": 19536, "oulos": 19537, "\u0120foolish": 19538, "\u0120righteous": 19539, "\u0120coff": 19540, "terrorism": 19541, "ustain": 19542, "oter": 19543, "\u0120abuses": 19544, "next": 19545, "\u0120abusive": 19546, "\u0120thereafter": 19547, "\u0120prohibition": 19548, "\u0120SUP": 19549, "\u0120dip": 19550, "\u0120ripped": 19551, "\u0120inherited": 19552, "\u0120bats": 19553, "stru": 19554, "GT": 19555, "\u0120flawed": 19556, "phabet": 19557, "\u0120fog": 19558, "doors": 19559, "\u0120imaging": 19560, "\u0120digits": 19561, "\u0120Hungary": 19562, "\u0120arrog": 19563, "\u0120teachings": 19564, "\u0120protocols": 19565, "\u0120Banks": 19566, "\u00e0\u00b8": 19567, "pound": 19568, "\u0120Curt": 19569, ".\")": 19570, "./": 19571, "\u0120exemption": 19572, "endix": 19573, "\u0120Mull": 19574, "\u0120improves": 19575, "\u0120Gamer": 19576, "dimensional": 19577, "Icon": 19578, "\u0120Margaret": 19579, "Status": 19580, "dates": 19581, "\u0120intends": 19582, "\u0120depict": 19583, "\u0120parked": 19584, "Joe": 19585, "\u0120Marines": 19586, "chnology": 19587, "!).": 19588, "\u0120judged": 19589, "\u0120weights": 19590, "Ray": 19591, "\u0120apartments": 19592, "hester": 19593, "\u0120reinforce": 19594, "\u0120offender": 19595, "occup": 19596, "\u0120sore": 19597, "ept": 19598, "\u0120PHP": 19599, "\u0120Brow": 19600, "\u0120authorization": 19601, "\u0120Risk": 19602, "\u0120Delaware": 19603, "\u0120QU": 19604, "\u0120notifications": 19605, "\u0120sunlight": 19606, "\u0120exclude": 19607, "dat": 19608, "\u0120mesh": 19609, "\u0120Sudan": 19610, "\u0120belonged": 19611, "\u0120subway": 19612, "\u0120noon": 19613, "\u0120Interior": 19614, "olics": 19615, "\u0120Lakers": 19616, "\u0120coding": 19617, "Disclaimer": 19618, "Calif": 19619, "Old": 19620, "\u0120disl": 19621, "?????": 19622, "\u0120confirms": 19623, "\u0120recruitment": 19624, "\u0120homicide": 19625, "Consider": 19626, "\u0120Jeffrey": 19627, "fty": 19628, "};": 19629, "\u0120objection": 19630, "doing": 19631, "\u0120Leo": 19632, "Want": 19633, "\u0120glow": 19634, "\u0120Clarke": 19635, "\u0120Norman": 19636, "\u0120verification": 19637, "\u0120packet": 19638, "\u0120Formula": 19639, "\u0120plag": 19640, "esville": 19641, "\u0120shouting": 19642, "\u0120ov": 19643, "\u0120REC": 19644, "\u0120Bub": 19645, "\u0120ninth": 19646, "\u0120energ": 19647, "\u0120validity": 19648, "\u0120ups": 19649, "jack": 19650, "\u0120neighboring": 19651, "\u0120Nec": 19652, "eworks": 19653, "\u0120Hab": 19654, "arez": 19655, "\u0120spine": 19656, "\u0120eventual": 19657, "\u0120Leaders": 19658, "\u0120Carn": 19659, "\u0120probation": 19660, "\u0120romance": 19661, "msg": 19662, "\u0120Mechanical": 19663, "ERY": 19664, "Rock": 19665, "\u0120partisan": 19666, "Node": 19667, "assets": 19668, "minent": 19669, "\u0120foreigners": 19670, "\u0120testify": 19671, "\u0120Usually": 19672, "lords": 19673, "\u0120Gren": 19674, "\u0120Powell": 19675, "BIL": 19676, "\u0120sr": 19677, "\u0120addict": 19678, "\u0120shells": 19679, "\u0120sigh": 19680, "\u0120Yale": 19681, "ternity": 19682, "\u0120750": 19683, "EU": 19684, "\u0120Rifle": 19685, "\u0120patron": 19686, "ema": 19687, "\u0120Bannon": 19688, "anity": 19689, "\u0120tropical": 19690, "\u0120VII": 19691, "cross": 19692, "Everything": 19693, "\u0120ISO": 19694, "\u0120humble": 19695, "assing": 19696, "\u0120FIG": 19697, "\u0120updating": 19698, "yson": 19699, "\u0120calcium": 19700, "\u0120competent": 19701, "\u0120steering": 19702, "Prot": 19703, "\u0120SY": 19704, "\u0120Finals": 19705, "\u0120Rug": 19706, "159": 19707, "137": 19708, "\u0120Golf": 19709, "\u0120126": 19710, "\u0120accommodation": 19711, "\u0120Hughes": 19712, "\u0120aesthetic": 19713, "artisan": 19714, "\u0120Twilight": 19715, "\u0120prince": 19716, "\u0120Agriculture": 19717, "\u0120Disco": 19718, "\u0120precedent": 19719, "\u0120typing": 19720, "authorized": 19721, "Option": 19722, "\u0120Aub": 19723, "lishes": 19724, "acht": 19725, "mag": 19726, "Peter": 19727, "\u0120UFO": 19728, "monton": 19729, "\u0120Lith": 19730, "\u0120arom": 19731, "\u0120securing": 19732, "\u0120confined": 19733, "private": 19734, "\u0120swords": 19735, "\u0120markers": 19736, "\u0120metabolic": 19737, "select": 19738, "\u0120Curse": 19739, "\u0120Ot": 19740, "gressive": 19741, "\u0120incumb": 19742, "\u0120Saga": 19743, "\u0120priced": 19744, "\u0120clearance": 19745, "Content": 19746, "\u0120drilling": 19747, "\u0120notices": 19748, "\u0120bourgeois": 19749, "\u0120vest": 19750, "\u0120cookie": 19751, "\u0120Guardians": 19752, "rys": 19753, "inyl": 19754, "\u0120124": 19755, "\u0120plausible": 19756, "ongh": 19757, "\u0120Odin": 19758, "\u0120conception": 19759, "\u0120Yuk": 19760, "\u0120Baghdad": 19761, "\u0120Flag": 19762, "Austral": 19763, "\u0120IBM": 19764, "\u0120internationally": 19765, "\u0120WikiLeaks": 19766, "IED": 19767, "\u0120cyn": 19768, "\u0120chooses": 19769, "\u0120Pill": 19770, "\u0120combining": 19771, "\u0120radi": 19772, "\u0120Mohammed": 19773, "defense": 19774, "atching": 19775, "Subject": 19776, "iciency": 19777, "Frame": 19778, "\u0120{\"": 19779, "\u0120chess": 19780, "\u0120timer": 19781, "190": 19782, "\u0120tin": 19783, "\u0120ordinance": 19784, "emetery": 19785, "\u0120accusing": 19786, "\u0120noticeable": 19787, "\u0120centres": 19788, "\u0120lid": 19789, "\u0120Mills": 19790, "imgur": 19791, "\u0120zoom": 19792, "ergic": 19793, "\u0120compression": 19794, "prim": 19795, "find": 19796, "\u0120surg": 19797, "\u0120pand": 19798, "\u0120Kee": 19799, "\u0120Chad": 19800, "cellence": 19801, "oyle": 19802, "\u0120socialism": 19803, "\u0120Travis": 19804, "\u0120MHz": 19805, "\u0120guild": 19806, "ALLY": 19807, "\u0120Subscribe": 19808, "\u0120Related": 19809, "\u0120occurrence": 19810, "itching": 19811, "\u0120fictional": 19812, "\u0120crush": 19813, "\u0120EA": 19814, "cod": 19815, "mix": 19816, "\u0120Triple": 19817, "\u0120retrieve": 19818, "\u0120stimulus": 19819, "\u0120psychiat": 19820, "\u0120Door": 19821, "\u0120homosexuality": 19822, "\u0120elementary": 19823, "\u0120cellular": 19824, "idian": 19825, "\u0120Laun": 19826, "\u0120intriguing": 19827, "\u0120foam": 19828, "\u0120Bass": 19829, "idi": 19830, "itsu": 19831, "\u0120assure": 19832, "\u0120congrat": 19833, "\u0120businessman": 19834, "\u0120Boost": 19835, "close": 19836, "\u0120lied": 19837, "\u0120sciences": 19838, "\u0120Omega": 19839, "\u0120Graphics": 19840, "\u0120<=": 19841, "spoken": 19842, "\u0120connectivity": 19843, "Saturday": 19844, "\u0120Avengers": 19845, "\u0120toggle": 19846, "\u0120ankle": 19847, "\u0120nationalist": 19848, "model": 19849, "\u0120Pool": 19850, "ophobia": 19851, "Var": 19852, "\u0120Mons": 19853, "atories": 19854, "\u0120aggressively": 19855, "Clear": 19856, "Forge": 19857, "acters": 19858, "\u0120hedge": 19859, "\u0120pipes": 19860, "\u0120blunt": 19861, "\u0120sq": 19862, "\u0120remotely": 19863, "Wed": 19864, "asers": 19865, "\u0120refriger": 19866, "\u0120tiles": 19867, "\u0120rescued": 19868, "\u0120comprised": 19869, "insky": 19870, "\u0120manif": 19871, "avanaugh": 19872, "\u0120prolifer": 19873, "\u0120aligned": 19874, "xml": 19875, "\u0120triv": 19876, "\u0120coordination": 19877, "\u0120PER": 19878, "\u0120Quote": 19879, "134": 19880, "bf": 19881, "\u0120Saw": 19882, "\u0120termination": 19883, "\u0120190": 19884, "\u0120additions": 19885, "\u0120trio": 19886, "\u0120projections": 19887, "\u0120positively": 19888, "\u0120inclusive": 19889, "\u0120membr": 19890, "1990": 19891, "older": 19892, "\u0120practiced": 19893, "inkle": 19894, "Arch": 19895, "\u0120starters": 19896, "arius": 19897, "\u0120intermediate": 19898, "\u0120Benef": 19899, "\u0120Killer": 19900, "\u0120interventions": 19901, "\u0120Kil": 19902, "\u0120Flying": 19903, "Inv": 19904, "\u0120premature": 19905, "\u0120psychiatric": 19906, "\u0120indie": 19907, "\u0120collar": 19908, "\u0120Rainbow": 19909, "afi": 19910, "\u0120disruption": 19911, "\u0120FOX": 19912, "casting": 19913, "\u0120misdem": 19914, "cro": 19915, "\u0120wipe": 19916, "ardon": 19917, "\u0120bast": 19918, "\u0120Tommy": 19919, "\u0120Representative": 19920, "\u0120belly": 19921, "\u0120PO": 19922, "\u0120Breitbart": 19923, "132": 19924, "\u0120messaging": 19925, "Should": 19926, "References": 19927, "\u0120GRE": 19928, "istical": 19929, "LP": 19930, "\u0120Cav": 19931, "\u0120Crazy": 19932, "\u0120intuitive": 19933, "keeping": 19934, "\u0120Moss": 19935, "\u0120discontin": 19936, "\u0120Module": 19937, "\u0120unrelated": 19938, "\u0120Practice": 19939, "\u0120Transport": 19940, "\u0120statistically": 19941, "orns": 19942, "\u0120sized": 19943, "pu": 19944, "\u0120caf": 19945, "\u0120Worlds": 19946, "\u0120Rodgers": 19947, "\u0120Lun": 19948, "\u0120Comic": 19949, "living": 19950, "\u0120cared": 19951, "\u0120climbed": 19952, "){": 19953, "\u0120consisted": 19954, "\u0120medieval": 19955, "folk": 19956, "\u0120hacked": 19957, "\u0120dire": 19958, "\u0120Hermione": 19959, "\u0120tended": 19960, "ceans": 19961, "Daniel": 19962, "went": 19963, "\u0120legislators": 19964, "\u0120redes": 19965, "games": 19966, "\u0120gn": 19967, "amiliar": 19968, "\u0120++": 19969, "ggy": 19970, "threat": 19971, "\u0120magnet": 19972, "\u0120perceive": 19973, "\u0120zip": 19974, "\u0120indictment": 19975, "\u0120critique": 19976, "gard": 19977, "\u0120Safe": 19978, "\u0120Cream": 19979, "\u0120advent": 19980, "oba": 19981, "\u0120vowed": 19982, "ousands": 19983, "\u0120ski": 19984, "\u0120abortions": 19985, "uart": 19986, "\u0120stunned": 19987, "\u0120advancing": 19988, "\u0120lacked": 19989, "\u0120\\\"": 19990, "\u0120schizophren": 19991, "\u0120elegant": 19992, "\u0120conferences": 19993, "\u0120canceled": 19994, "\u0120Hudson": 19995, "\u0120Hopefully": 19996, "\u0120trump": 19997, "\u0120frequencies": 19998, "\u0120meteor": 19999, "\u0120Junior": 20000, "\u0120Fleet": 20001, "\u0120Malcolm": 20002, "\u0120Tools": 20003, "\u0120........": 20004, "\u0120hobby": 20005, "\u0120Europeans": 20006, "\u01201500": 20007, "\u0120Into": 20008, "\u0120sway": 20009, "\u0120Appro": 20010, "\u0120Compl": 20011, "Community": 20012, "\u0120tide": 20013, "\u0120Summit": 20014, "\u00e4\u00bb": 20015, "\u0120intervals": 20016, "\u0120Ether": 20017, "\u0120habitat": 20018, "\u0120Stevens": 20019, "lishing": 20020, "\u0120Domain": 20021, "\u0120triggers": 20022, "\u0120chasing": 20023, "\u0120charm": 20024, "\u0120Flower": 20025, "itored": 20026, "\u0120blessing": 20027, "\u0120textures": 20028, "Five": 20029, "\u0120liquor": 20030, "RP": 20031, "FIN": 20032, "\u01201962": 20033, "CAR": 20034, "Unknown": 20035, "\u0120resil": 20036, "\u0120Lily": 20037, "\u0120abundance": 20038, "\u0120predictable": 20039, "rar": 20040, "\u0120bullshit": 20041, "leen": 20042, "chet": 20043, "Mor": 20044, "Much": 20045, "\u00e4\u00b9": 20046, "\u0120emphasized": 20047, "\u0120crust": 20048, "\u0120primitive": 20049, "\u0120enjoyable": 20050, "\u0120Pictures": 20051, "\u0120teammate": 20052, "pler": 20053, "\u0120Tol": 20054, "\u0120Kane": 20055, "\u0120summoned": 20056, "thy": 20057, "rama": 20058, "\u0120Honda": 20059, "\u0120realizing": 20060, "\u0120quicker": 20061, "\u0120concentrate": 20062, "clear": 20063, "\u0120210": 20064, "\u0120Erdogan": 20065, "aris": 20066, "\u0120responds": 20067, "\u0120BI": 20068, "\u0120eligibility": 20069, "\u0120pushes": 20070, "\u0120Idaho": 20071, "\u0120aggrav": 20072, "\u0120ruins": 20073, "urations": 20074, "\u0120bans": 20075, "\u0120anat": 20076, "share": 20077, "\u0120grind": 20078, "hin": 20079, "umen": 20080, "\u0120utilities": 20081, "\u0120Yankees": 20082, "\u0120databases": 20083, "\u0120DD": 20084, "\u0120displaced": 20085, "\u0120dependencies": 20086, "\u0120stimulation": 20087, "hun": 20088, "houses": 20089, "\u0120Pretty": 20090, "\u0120Ravens": 20091, "\u0120TODAY": 20092, "\u0120associates": 20093, "\u0120therape": 20094, "cled": 20095, "\u0120deer": 20096, "\u0120repairs": 20097, "rentice": 20098, "\u0120receptors": 20099, "\u0120remed": 20100, "\u0120Ce": 20101, "\u0120marriages": 20102, "\u0120ballots": 20103, "\u0120Soldier": 20104, "\u0120hilarious": 20105, "opl": 20106, "138": 20107, "\u0120inherently": 20108, "\u0120ignorant": 20109, "\u0120bounce": 20110, "\u0120Easter": 20111, "RELATED": 20112, "\u0120Currency": 20113, "EV": 20114, "\u00e3\u0125\u0140": 20115, "\u0120Lead": 20116, "\u0120deceased": 20117, "Brien": 20118, "\u0120Musk": 20119, "JS": 20120, "\u0120merge": 20121, "hearted": 20122, "creat": 20123, "mitt": 20124, "mund": 20125, "\u0120\u00e2\u0122\u012d": 20126, "\u0120Bag": 20127, "\u0120projection": 20128, "\u0120java": 20129, "\u0120Standards": 20130, "\u0120Leonard": 20131, "\u0120coconut": 20132, "\u0120Population": 20133, "\u0120traject": 20134, "\u0120imply": 20135, "\u0120curiosity": 20136, "\u0120DB": 20137, "\u0120Fresh": 20138, "\u0120Por": 20139, "\u0120heavier": 20140, "neys": 20141, "gomery": 20142, "\u0120deserved": 20143, "\u0120phrases": 20144, "\u0120GC": 20145, "\u0120yeast": 20146, "desc": 20147, "Death": 20148, "\u0120reboot": 20149, "\u0120metadata": 20150, "ICAL": 20151, "\u0120repay": 20152, "\u0120Independence": 20153, "\u0120suburban": 20154, "icals": 20155, "\u0120atop": 20156, "\u0120allocation": 20157, "generation": 20158, "\u0120Gram": 20159, "\u0120moisture": 20160, "\u0120pine": 20161, "\u0120Liberals": 20162, "\u0120aides": 20163, "\u0120underest": 20164, "\u0120Berry": 20165, "\u0120ceremon": 20166, "370": 20167, "astrous": 20168, "\u0120Pirates": 20169, "\u0120tense": 20170, "\u0120Industries": 20171, "\u0120Appeals": 20172, "\u0120Near": 20173, "\u0120\u00e8\u00a3\u0131\u00e7": 20174, "\u0120lovers": 20175, "\u0120CAP": 20176, "\u0120Craw": 20177, "\u0120giants": 20178, "\u0120efficacy": 20179, "Element": 20180, "\u0120Behavior": 20181, "\u0120Toyota": 20182, "\u0120intest": 20183, "Priv": 20184, "AI": 20185, "\u0120maneuver": 20186, "\u0120perfection": 20187, "\u0120bang": 20188, "paper": 20189, "rill": 20190, "George": 20191, "border": 20192, "inters": 20193, "\u0120Seth": 20194, "\u0120clues": 20195, "\u0120Levi": 20196, "\u0120Revenue": 20197, "147": 20198, "\u0120vapor": 20199, "\u0120fortunate": 20200, "\u0120threatens": 20201, "\u0120vet": 20202, "\u0120dependency": 20203, "ersed": 20204, "article": 20205, "\u0120Blizzard": 20206, "\u0120chlor": 20207, "\u0120minus": 20208, "\u0120Bills": 20209, "\u0120cryptocurrency": 20210, "\u0120metabolism": 20211, "tering": 20212, "\u0120pestic": 20213, "steps": 20214, "\u0120Treasure": 20215, "racted": 20216, "\u0120Constant": 20217, "\u0120temp": 20218, "139": 20219, "\u0120Detective": 20220, "urally": 20221, "\u0120recovering": 20222, "\u0120cortex": 20223, "\u0120144": 20224, "closed": 20225, "\u0120prejudice": 20226, "aunted": 20227, "\u0120storms": 20228, "\u0120NOW": 20229, "\u0120machinery": 20230, "Address": 20231, "\u0120compelled": 20232, "270": 20233, "\u0120despair": 20234, "bane": 20235, "\u0120vegetable": 20236, "\u0120beds": 20237, "Learn": 20238, "\u0120colorful": 20239, "\u0120spike": 20240, "\u0120margins": 20241, "\u0120sympathy": 20242, "\u0120workshop": 20243, "\u0120CBC": 20244, "Sat": 20245, "\u0120burns": 20246, "\u0120Gender": 20247, "\u0120129": 20248, "\u0120Cable": 20249, "\u0120debts": 20250, "\u0120Theresa": 20251, "\u0120reflecting": 20252, "\u0120airst": 20253, "\u0120rim": 20254, "ramid": 20255, "\u0120weaknesses": 20256, "Writ": 20257, "oggle": 20258, "ti": 20259, "\u0120Charge": 20260, "\u0120weighed": 20261, "\u0120(.": 20262, "\u0120laughter": 20263, "\u0120router": 20264, "\u0120Democracy": 20265, "Dear": 20266, "\u0120hasht": 20267, "\u0120dy": 20268, "\u0120hints": 20269, "running": 20270, "\u0120finishes": 20271, "arus": 20272, "Mass": 20273, "result": 20274, "ascus": 20275, "\u0120vintage": 20276, "\u0120conqu": 20277, "\u0120wildly": 20278, "acist": 20279, "\u0120lingu": 20280, "\u0120protagonist": 20281, "strom": 20282, "teenth": 20283, "\u0120Solo": 20284, "mac": 20285, "filled": 20286, "\u0120renown": 20287, "itives": 20288, "\u0120motive": 20289, "\u0120Antar": 20290, "\u0120Mann": 20291, "\u0120Adjust": 20292, "\u0120rockets": 20293, "\u0120troubling": 20294, "ei": 20295, "\u0120organisms": 20296, "assis": 20297, "Christian": 20298, "\u0120145": 20299, "\u0120Hass": 20300, "\u0120swall": 20301, "\u0120wax": 20302, "\u0120Survival": 20303, "VS": 20304, "\u0120Murd": 20305, "vd": 20306, "standard": 20307, "\u0120dragons": 20308, "\u0120acceleration": 20309, "rational": 20310, "final": 20311, "\u0120paired": 20312, "\u0120Ethereum": 20313, "\u0120interfaces": 20314, "\u0120resent": 20315, "\u0120artifacts": 20316, "\u00c5\u00ab": 20317, "arel": 20318, "\u0120competitor": 20319, "\u0120Nicholas": 20320, "\u0120Surface": 20321, "cpp": 20322, "\u0120Tot": 20323, "\u0120economically": 20324, "\u0120organised": 20325, "\u0120enforced": 20326, "inho": 20327, "\u0120varieties": 20328, "\u0120abdom": 20329, "\u0120Bailey": 20330, "idav": 20331, "\u0120Salv": 20332, "paid": 20333, "\u0120altitude": 20334, "essert": 20335, "\u0120Gutenberg": 20336, "area": 20337, "opoulos": 20338, "\u0120professors": 20339, "iggs": 20340, "\u0120Fate": 20341, "hey": 20342, "\u01203000": 20343, "Dist": 20344, "\u0120twins": 20345, "cill": 20346, "\u0120Maps": 20347, "\u0120traps": 20348, "\u0120weed": 20349, "\u0120Kiss": 20350, "\u0120yoga": 20351, "\u0120recipients": 20352, "\u0120Westminster": 20353, "\u0120pools": 20354, "\u0120Walmart": 20355, "188": 20356, "\u0120Schools": 20357, "attack": 20358, "\u0120ARM": 20359, "paragraph": 20360, "Warning": 20361, "jl": 20362, "\u0120selfish": 20363, "anchez": 20364, "\u0120Heights": 20365, "Fre": 20366, "\u0120Soph": 20367, "\u0120--------------------------------": 20368, "tml": 20369, "333": 20370, "\u0120raids": 20371, "\u0120satellites": 20372, "KEY": 20373, "\u0120lasts": 20374, "\u00d1\u0124": 20375, "Ins": 20376, "\u0120Dame": 20377, "\u0120unpredict": 20378, "///": 20379, "ghai": 20380, "\u0120artillery": 20381, "\u0120cruise": 20382, "\u0120gel": 20383, "\u0120Cabinet": 20384, "\u0120blows": 20385, "\u0120Esp": 20386, "\u0120proximity": 20387, "othe": 20388, "\u0120Skills": 20389, "\u0120Upper": 20390, "obo": 20391, "\u0120NDP": 20392, "\u0120enjoys": 20393, "\u0120repeating": 20394, "\u0120Construction": 20395, "\u0120Questions": 20396, "Hillary": 20397, "\u0120uint": 20398, "\u0120processors": 20399, "\u0120Gibson": 20400, "\u0120Multiple": 20401, "qa": 20402, "\u0120Bom": 20403, "\u0120Miles": 20404, "ventional": 20405, "\u0120hurts": 20406, "skin": 20407, "\u0120AIDS": 20408, "\u0120advisers": 20409, "\u0120Root": 20410, "\u0120methodology": 20411, "\u0120Dale": 20412, "\u0120deton": 20413, "\u0120Knowledge": 20414, "sequently": 20415, "\u0120121": 20416, "\u0120connects": 20417, "Cy": 20418, "\u0120Danger": 20419, "\u0120contributors": 20420, "\u0120Bent": 20421, "\u0120brass": 20422, "\u0120Guns": 20423, "into": 20424, "\u0120Fortune": 20425, "\u0120broker": 20426, "balance": 20427, "\u0120lengths": 20428, "\u0120vic": 20429, "\u0120averaging": 20430, "\u0120appropriately": 20431, "\u0120Camera": 20432, "\u0120sandwich": 20433, "\u0120CDC": 20434, "\u0120coordinate": 20435, "\u0120navig": 20436, "\u0120goodness": 20437, "laim": 20438, "\u0120brake": 20439, "\u0120extremist": 20440, "\u0120Wake": 20441, "\u0120Mend": 20442, "\u0120Tiny": 20443, "\u0120COL": 20444, "\u0120RF": 20445, "\u0120Dual": 20446, "\u0120Wine": 20447, "Case": 20448, "\u0120refined": 20449, "\u0120lamp": 20450, "Lead": 20451, "\u0120bapt": 20452, "\u0120Carb": 20453, "\u0120Sadd": 20454, "\u0120Minneapolis": 20455, "PDF": 20456, "Early": 20457, "\u0120Hidden": 20458, "Its": 20459, "\u0120TIME": 20460, "\u0120pap": 20461, "\u0120commissioned": 20462, "\u0120Few": 20463, "\u0120Colts": 20464, "\u0120Bren": 20465, "\u0120bothered": 20466, "\u0120likewise": 20467, "Exper": 20468, "\u0120Schw": 20469, "cry": 20470, "nn": 20471, "\u0120Mitch": 20472, "imon": 20473, "MG": 20474, "bm": 20475, "UMP": 20476, "rays": 20477, "\u0120registry": 20478, "\u0120270": 20479, "achine": 20480, "rella": 20481, "anting": 20482, "00000": 20483, "\u0120ruined": 20484, "spot": 20485, "\u0120ta": 20486, "\u0120maximize": 20487, "\u0120inconven": 20488, "Dead": 20489, "Human": 20490, "Enabled": 20491, "\u0120Marie": 20492, "\u0120chill": 20493, "\u0120Paradise": 20494, "\u0120starring": 20495, "\u0120Latino": 20496, "\u0120Protocol": 20497, "\u0120EVER": 20498, "\u0120suppliers": 20499, "message": 20500, "\u0120Brock": 20501, "\u0120serum": 20502, "\u00e2\u0138\u012a\u00e2\u0138\u012a\u00e2\u0138\u012a\u00e2\u0138\u012a": 20503, "\u0120encomp": 20504, "\u0120ambition": 20505, "uese": 20506, "\u0120arrows": 20507, "Andrew": 20508, "\u0120antenna": 20509, "\u01201961": 20510, "\u0120Bark": 20511, "\u0120bool": 20512, "\u00e3\u0124\u00aa": 20513, "\u0120Storage": 20514, "\u0120railway": 20515, "\u0120tougher": 20516, "\u0120Cad": 20517, "\u0120washing": 20518, "Py": 20519, "']": 20520, "embed": 20521, "\u0120Memphis": 20522, "ackle": 20523, "\u0120famously": 20524, "\u0120Fortunately": 20525, "ovies": 20526, "\u0120mindset": 20527, "\u0120sneak": 20528, "\u0120Dh": 20529, "RAW": 20530, "\u0120Simpson": 20531, "\u0120livest": 20532, "\u0120landmark": 20533, "\u0120cement": 20534, "Low": 20535, "\u0120thrilled": 20536, "\u0120Course": 20537, "inel": 20538, "\u0120chuck": 20539, "idate": 20540, "global": 20541, "\u0120whit": 20542, "\u0120\u00ef\u00bf\u00bd": 20543, "adays": 20544, "ski": 20545, "\u0120SV": 20546, "\u0120viruses": 20547, "306": 20548, "\u0120Respons": 20549, "\u0120theaters": 20550, "\u0120Branch": 20551, "\u0120Geneva": 20552, "\u0120MK": 20553, "\u0120unbeliev": 20554, "\u0120communist": 20555, "Original": 20556, "\u0120Received": 20557, "\u0120Transfer": 20558, "\u0120Arg": 20559, "Input": 20560, "\u0120Strategy": 20561, "\u0120palace": 20562, "thening": 20563, "Dri": 20564, "\u0120sentencing": 20565, "umbnail": 20566, "\u0120pins": 20567, "recy": 20568, "\u0120siblings": 20569, "Getting": 20570, "\u0120BU": 20571, "\u0120Northwest": 20572, "\u0120prolonged": 20573, "\u0120Sakura": 20574, "Comb": 20575, "\u0120Bour": 20576, "\u0120inadequate": 20577, "\u0120Kash": 20578, "\u0120username": 20579, "\u0120Improve": 20580, "\u0120battling": 20581, "\u0120MAC": 20582, "\u0120curriculum": 20583, "\u0120soda": 20584, "\u0120Cannon": 20585, "\u0120sensible": 20586, "spons": 20587, "December": 20588, "\u0120wicked": 20589, "\u0120Pengu": 20590, "\u0120dictators": 20591, "\u0120Hearts": 20592, "ogyn": 20593, "\u0120similarities": 20594, "\u0120Stats": 20595, "\u0120hollow": 20596, "itations": 20597, "\":[": 20598, "\u0120hover": 20599, "\u0120Listen": 20600, "sch": 20601, "Sund": 20602, "\u0120cad": 20603, "\u0120Parks": 20604, "\u0120lur": 20605, "\u0120hype": 20606, "\u0120Lem": 20607, "NAME": 20608, "isure": 20609, "Friday": 20610, "\u0120shoots": 20611, "\u0120closes": 20612, "\u0120db": 20613, "\u0120Ridge": 20614, "\u0120Different": 20615, "\u0120replies": 20616, "\u0120Broadway": 20617, "opers": 20618, "\u0120intoler": 20619, "\u0120Zeus": 20620, "akespe": 20621, "\u0120proprietary": 20622, "\u0120requesting": 20623, "\u0120controllers": 20624, "\u0120MIN": 20625, "imedia": 20626, "becca": 20627, "\u0120expans": 20628, "\u0120oils": 20629, "Bot": 20630, "\u0120Chand": 20631, "\u0120printer": 20632, "\u0120topped": 20633, "\u0120POL": 20634, "\u0120Earlier": 20635, "Social": 20636, "avin": 20637, "\u0120decreases": 20638, "\u0120Seb": 20639, "\u0120specifications": 20640, "\u0120Blast": 20641, "\u0120Kurt": 20642, "\u0120freel": 20643, "Brown": 20644, "\u0120dilig": 20645, "roe": 20646, "\u0120Problem": 20647, "\u0120Quad": 20648, "\u0120decentral": 20649, "\u0120Vector": 20650, "anut": 20651, "\u0120plugins": 20652, "\u0120Gregory": 20653, "\u0120fucked": 20654, "elines": 20655, "\u0120Ambassador": 20656, "take": 20657, "\u0120cleans": 20658, "ongyang": 20659, "Anonymous": 20660, "stro": 20661, "\"}": 20662, "aline": 20663, "\u0120Odd": 20664, "\u0120Eug": 20665, "216": 20666, "\u0120boil": 20667, "\u0120Powers": 20668, "\u0120nurses": 20669, "Obviously": 20670, "\u0120Technical": 20671, "\u0120exceeded": 20672, "ORS": 20673, "\u0120extremists": 20674, "\u0120traces": 20675, "expl": 20676, "\u0120comr": 20677, "\u0120Sach": 20678, ")/": 20679, "\u0120masks": 20680, "\u0120sci": 20681, "Bon": 20682, "\u0120regression": 20683, "wegian": 20684, "\u0120advisor": 20685, "itures": 20686, "\u0120Vo": 20687, "example": 20688, "\u0120Instruct": 20689, "\u0120siege": 20690, "\u0120reductions": 20691, "ptr": 20692, "\u0120statutory": 20693, "\u0120removes": 20694, "\u0120puck": 20695, "redits": 20696, "\u0120bee": 20697, "\u0120salad": 20698, "\u0120promotions": 20699, "\u0120Joshua": 20700, "withstanding": 20701, "ETH": 20702, "\u0120Cha": 20703, "imus": 20704, "\u0120expenditure": 20705, "aunting": 20706, "\u0120delighted": 20707, "\u0120155": 20708, "beh": 20709, "\u0120carpet": 20710, "\u0120Spart": 20711, "\u0120jungle": 20712, "lists": 20713, "\u0120bullying": 20714, "\u0120Nobel": 20715, "\u0120Glen": 20716, "\u0120referenced": 20717, "\u0120introduces": 20718, "sein": 20719, "\u0120chopped": 20720, "glass": 20721, "\u0120Wrest": 20722, "\u0120neutrality": 20723, "\u0120\u00e2\u013b": 20724, "\u0120investigator": 20725, "\u0120shelves": 20726, "\u0120unconstitutional": 20727, "\u0120reproduction": 20728, "\u0120merchant": 20729, "mia": 20730, "\u0120metrics": 20731, "\u0120explosives": 20732, "\u0120Sonia": 20733, "\u0120bodily": 20734, "\u0120thickness": 20735, "\u0120predominantly": 20736, "\u0120Ability": 20737, "\u0120monitored": 20738, "ICH": 20739, "\u0120].": 20740, "\u0120Martinez": 20741, "\u0120visibility": 20742, "\u0120queries": 20743, "\u0120genocide": 20744, "\u0120Warfare": 20745, "Query": 20746, "\u0120studios": 20747, "\u0120embry": 20748, "\u0120corridor": 20749, "\u0120cleaned": 20750, "complete": 20751, "\u0120MH": 20752, "\u0120enrollment": 20753, "INGS": 20754, "\u0120impacted": 20755, "\u0120disastrous": 20756, "\u0120Yun": 20757, "\u0120Claire": 20758, "\u0120Basically": 20759, "yt": 20760, "usterity": 20761, "\u0120indirectly": 20762, "wik": 20763, "\u0120dod": 20764, "\u0120Carr": 20765, "\u0120amp": 20766, "\u0120prohibit": 20767, "\u0120Initial": 20768, "\u0120Rd": 20769, "iji": 20770, "\u0120educate": 20771, "corn": 20772, "iott": 20773, "\u0120Beauty": 20774, "\u0120detective": 20775, "\u0120Conn": 20776, "since": 20777, "\u0120stagger": 20778, "\u0120obese": 20779, "\u0120bree": 20780, "ologic": 20781, "isse": 20782, "walker": 20783, "\u0120blades": 20784, "\u0120lawful": 20785, "func": 20786, "\u0120Behind": 20787, "\u0120appetite": 20788, "\u0120(*": 20789, "\u0120tennis": 20790, "\u0120offspring": 20791, "\u0120jets": 20792, "\u0120structured": 20793, "\u0120aforementioned": 20794, "Nov": 20795, "\u0120scaling": 20796, "fill": 20797, "\u0120stew": 20798, "\u0120curb": 20799, "\u0120Stephan": 20800, "edIn": 20801, "SF": 20802, "obic": 20803, "\u00e9\u0143\u0136": 20804, "oug": 20805, "\u0120MM": 20806, "\u0120genetically": 20807, "opez": 20808, "136": 20809, "\u0120umb": 20810, "ancers": 20811, "\u0120cohort": 20812, "\u0120merchandise": 20813, "\u0120imposing": 20814, "\u0120Legislature": 20815, "\u0120Archive": 20816, "ivia": 20817, "\u0120Naval": 20818, "\u0120offences": 20819, "\u0120miracle": 20820, "\u0120snapped": 20821, "\u0120foes": 20822, "\u0120extensively": 20823, "\u0120Raf": 20824, "\u0120cater": 20825, "edience": 20826, "Kit": 20827, "\u0120Bin": 20828, "\u0120recommends": 20829, "\u0120Cities": 20830, "\u0120rigid": 20831, "\u0120READ": 20832, "\u0120Noble": 20833, "\u0120Tian": 20834, "\u0120certificates": 20835, "antis": 20836, "oiler": 20837, "\u0120Buddhist": 20838, "did": 20839, "\u0120surveyed": 20840, "\u0120downward": 20841, "\u0120prints": 20842, "\u0120Motion": 20843, "ronics": 20844, "\u0120Sans": 20845, "ossibly": 20846, "uctions": 20847, "\u0120colonies": 20848, "\u0120Danish": 20849, "unit": 20850, "\u0120spoil": 20851, "\u0120advisory": 20852, "berries": 20853, "Plan": 20854, "\u0120specification": 20855, "ophers": 20856, "\u0120Resource": 20857, "\u0120shirts": 20858, "prisingly": 20859, "communications": 20860, "\u0120trivial": 20861, "\u0120mentioning": 20862, "isexual": 20863, "\u0120supplements": 20864, "\u0120supervision": 20865, "BP": 20866, "vor": 20867, "\u0120wit": 20868, "\u0120cooldown": 20869, "\u0120plaintiff": 20870, "\u0120Reviews": 20871, "\u0120Sri": 20872, "\u0120Mint": 20873, "\u0120Sugar": 20874, "\u0120afterward": 20875, "\u0120Priest": 20876, "\u0120Investment": 20877, "ogene": 20878, "\u0120Taking": 20879, "\u0120stretching": 20880, "\u0120inflammation": 20881, "\u0120Tehran": 20882, "\u0120lining": 20883, "\u0120freezing": 20884, "\u0120Entity": 20885, "\u0120inspiring": 20886, "special": 20887, "price": 20888, "\u0120sue": 20889, "\u0120Porter": 20890, "ounge": 20891, "ETA": 20892, "\u0120Derek": 20893, "\u0120Luis": 20894, "uo": 20895, "ymph": 20896, "\u0120exterior": 20897, "ihil": 20898, "\u0120Ashley": 20899, "inator": 20900, "\u0120nutrients": 20901, "\u0120Thrones": 20902, "\u0120finances": 20903, "\u0120Inspect": 20904, "\u0120specially": 20905, "\u0120Required": 20906, "\u0120PTS": 20907, "\u0120Violence": 20908, "ointed": 20909, "shots": 20910, "\u0120excerpt": 20911, "coon": 20912, "INS": 20913, "\u0120Gri": 20914, "\u0120recognised": 20915, "Week": 20916, "Young": 20917, "\u0120vom": 20918, "isle": 20919, "\u0120Curry": 20920, "\u0120Buddh": 20921, "\u0120notebook": 20922, "\u0120durable": 20923, "/?": 20924, "\u0120Gad": 20925, "\u0120Pupp": 20926, "\u0120forgive": 20927, "park": 20928, "\u0120personalities": 20929, "analysis": 20930, "clamation": 20931, "\u0120elevator": 20932, "\u0120warehouse": 20933, "\u0120Role": 20934, "unn": 20935, "\u0120illustration": 20936, "\u0120Scan": 20937, "\u0120atmospheric": 20938, "Import": 20939, "ANC": 20940, "ricted": 20941, "fu": 20942, "010": 20943, "\u0120arche": 20944, "\u0120rewarded": 20945, "akespeare": 20946, "\u0120internally": 20947, "\u0120RBI": 20948, "alker": 20949, "\u0120elephant": 20950, "owitz": 20951, "\u0120Pizza": 20952, "\u0120bipartisan": 20953, "\u00c3\u00a9s": 20954, "\u0120slowed": 20955, "\u0120Stark": 20956, "\u0120override": 20957, "OUS": 20958, "\u0120320": 20959, "undreds": 20960, "\u0120Deck": 20961, "\u0120Census": 20962, "bee": 20963, "146": 20964, "otor": 20965, "\u0120ip": 20966, "\u0120ub": 20967, "ocations": 20968, "\u0120Button": 20969, "rice": 20970, "\u0120cripp": 20971, "fff": 20972, "\u0120originated": 20973, "\u0120overwhelmed": 20974, "appa": 20975, "\u0120foremost": 20976, "\u00e2\u0122\u0133": 20977, "\u0120LEG": 20978, "release": 20979, "eatured": 20980, "atches": 20981, "\u0120reps": 20982, "\u0120lending": 20983, "\u0120Reference": 20984, "\u0120Client": 20985, "165": 20986, "venth": 20987, "Complete": 20988, "\u0120Patrol": 20989, "\u0120sworn": 20990, "cam": 20991, "\u0120shuttle": 20992, "\u0120Ralph": 20993, "\u0120hometown": 20994, "-,": 20995, "onal": 20996, "\u0120BP": 20997, "\u00e5\u0131": 20998, "\u0120persuade": 20999, "\u0120Alexand": 21000, "\u0120combines": 21001, "\u0120vivid": 21002, "\u0120Lag": 21003, "\u0120encoding": 21004, "\u0120salvation": 21005, "wen": 21006, "\u0120Recovery": 21007, "iya": 21008, "University": 21009, "\u0120Biden": 21010, "\u0120budgets": 21011, "\u0120Texans": 21012, "fits": 21013, "\u0120honored": 21014, "\u0120python": 21015, "TD": 21016, "###": 21017, "clone": 21018, "\u0120blink": 21019, "\u0120Liquid": 21020, "\u0120unemployed": 21021, "\u0120clashes": 21022, "\u0120Counsel": 21023, "\u0120directing": 21024, "\u0120punct": 21025, "\u0120Falcons": 21026, "\u0120shark": 21027, "\u0120Damascus": 21028, "\u0120jeans": 21029, "\u0120embark": 21030, "\u0120seize": 21031, "\u0120upwards": 21032, "280": 21033, "\u0120Ez": 21034, "\u0120Anything": 21035, "\u0120exotic": 21036, "lower": 21037, "\u0120Creator": 21038, "\u0120Um": 21039, "\u0120suburbs": 21040, "berger": 21041, "\u0120Wend": 21042, "\u0120mint": 21043, "\u0120XX": 21044, "\u0120Dro": 21045, "\u0120suffers": 21046, "\u0120herb": 21047, "tree": 21048, "\u0120fragile": 21049, "\u0120flooded": 21050, "\u0120Alcohol": 21051, "olean": 21052, "nyder": 21053, "\u0120KO": 21054, "Fram": 21055, "\u0120136": 21056, "\u0120owed": 21057, "\u0120Melee": 21058, "\u0120Hash": 21059, "\u0120whisk": 21060, "\u0120sudo": 21061, "rr": 21062, "Quick": 21063, "appro": 21064, "\u0120ii": 21065, "\u0120Examples": 21066, "hee": 21067, "\u0120promotes": 21068, "perature": 21069, "kar": 21070, "\u0120Honor": 21071, "\u0120sodium": 21072, "\u0120Lif": 21073, "rosso": 21074, "intendent": 21075, "\u0120correspondent": 21076, "Found": 21077, "secret": 21078, "\u0120identifies": 21079, "agne": 21080, "\u0120lou": 21081, "\u0120PP": 21082, "\u0120coincidence": 21083, "move": 21084, "\u0120militia": 21085, "\u0120infiltr": 21086, "\u0120Primary": 21087, "\u0120pitching": 21088, "\u0120Ib": 21089, "\u0120GOOD": 21090, "\u00e3\u0124\u00b8": 21091, "\u0120Wizards": 21092, "iral": 21093, "\u0120Venus": 21094, "RR": 21095, "\u0120\u00e2\u0122\u0137": 21096, "\u0120Casey": 21097, "\u0120sadly": 21098, "\u0120admire": 21099, "\u0120embarrassed": 21100, "cb": 21101, "Mel": 21102, "\u0120tubes": 21103, "\u0120beautifully": 21104, "\u0120Queensland": 21105, "Below": 21106, "rez": 21107, "quet": 21108, "pleasant": 21109, "\u0120\u00c2\u00ab": 21110, "Camp": 21111, "\u0120decisive": 21112, "1998": 21113, "\u0120Lamb": 21114, "utton": 21115, "hn": 21116, "\u0120Jagu": 21117, "aunder": 21118, "\u0120Cord": 21119, "\u0120clerk": 21120, "\u0120caffe": 21121, "\u0120wiped": 21122, "\u0120reim": 21123, "\u0120Mountains": 21124, "\u0120imprisoned": 21125, "\u0120develops": 21126, "\u0120Pra": 21127, "\u0120modeling": 21128, "Anyone": 21129, "ancel": 21130, "\u0120Sit": 21131, "\u0120shields": 21132, "\u0120lawn": 21133, "\u0120cardiovascular": 21134, "\u0120demonstrating": 21135, "\u0120parse": 21136, "\u0120Israelis": 21137, "\u0120euros": 21138, "143": 21139, "\u0120glorious": 21140, "inski": 21141, "ecd": 21142, "\u0120conditioning": 21143, "\u0120helpless": 21144, "\u0120microsc": 21145, "\u0120Harbor": 21146, "\u0120stakes": 21147, "\u0120260": 21148, "\u0120unequ": 21149, "\u0120Floyd": 21150, "\u0120damp": 21151, "\u0120apparatus": 21152, "\u0120Laws": 21153, "\u0120counters": 21154, "\u0120induce": 21155, "atable": 21156, "\u0120Ahmed": 21157, "\u0120slam": 21158, "November": 21159, "\u0120persist": 21160, "\u0120imminent": 21161, "\u00c3\u00a1n": 21162, "\u0120shred": 21163, "\u0120phases": 21164, "\u0120Edmonton": 21165, "\u0120Armstrong": 21166, "\u0120Meet": 21167, "\u0120Kitty": 21168, "\u00d1\u0122": 21169, "circ": 21170, "\u0120Adult": 21171, "\u0120arose": 21172, "\u0120Xen": 21173, "Dan": 21174, "gow": 21175, "\u0120superf": 21176, "\u0120Admir": 21177, "\u0120endure": 21178, "\u0120keyword": 21179, "yrus": 21180, "\u0120yarn": 21181, "\u0120pathway": 21182, "\u0120Hopkins": 21183, "midt": 21184, "\u0120censorship": 21185, "dependent": 21186, "\u0120instructor": 21187, "Sources": 21188, "\u0120toe": 21189, "\u0120balloon": 21190, "Nob": 21191, "\u0120swear": 21192, "\u0120Castro": 21193, "\u0120gloss": 21194, "\u0120Kavanaugh": 21195, "\u0120remarkably": 21196, "Photos": 21197, "\u0120Nom": 21198, "\u0120Southeast": 21199, "yers": 21200, "\u0120validation": 21201, "\u0120cannon": 21202, "\u0120Victory": 21203, "\u0120Pierre": 21204, "\u0120cautious": 21205, "Audio": 21206, "\u0120fetch": 21207, "\u0120Gift": 21208, "\u0120Hyp": 21209, "\u0120remedy": 21210, "ZE": 21211, "\u0120scent": 21212, "\u0120beard": 21213, "\u0120Rut": 21214, "-\"": 21215, "\u0120patents": 21216, "Hy": 21217, "\u0120unjust": 21218, "\u0120potato": 21219, "\u0120forthcoming": 21220, "\u0120chef": 21221, "\u0120Rift": 21222, "affe": 21223, "\u0120ROM": 21224, "\u0120Launch": 21225, "\u0120pads": 21226, "\u0120Neo": 21227, "\u0120onset": 21228, "\u0120squeeze": 21229, "safe": 21230, "\u0120prefix": 21231, "\u0120TM": 21232, "\u0120Nearly": 21233, "\u0120Clinical": 21234, "\u0120Mental": 21235, "otiation": 21236, "\u0120Unic": 21237, "antry": 21238, "\u0120Cir": 21239, "\u0120epit": 21240, "\u00c3\u00a6": 21241, "\u0120extracted": 21242, "versely": 21243, "riad": 21244, "\u0120strains": 21245, "\u0120tops": 21246, "\u0120poem": 21247, "\u0120Randy": 21248, "\u0120Maple": 21249, "THER": 21250, "upiter": 21251, "\u0120SSD": 21252, "\u013c\u00e9": 21253, "\u0120uncon": 21254, "pering": 21255, "\u0120slept": 21256, "iners": 21257, "\u0120underwater": 21258, "\u0120Evidence": 21259, "gone": 21260, "205": 21261, "\u0120historians": 21262, "\u0120synthesis": 21263, "\u0120frog": 21264, "basketball": 21265, "\u0120vibrant": 21266, "\u0120subord": 21267, "\u0120365": 21268, "\u0120Dial": 21269, "\u0120cooperate": 21270, "HAHA": 21271, "\u0120greeted": 21272, "158": 21273, "\u0120jazz": 21274, "\u0120intox": 21275, "\u0120Walking": 21276, "\u0120supervisor": 21277, "\u0120Fusion": 21278, "\u0120Mercedes": 21279, "send": 21280, "Ham": 21281, "sd": 21282, "nl": 21283, "\u0120tours": 21284, "\u0120FIFA": 21285, "\u0120culp": 21286, "gd": 21287, "304": 21288, "\u0120pleas": 21289, "\u0120illustrates": 21290, "\u0120Colombia": 21291, "\u0120highlighting": 21292, "\u0120Summary": 21293, "\u0120exposing": 21294, "\u0120Dru": 21295, "\u0120irony": 21296, "ritional": 21297, "\u0120Carroll": 21298, "\u0120Ellis": 21299, "Pict": 21300, "\u0120Rapt": 21301, "\u0120adapter": 21302, "\u0120unm": 21303, "\u0120corpse": 21304, "\u0120celebrities": 21305, "Den": 21306, "atum": 21307, "\u0120Apocalypse": 21308, "\u0120Wag": 21309, "lining": 21310, "\u0120hormones": 21311, "Rub": 21312, "\u0120Xi": 21313, "\u0120Vaults": 21314, "208": 21315, "alkyrie": 21316, "inosaur": 21317, "\u0120feeds": 21318, "vity": 21319, "\u0120defeating": 21320, "Wait": 21321, "\u0120emphasize": 21322, "\u0120Steelers": 21323, "yrinth": 21324, "leys": 21325, "\u0120Whenever": 21326, "Currently": 21327, "\u0120Clock": 21328, "\u0120collectively": 21329, "anyon": 21330, "\u0120JP": 21331, "\u0120mentality": 21332, "\u0120downloads": 21333, "\u0120surroundings": 21334, "\u0120Barnes": 21335, "\u0120flagship": 21336, "\u0120indicators": 21337, "\u0120grapp": 21338, "January": 21339, "\u0120Elemental": 21340, "\u0120Athena": 21341, "ibal": 21342, "\u0120sights": 21343, "\u0120capita": 21344, "\u0120Treaty": 21345, "\u0120voiced": 21346, "\u0120Gaz": 21347, "lette": 21348, "\u0120ya": 21349, "\u0120expired": 21350, "Legend": 21351, "Hot": 21352, "nature": 21353, "\u0120unstable": 21354, "\u0120280": 21355, "\u00c3\u00ba": 21356, "Comment": 21357, "ALE": 21358, "\u0120quests": 21359, "\u0120handler": 21360, "nis": 21361, "\u0120versatile": 21362, "\u0120conceal": 21363, "engeance": 21364, "\u0120Interactive": 21365, "\u0120obsessed": 21366, "\u0120Dogs": 21367, "\u0120cracked": 21368, "Sound": 21369, "sv": 21370, "\u0120Dylan": 21371, "roads": 21372, "fx": 21373, "\u0120Catholics": 21374, "\u0120Hag": 21375, "\u0120slammed": 21376, "\u0120glowing": 21377, "sale": 21378, "\u0120tissues": 21379, "\u0120Chi": 21380, "nee": 21381, "\u0120cher": 21382, "sic": 21383, "urrection": 21384, "\u0120bacon": 21385, "ulatory": 21386, ").\"": 21387, "\u0120irregular": 21388, "FORM": 21389, "assed": 21390, "\u0120intentional": 21391, "\u0120compensate": 21392, "\u0120Speaking": 21393, "\u0120Sets": 21394, "153": 21395, "\u0120conventions": 21396, "bands": 21397, "emade": 21398, "\u0120ecc": 21399, "\u0120Winston": 21400, "\u0120Assassin": 21401, "\u0120Belgian": 21402, "\u0120dependence": 21403, "\u0120niche": 21404, "\u0120bark": 21405, "\u0120Jazz": 21406, "\u0120disadvantage": 21407, "\u0120gasoline": 21408, "\u0120165": 21409, "\u00e7\u013c\u0126": 21410, "essa": 21411, "module": 21412, "angular": 21413, "OY": 21414, "\u0120Treatment": 21415, "itas": 21416, "olation": 21417, "\u0120Arnold": 21418, "\u0120feud": 21419, "\u0120Nest": 21420, "\u0120theatre": 21421, "ewater": 21422, "\u0120minors": 21423, "olicy": 21424, "\u0120Haven": 21425, "division": 21426, "\u0120trunk": 21427, "Far": 21428, "\u0120Pull": 21429, "\u0120capturing": 21430, "\u01201800": 21431, "\u0120Teen": 21432, "\u0120exempl": 21433, "\u0120clinics": 21434, "\u0120Burg": 21435, "\u0120substit": 21436, "\u0120payload": 21437, "\u0120Lav": 21438, "\u0120Troy": 21439, "\u0120Witness": 21440, "\u0120fragments": 21441, "\u0120passwords": 21442, "\u0120gospel": 21443, "\u0120Gin": 21444, "\u0120tenants": 21445, "olith": 21446, "Six": 21447, "Previous": 21448, "\u0120Ages": 21449, "\u0120Darwin": 21450, "\u0120blat": 21451, "\u0120empathy": 21452, "smith": 21453, "bag": 21454, "\u0120Echo": 21455, "\u0120Camb": 21456, "\u0120Madd": 21457, "\u0120Boo": 21458, "\u0120rede": 21459, "\u0120Burning": 21460, "\u0120smoothly": 21461, "\u0120Adrian": 21462, "\u0120Vampire": 21463, "\u0120Monsters": 21464, "steam": 21465, "Style": 21466, "Ma": 21467, "rea": 21468, "\u0120Dwar": 21469, "alyst": 21470, "ursor": 21471, "\u0120elimination": 21472, "\u0120crypto": 21473, "cht": 21474, "\u0120Eternal": 21475, "\u00e2\u0122\u00a6]": 21476, "\u0120Sorce": 21477, "Ill": 21478, "NER": 21479, "\u0120uh": 21480, "Conclusion": 21481, "wage": 21482, "\u0120respir": 21483, "\u0120reminis": 21484, "hetical": 21485, "\u0120gy": 21486, "\u0120utilized": 21487, "icidal": 21488, "\u01201900": 21489, "\u0120hunters": 21490, "\u0120Swan": 21491, "\u0120React": 21492, "\u0120visitor": 21493, "\u0120Thanksgiving": 21494, "308": 21495, "Posts": 21496, "\u0120hips": 21497, "1997": 21498, "omers": 21499, "\u0120knocking": 21500, "\u0120Vehicle": 21501, "\u0120til": 21502, "\u0120138": 21503, "\u0120mi": 21504, "\u0120Investigation": 21505, "\u0120Kenya": 21506, "\u0120casino": 21507, "\u0120motives": 21508, "\u0120regain": 21509, "rex": 21510, "\u0120weekends": 21511, "\u0120stabbed": 21512, "boro": 21513, "\u0120exploited": 21514, "\u0120HAVE": 21515, "\u0120Television": 21516, "cock": 21517, "\u0120preparations": 21518, "\u0120endeav": 21519, "\u0120Remote": 21520, "\u0120Maker": 21521, "\u0120Produ": 21522, "\u0120Evan": 21523, "\u0120informational": 21524, "\u0120Louisville": 21525, "154": 21526, "\u0120Dreams": 21527, "\u0120plots": 21528, "\u0120Runner": 21529, "\u0120hurting": 21530, "\u0120academy": 21531, "\u0120Montgomery": 21532, "nm": 21533, "\u0120Lanc": 21534, "\u0120Alz": 21535, "210": 21536, "elong": 21537, "\u0120retailer": 21538, "\u0120arising": 21539, "\u0120rebellion": 21540, "\u0120blonde": 21541, "played": 21542, "\u0120instrumental": 21543, "Cross": 21544, "\u0120retention": 21545, "\u0120therapeutic": 21546, "\u0120seas": 21547, "\u0120infantry": 21548, "\u0120Clint": 21549, "\u0120prompting": 21550, "\u0120bitch": 21551, "\u0120stems": 21552, "\u0120Kra": 21553, "\u0120thesis": 21554, "\u0120Bog": 21555, "rued": 21556, "\u0120kings": 21557, "\u0120clay": 21558, "ificent": 21559, "\u0120YES": 21560, "\u0120Thing": 21561, "\u0120Cubs": 21562, "veyard": 21563, "elsh": 21564, "inarily": 21565, "\u0120Ey": 21566, "\u0120Rolling": 21567, "\u0120evolving": 21568, "India": 21569, "\u0120recognizes": 21570, "\u0120graduation": 21571, "isers": 21572, "\u0120fertility": 21573, "\u0120Milan": 21574, "Command": 21575, "\u0120boxing": 21576, "\u01201943": 21577, "\u0120gluten": 21578, "\u0120Emir": 21579, "\u0120idol": 21580, "\u0120conceived": 21581, "\u0120Creation": 21582, "Merit": 21583, "uddy": 21584, "ussions": 21585, "\u0120Lieutenant": 21586, "ietal": 21587, "\u0120unchanged": 21588, "\u0120Scale": 21589, "\u0120Crimea": 21590, "balls": 21591, "atorial": 21592, "\u0120depths": 21593, "\u0120empirical": 21594, "\u0120transm": 21595, "\u0120unsafe": 21596, "missible": 21597, "comfort": 21598, "156": 21599, "\u0120mechanic": 21600, "002": 21601, "lins": 21602, "\u0120smoked": 21603, "Pos": 21604, "\u0120slowing": 21605, "\u0120lav": 21606, "Texas": 21607, "\u0120cheating": 21608, "\u0120Metropolitan": 21609, "ethyl": 21610, "\u0120discovering": 21611, "asse": 21612, "\u0120pencil": 21613, "\u0120Pyongyang": 21614, "\u0120closet": 21615, "\u0120Sheet": 21616, "\u0120Entry": 21617, "oustic": 21618, "\u0120myst": 21619, "erate": 21620, "ariat": 21621, "\u0120minerals": 21622, "\u0120musician": 21623, "\u0120Pul": 21624, "\u0120Maz": 21625, "249": 21626, "\u0120permissions": 21627, "\u0120iv": 21628, "enary": 21629, "ickers": 21630, "\u0120Bing": 21631, "hea": 21632, "enable": 21633, "\u0120griev": 21634, "\u0120asserted": 21635, "\u0120Colonel": 21636, "\u0120affidav": 21637, "wo": 21638, "\u0120seated": 21639, "\u0120Ride": 21640, "\u0120paintings": 21641, "\u0120Pix": 21642, "\u0120137": 21643, "ishi": 21644, "umbai": 21645, "gotten": 21646, "\u0120Earl": 21647, "\u0120inning": 21648, "\u0120census": 21649, "\u0120travelled": 21650, "\u0120Consult": 21651, "185": 21652, "bind": 21653, "\u0120simplicity": 21654, "\u0120overlooked": 21655, "\u0120Helpful": 21656, "\u0120monkey": 21657, "\u0120overwhelmingly": 21658, "Blood": 21659, "\u0120Flint": 21660, "\u0120Jama": 21661, "\u0120Present": 21662, "\u0120Rage": 21663, "\u0120TA": 21664, "ptive": 21665, "\u0120turnout": 21666, "wald": 21667, "\u0120Dolphins": 21668, "\u0120VPN": 21669, "\u0120onion": 21670, "\u0120crafting": 21671, "mma": 21672, "\u0120Mercury": 21673, "\u0120arrange": 21674, "\u0120alerts": 21675, "\u0120OT": 21676, "zbollah": 21677, "\u0120gases": 21678, "\u0120Richardson": 21679, "sal": 21680, "lar": 21681, "\u0120frost": 21682, "\u0120lowering": 21683, "\u0120acclaim": 21684, "\u0120startups": 21685, "\u0120Gain": 21686, "essment": 21687, "\u0120guardian": 21688, "\u00e4\u00ba\u00ba": 21689, "\u0120Pie": 21690, "\u0120Links": 21691, "\u0120merits": 21692, "\u0120awake": 21693, "\u0120parental": 21694, "\u0120exceeds": 21695, "\u0120idle": 21696, "\u0120Pilot": 21697, "\u0120eBay": 21698, "\u0120Accept": 21699, "ipeg": 21700, "Cam": 21701, "\u0120Kot": 21702, "\u0120traders": 21703, "olitics": 21704, "unker": 21705, "\u0120Pale": 21706, "osi": 21707, "anmar": 21708, "\u01201947": 21709, "\u0120Fell": 21710, "estial": 21711, "itating": 21712, "GF": 21713, "\u0120Sr": 21714, "ifted": 21715, "\u0120connector": 21716, "\u0120Bone": 21717, "illes": 21718, "260": 21719, "hma": 21720, "\u0120overlap": 21721, "\u0120GitHub": 21722, "\u0120cleaner": 21723, "\u0120Baptist": 21724, "\u0120WAS": 21725, "\u0120lungs": 21726, "\u00d1\u0123": 21727, "\u0120BUT": 21728, "\u0120cite": 21729, "\u0120pitched": 21730, "reatment": 21731, "\u0120trophies": 21732, "\u0120Nu": 21733, "386": 21734, "\u0120Pride": 21735, "\u0120attendees": 21736, "[]": 21737, "179": 21738, "\u0120spatial": 21739, "\u0120prizes": 21740, "\u0120Religion": 21741, "\u0120showcase": 21742, "\u0120Category": 21743, "vidia": 21744, "Target": 21745, "Property": 21746, "?,": 21747, "\u0120fusion": 21748, "pie": 21749, "\u0120UCLA": 21750, "\u0120soundtrack": 21751, "\u0120princess": 21752, "\u0120Caval": 21753, "should": 21754, "\u0120limbs": 21755, "Background": 21756, "\u0120lonely": 21757, "\u0120cores": 21758, "\u0120Tail": 21759, "sheet": 21760, "\u0120132": 21761, "Ra": 21762, "\u00e3\u0124\u00ab": 21763, "\u0120Bolt": 21764, "\u0120booked": 21765, "\u0120administer": 21766, "\u0120equals": 21767, "wy": 21768, "\u0120observing": 21769, "\u0120Baron": 21770, "\u0120Adobe": 21771, "\u0120virgin": 21772, "\u0120Socialist": 21773, "Move": 21774, "ghazi": 21775, "\u0120Linda": 21776, "212": 21777, "\u0120brewing": 21778, "\u0120merchants": 21779, "burse": 21780, "\u0120divor": 21781, "\u0120metals": 21782, "\u0120Ner": 21783, "\u0120sums": 21784, "\u0120Enemy": 21785, "\u0120envision": 21786, "\u0120granting": 21787, "\u0120Honey": 21788, "\u0120Skyrim": 21789, "\u0120socio": 21790, "graded": 21791, "\u0120selective": 21792, "WASHINGTON": 21793, "\u01201948": 21794, "\u0120Sirius": 21795, "\u0120Gross": 21796, "activity": 21797, "\u0120Ivan": 21798, "\u0120furious": 21799, "BSD": 21800, "\u0120Previous": 21801, "\u0120responsive": 21802, "\u0120charitable": 21803, "\u0120leaning": 21804, "\u0120Pew": 21805, "\u0120violates": 21806, "\\\\\\\\\\\\\\\\": 21807, "\u0120Coming": 21808, "wire": 21809, "\u0120poet": 21810, "\u0120resolutions": 21811, "command": 21812, "\u0120Portuguese": 21813, "\u0120nickname": 21814, "\u0120deaf": 21815, "February": 21816, "\u0120recognise": 21817, "\u0120entirety": 21818, "\u0120seasonal": 21819, "placed": 21820, "\u0120Telegraph": 21821, "\u0120microphone": 21822, "ouring": 21823, "\u0120grains": 21824, "\u0120governed": 21825, "\u0120postp": 21826, "\u0120Waters": 21827, "inement": 21828, "\u0120undocumented": 21829, "\u0120Comcast": 21830, "\u0120fox": 21831, "\u0120assaults": 21832, "reon": 21833, "many": 21834, "\u0120Jenkins": 21835, "\u0120Anyway": 21836, "\u0120assessments": 21837, "\u0120downs": 21838, "\u0120Mouse": 21839, "\u0120superb": 21840, "kt": 21841, "\u0120Dow": 21842, "\u0120taxation": 21843, "401": 21844, "\u0120smiles": 21845, "\u0120undertaken": 21846, "\u0120exh": 21847, "\u0120enthusiastic": 21848, "\u0120twent": 21849, "\u0120governmental": 21850, "\u0120autonomy": 21851, "\u0120Technologies": 21852, "\u0120Chain": 21853, "\u0120prevalent": 21854, "fb": 21855, "\u0120nicotine": 21856, "ogram": 21857, "job": 21858, "\u0120awaiting": 21859, "\u0120Menu": 21860, "\u0120deputies": 21861, "kov": 21862, "ishops": 21863, "Button": 21864, "\u0120Shanghai": 21865, "\u0120diesel": 21866, "\u0120Duck": 21867, "Ryan": 21868, "\u0120PCs": 21869, "NF": 21870, "jury": 21871, "ente": 21872, "\u0120inaccurate": 21873, "eddy": 21874, "Whatever": 21875, "\u0120showc": 21876, "\u0120Nad": 21877, "odus": 21878, "etr": 21879, "\u0120plaintiffs": 21880, "\u0120WOR": 21881, "\u0120Assange": 21882, "\u0120privat": 21883, "\u0120premiums": 21884, "\u0120tam": 21885, "URL": 21886, "\u0120elites": 21887, "\u0120Ranger": 21888, "ottenham": 21889, "\u0120Hoff": 21890, "\u0120Athens": 21891, "\u0120definite": 21892, "\u0120sighed": 21893, "\u0120evenly": 21894, "211": 21895, "\u0120Amber": 21896, "akia": 21897, "\u0120mailing": 21898, "\u0120crashing": 21899, "\u0120Confederate": 21900, "rugged": 21901, "Wal": 21902, "\u0120Depths": 21903, "\u0120juvenile": 21904, "\u0120reactor": 21905, "Introduction": 21906, "\u0120Deluxe": 21907, "1995": 21908, "\u0120Sanchez": 21909, "\u0120Mead": 21910, "ivable": 21911, ":-": 21912, "\u0120Planning": 21913, "\u0120Trap": 21914, "quin": 21915, "\u0120Protect": 21916, "vered": 21917, "Information": 21918, "\u0120kidney": 21919, "innamon": 21920, "las": 21921, "\u0120policing": 21922, "\u0120tolerate": 21923, "\u0120Qi": 21924, "\u0120biased": 21925, "Fort": 21926, "\u0120Ki": 21927, "save": 21928, "\u0120privileged": 21929, "\u0120beasts": 21930, "\u0120Glas": 21931, "\u0120Cinem": 21932, "\u0120comeback": 21933, "Sunday": 21934, "\u0120extinction": 21935, "hops": 21936, "\u0120transmit": 21937, "\u0120doubles": 21938, "\u0120Flat": 21939, "167": 21940, "\u0120disputed": 21941, "\u0120injustice": 21942, "foo": 21943, "Vict": 21944, "roleum": 21945, "\u0120Julie": 21946, "Context": 21947, "\u0120Rarity": 21948, "issue": 21949, "Component": 21950, "\u0120counseling": 21951, "anne": 21952, "dark": 21953, "\u0120objections": 21954, "uilt": 21955, "\u0120gast": 21956, "\u0120plac": 21957, "\u0120unused": 21958, "\u00e3\u0125\u0129": 21959, "\u0120Trial": 21960, "\u0120Jas": 21961, "hedral": 21962, "obb": 21963, "\u0120temporal": 21964, "\u0120PRO": 21965, "\u0120NW": 21966, "\u0120Anniversary": 21967, "Large": 21968, "\u0120therm": 21969, "\u0120david": 21970, "\u0120systemic": 21971, "\u0120Shir": 21972, "mut": 21973, "\u0120Nept": 21974, "address": 21975, "\u0120scanning": 21976, "\u0120understandable": 21977, "\u0120canvas": 21978, "Cat": 21979, "\u0120Zoo": 21980, "\u0120angels": 21981, "LO": 21982, "\u0120Statement": 21983, "\u0120Sig": 21984, "ovable": 21985, "\u0120Away": 21986, "sharing": 21987, "ocrats": 21988, "stated": 21989, "\u0120weighing": 21990, "Nor": 21991, "wild": 21992, "Bey": 21993, "\u0120astonishing": 21994, "\u0120Reynolds": 21995, "\u0120opener": 21996, "\u0120trainer": 21997, "\u0120surgical": 21998, "pn": 21999, "\u0120adjusting": 22000, "wheel": 22001, "\u0120frown": 22002, "ervative": 22003, "\u0120suspend": 22004, "Within": 22005, "tein": 22006, "\u0120obstacle": 22007, "\u0120liberties": 22008, "ymes": 22009, "\u0120uranium": 22010, "ansom": 22011, "anol": 22012, "uba": 22013, "\u0120Loss": 22014, "\u0120arous": 22015, "\u0120Henderson": 22016, "Wow": 22017, "spl": 22018, "cur": 22019, "\u0120\u00c2\u0143": 22020, "\u0120theirs": 22021, "Damage": 22022, "\u0120downloading": 22023, "\u0120discern": 22024, "\u0120Sto": 22025, "\u0120Fla": 22026, "\u0120hath": 22027, "\u0120Aj": 22028, "\u0120unpleasant": 22029, "European": 22030, "expensive": 22031, "\u0120screenshot": 22032, "\u0120UV": 22033, "\u0120allied": 22034, "\u0120Persian": 22035, "\u0120monopoly": 22036, "\u0120atom": 22037, "\u0120Redskins": 22038, "\"><": 22039, "\u0120cancell": 22040, "\u0120cinema": 22041, "131": 22042, "fair": 22043, "\u0120Alfred": 22044, "\u0120duck": 22045, "args": 22046, "223": 22047, "\u0120ISI": 22048, "\u0120signaling": 22049, "inar": 22050, "\u0120laughs": 22051, "\u0120forwards": 22052, "\u0120reckless": 22053, "\u0120listeners": 22054, "ativity": 22055, "\u0120vastly": 22056, "nant": 22057, "Less": 22058, "\u0120Hunting": 22059, "\u0120Scientific": 22060, "ITED": 22061, "\u0120knight": 22062, "\u0120HTC": 22063, "usa": 22064, "tmp": 22065, "\u0120rude": 22066, "\u0120Legendary": 22067, "\u0120arises": 22068, "Bad": 22069, "\u0120Claim": 22070, "peg": 22071, "\u0120realities": 22072, "Think": 22073, "\u0120\u00c2\u00b0": 22074, "\u0120rode": 22075, "\u0120strive": 22076, "\u0120anecd": 22077, "\u0120shorts": 22078, "\u0120hypothes": 22079, "\u0120coordinated": 22080, "\u0120Gandhi": 22081, "\u0120FPS": 22082, "RED": 22083, "\u0120susceptible": 22084, "\u0120shrink": 22085, "\u0120Chart": 22086, "Help": 22087, "\u0120ion": 22088, "deep": 22089, "ribes": 22090, "\u0120Kai": 22091, "\u0120Customer": 22092, "Summary": 22093, "\u0120cough": 22094, "wife": 22095, "\u0120lend": 22096, "\u0120positioning": 22097, "\u0120lottery": 22098, "\u0120Canyon": 22099, "\u0120fade": 22100, "\u0120bronze": 22101, "\u0120Kenny": 22102, "\u0120boasts": 22103, "\u0120Enhanced": 22104, "record": 22105, "\u0120emergence": 22106, "\u0120akin": 22107, "\u0120Bert": 22108, "itous": 22109, "\u00e2\u0138\u0133": 22110, "\u0120stip": 22111, "\u0120exchanged": 22112, "omore": 22113, "alsh": 22114, "\u0120reservoir": 22115, "\u0120standpoint": 22116, "WM": 22117, "\u0120initiate": 22118, "\u0120decay": 22119, "\u0120brewery": 22120, "\u0120terribly": 22121, "\u0120mortal": 22122, "levard": 22123, "\u0120revis": 22124, "NI": 22125, "elo": 22126, "\u0120confess": 22127, "\u0120MSNBC": 22128, "\u0120submissions": 22129, "Controller": 22130, "\u0120202": 22131, "\u0120Ruth": 22132, "});": 22133, "\u0120Azure": 22134, "\u0120.\"": 22135, "206": 22136, "\u0120Marketing": 22137, "\u0120laund": 22138, "iencies": 22139, "\u0120renowned": 22140, "\u0120Trou": 22141, "\u0120NGO": 22142, "blems": 22143, "\u0120terrified": 22144, "\u0120warns": 22145, "\u0120pert": 22146, "\u0120unsure": 22147, "480": 22148, "alez": 22149, "ultz": 22150, "\u0120Outside": 22151, "\u0120styl": 22152, "\u0120Underground": 22153, "\u0120panc": 22154, "\u0120dictionary": 22155, "\u0120foe": 22156, "riminal": 22157, "\u0120Norwegian": 22158, "\u0120jailed": 22159, "\u0120maternal": 22160, "\u00c3\u00a9e": 22161, "\u0120Lucy": 22162, "cop": 22163, "Cho": 22164, "\u0120unsigned": 22165, "\u0120Zelda": 22166, "\u0120Insider": 22167, "\u0120Continued": 22168, "\u0120133": 22169, "\u0120Naruto": 22170, "\u0120Majority": 22171, "169": 22172, "\u0120Wo": 22173, "\u00e3\u0124\u0135": 22174, "\u0120pastor": 22175, "\u0120informal": 22176, "\u00d0\u00bd": 22177, "anthrop": 22178, "join": 22179, "\u00e3\u0123\u0139": 22180, "itational": 22181, "NP": 22182, "\u0120Writing": 22183, "fn": 22184, "\u0120Bever": 22185, "195": 22186, "\u0120yelling": 22187, "\u0120drastically": 22188, "\u0120eject": 22189, "\u0120neut": 22190, "\u0120thrive": 22191, "\u0120Frequ": 22192, "oux": 22193, "\u0120possesses": 22194, "\u0120Senators": 22195, "\u0120DES": 22196, "\u0120Shakespeare": 22197, "\u0120Franco": 22198, "\u0120LB": 22199, "uchi": 22200, "\u0120incarn": 22201, "\u0120founders": 22202, "Function": 22203, "\u0120brightness": 22204, "\u0120BT": 22205, "\u0120whale": 22206, "\u0120Theater": 22207, "mass": 22208, "\u0120Doll": 22209, "Something": 22210, "\u0120echoed": 22211, "\u0120Hex": 22212, "crit": 22213, "afia": 22214, "\u0120goddess": 22215, "\u0120eleven": 22216, "\u0120Preview": 22217, "\u0120Aurora": 22218, "\u0120401": 22219, "ulsive": 22220, "\u0120Logan": 22221, "inburgh": 22222, "\u0120Centers": 22223, "\u0120ONLY": 22224, "\u0120Aid": 22225, "\u0120paradox": 22226, "\u0120hurd": 22227, "\u0120LC": 22228, "Due": 22229, "court": 22230, "\u0120offended": 22231, "\u0120evaluating": 22232, "\u0120Matthews": 22233, "\u0120tomb": 22234, "\u0120payroll": 22235, "\u0120extraction": 22236, "\u0120Hands": 22237, "ifi": 22238, "\u0120supernatural": 22239, "\u0120COMM": 22240, "]=": 22241, "dogs": 22242, "\u0120512": 22243, "\u0120Meeting": 22244, "Richard": 22245, "\u0120Maximum": 22246, "\u0120ideals": 22247, "Things": 22248, "mand": 22249, "\u0120Regardless": 22250, "\u0120humili": 22251, "buffer": 22252, "Little": 22253, "\u0120Dani": 22254, "\u0120Nak": 22255, "\u0120liberation": 22256, "\u0120Abe": 22257, "\u0120OL": 22258, "\u0120stuffed": 22259, "aca": 22260, "inda": 22261, "raphic": 22262, "\u0120mosqu": 22263, "\u0120campaigning": 22264, "\u0120occupy": 22265, "Squ": 22266, "rina": 22267, "\u0120Wel": 22268, "\u0120VS": 22269, "\u0120physic": 22270, "\u0120puls": 22271, "rint": 22272, "oaded": 22273, "ETF": 22274, "\u0120Archives": 22275, "\u0120venues": 22276, "hner": 22277, "\u0120Turbo": 22278, "\u0120lust": 22279, "\u0120appealed": 22280, "quez": 22281, "ilib": 22282, "\u0120Timothy": 22283, "\u0120omn": 22284, "dro": 22285, "\u0120obsession": 22286, "\u0120Savage": 22287, "1996": 22288, "Global": 22289, "Jes": 22290, "214": 22291, "\u0120sliding": 22292, "\u0120disappro": 22293, "\u0120Magical": 22294, "\u0120voluntarily": 22295, "gb": 22296, "aney": 22297, "\u0120prophet": 22298, "\u0120Rein": 22299, "\u0120Julia": 22300, "\u0120Worth": 22301, "aurus": 22302, "\u0120bounds": 22303, "ieu": 22304, ")))": 22305, "\u0120crore": 22306, "\u0120Citizen": 22307, "Sky": 22308, "\u0120columnist": 22309, "\u0120seekers": 22310, "ondo": 22311, "ISA": 22312, "\u0120Length": 22313, "\u0120nostalg": 22314, "\u0120newcom": 22315, "\u0120detrim": 22316, "entric": 22317, "375": 22318, "\u0120GE": 22319, "\u0120autop": 22320, "\u0120academics": 22321, "AppData": 22322, "\u0120Shen": 22323, "\u0120idiot": 22324, "\u0120Transit": 22325, "\u0120teaspoon": 22326, "Wil": 22327, "KO": 22328, "\u0120Comedy": 22329, ">,": 22330, "\u0120populated": 22331, "WD": 22332, "\u0120pigs": 22333, "\u0120Oculus": 22334, "\u0120sympathetic": 22335, "\u0120marathon": 22336, "198": 22337, "\u0120seizure": 22338, "sided": 22339, "\u0120dop": 22340, "irtual": 22341, "Land": 22342, "\u0120Floor": 22343, "osaurs": 22344, "...]": 22345, "\u0120los": 22346, "\u0120subsidiary": 22347, "EY": 22348, "\u0120Parts": 22349, "\u0120Stef": 22350, "\u0120Judiciary": 22351, "\u0120134": 22352, "\u0120mirrors": 22353, "\u0120ket": 22354, "times": 22355, "\u0120neurolog": 22356, "\u0120cav": 22357, "\u0120Guest": 22358, "\u0120tumor": 22359, "scill": 22360, "\u0120Lloyd": 22361, "Est": 22362, "\u0120clearer": 22363, "\u0120stereotypes": 22364, "\u0120dur": 22365, "nothing": 22366, "Reddit": 22367, "\u0120negotiated": 22368, "------------------------": 22369, "235": 22370, "\u0120flown": 22371, "\u0120Seoul": 22372, "\u0120Resident": 22373, "\u0120SCH": 22374, "\u0120disappearance": 22375, "\u0120Vince": 22376, "grown": 22377, "\u0120grabs": 22378, "ril": 22379, "\u0120Infinite": 22380, "\u0120Twenty": 22381, "\u0120pedestrian": 22382, "\u0120jersey": 22383, "\u0120Fur": 22384, "\u0120Infinity": 22385, "\u0120Elliott": 22386, "\u0120mentor": 22387, "\u0120morally": 22388, "\u0120obey": 22389, "secure": 22390, "iffe": 22391, "\u0120antibiotics": 22392, "angled": 22393, "\u0120Freeman": 22394, "\u0120Introduction": 22395, "Jun": 22396, "\u0120marsh": 22397, "icans": 22398, "\u0120EVENTS": 22399, "ochond": 22400, "Wall": 22401, "iculty": 22402, "\u0120misdemeanor": 22403, "\u0120ly": 22404, "Thomas": 22405, "\u0120Resolution": 22406, "\u0120animations": 22407, "\u0120Dry": 22408, "\u0120intercourse": 22409, "\u0120Newcastle": 22410, "\u0120Hog": 22411, "\u0120Equipment": 22412, "177": 22413, "\u0120territorial": 22414, "\u0120archives": 22415, "203": 22416, "Filter": 22417, "\u0120Munich": 22418, "\u0120commanded": 22419, "\u0120Wand": 22420, "\u0120pitches": 22421, "\u0120Croat": 22422, "\u0120ratios": 22423, "\u0120Mits": 22424, "\u0120accumulated": 22425, "\u0120Specifically": 22426, "\u0120gentleman": 22427, "acerb": 22428, "\u0120penn": 22429, "\u0120aka": 22430, "\u0120Fuk": 22431, "\u0120intervene": 22432, "\u0120Refuge": 22433, "\u0120Alzheimer": 22434, "\u0120succession": 22435, "ohan": 22436, "does": 22437, "Lord": 22438, "\u0120separat": 22439, "\u0120correspondence": 22440, "\u0120shiny": 22441, "Prior": 22442, "\u0120sulf": 22443, "\u0120miserable": 22444, "\u0120dedication": 22445, "().": 22446, "\u0120specialists": 22447, "\u0120defects": 22448, "\u0120Cult": 22449, "\u0120Xia": 22450, "\u0120jeopard": 22451, "\u0120Ore": 22452, "Ability": 22453, "\u0120lear": 22454, "\u0120ambitions": 22455, "\u0120BMI": 22456, "\u0120Arabs": 22457, "\u01201942": 22458, "\u0120preservation": 22459, "ificate": 22460, "\u0120ashamed": 22461, "loss": 22462, "\u0120Restaur": 22463, "\u0120resemble": 22464, "\u0120enrich": 22465, "\u0120KN": 22466, "\u0120Clan": 22467, "float": 22468, "\u0120playable": 22469, "ITT": 22470, "\u0120harmony": 22471, "arrison": 22472, "\u0120Weinstein": 22473, "were": 22474, "\u0120poisoning": 22475, "\u0120Comput": 22476, "\u0120WordPress": 22477, "major": 22478, "\u0120Valve": 22479, "Fan": 22480, "\u0120Throw": 22481, "\u0120Romans": 22482, "\u0120Depression": 22483, "ados": 22484, "\u0120tortured": 22485, "\u0120balancing": 22486, "bottom": 22487, "\u0120acquiring": 22488, "\u0120Monte": 22489, "ardi": 22490, "\u0120aura": 22491, "\u0120##": 22492, "\u0120Standing": 22493, "\u0120Atlas": 22494, "CF": 22495, "\u0120intrins": 22496, "\u0120Benghazi": 22497, "\u0120camping": 22498, "\u0120tapped": 22499, "blade": 22500, "strous": 22501, "\u0120Rabb": 22502, "\u0120Written": 22503, "tip": 22504, "\u0120Neigh": 22505, "sterdam": 22506, "\u0120Allow": 22507, "\u0120Healing": 22508, "\u0120Rhod": 22509, "num": 22510, "\u0120caffeine": 22511, "\u0120Percent": 22512, "\u0120boo": 22513, "\u0120apples": 22514, "305": 22515, "\u0120welcoming": 22516, "\u0120applaud": 22517, "\u0120austerity": 22518, "\u00c2\u00b1": 22519, "\u0120Reality": 22520, "efe": 22521, "\u00e5\u00ae": 22522, "\u0120sucks": 22523, "\u0120tabs": 22524, "\u0120PayPal": 22525, "\u0120backpack": 22526, "\u0120gifted": 22527, "abulary": 22528, "\u0120Scout": 22529, "irteen": 22530, "\u0120chin": 22531, "\u0120omitted": 22532, "\u0120negatively": 22533, "\u0120accessing": 22534, "\u0120Earn": 22535, "\u0120ambulance": 22536, "\u0120headphones": 22537, "\u0120205": 22538, "\u0120Refresh": 22539, "president": 22540, "\u0120Kitchen": 22541, "\u0120Entered": 22542, "\u0120Snyder": 22543, "005": 22544, "omical": 22545, "\u0120borrowed": 22546, "\u0120Nem": 22547, "\u0120aviation": 22548, "\u0120stall": 22549, "rimination": 22550, "\u0120uniforms": 22551, "itime": 22552, "\u0120Simmons": 22553, "energy": 22554, "ablished": 22555, "yy": 22556, "qualified": 22557, "\u0120rallies": 22558, "\u0120Stuart": 22559, "flight": 22560, "\u0120gangs": 22561, "rag": 22562, "\u0120vault": 22563, "lux": 22564, "\u0120Compar": 22565, "\u0120designation": 22566, "209": 22567, "\u0120Jos": 22568, "dollar": 22569, "zero": 22570, "\u0120wells": 22571, "303": 22572, "\u0120constituents": 22573, "\u0120heck": 22574, "\u0120cows": 22575, "\u0120commanders": 22576, "\u0120differential": 22577, "\u0120Catherine": 22578, "299": 22579, "\u0120valve": 22580, "\u0120brace": 22581, "\u0120perspectives": 22582, "cert": 22583, "fact": 22584, "icularly": 22585, "\u0120McN": 22586, "planes": 22587, "\u0120intric": 22588, "\u0120peas": 22589, "ovan": 22590, "\u0120tossed": 22591, "retch": 22592, "\u0120Lopez": 22593, "\u0120unfamiliar": 22594, "death": 22595, "\u0120Apart": 22596, "\u0120Chang": 22597, "\u0120relieved": 22598, "rophe": 22599, "\u0120airports": 22600, "\u0120freak": 22601, "util": 22602, "Mill": 22603, "\u0120Chin": 22604, "\u0120Owen": 22605, "male": 22606, "\u0120Broken": 22607, "\u0120Winds": 22608, "rob": 22609, "rising": 22610, "\u0120firefighters": 22611, "\u0120authoritarian": 22612, "\u0120148": 22613, "Bitcoin": 22614, "external": 22615, "\u0120browsers": 22616, "ichever": 22617, "orian": 22618, "\u0120unb": 22619, "\u0120poke": 22620, "\u0120Zot": 22621, "Mid": 22622, "\u0120Popular": 22623, "\u0120covert": 22624, "\u0120contributes": 22625, "\u0120650": 22626, "\u0120contention": 22627, "Gate": 22628, "\u0120consoles": 22629, "\u0120chromos": 22630, "\u0120IX": 22631, "\u0120visually": 22632, "\u0120Eisen": 22633, "\u0120jewelry": 22634, "\u0120delegation": 22635, "\u0120accelerate": 22636, "\u0120Riley": 22637, "\u0120slope": 22638, "\u0120indoor": 22639, "itially": 22640, "\u0120hugely": 22641, "\u0120tunnels": 22642, "\u0120fined": 22643, "\u0120directive": 22644, "\u0120forehead": 22645, "ustomed": 22646, "\u0120skate": 22647, "Music": 22648, "gas": 22649, "\u0120recognizing": 22650, "ambo": 22651, "\u0120overweight": 22652, "\u0120Grade": 22653, "\u00d9\u012c": 22654, "\u0120sounding": 22655, "\u0120locking": 22656, "\u0120REM": 22657, "Store": 22658, "\u0120excav": 22659, "\u0120Likewise": 22660, "\u0120Lights": 22661, "\u0120elbow": 22662, "\u0120Supply": 22663, "wic": 22664, "\u0120handsome": 22665, "1994": 22666, "Coll": 22667, "\u0120adequately": 22668, "\u0120Associate": 22669, "\u0120strips": 22670, "\u0120crackdown": 22671, "\u0120marvel": 22672, "\u0120Kun": 22673, "\u0120passages": 22674, "@@@@": 22675, "\u0120Tall": 22676, "\u0120thoughtful": 22677, "namese": 22678, "\u0120prostitution": 22679, "business": 22680, "\u0120ballistic": 22681, "personal": 22682, "cig": 22683, "izational": 22684, "Round": 22685, "\u0120\u00c2\u0142\u0120\u00c2\u0142\u0120\u00c2\u0142\u0120\u00c2\u0142": 22686, "\u0120Coleman": 22687, "\u0120admitting": 22688, "\u0120Plug": 22689, "\u0120bitcoins": 22690, "\u0120Suz": 22691, "\u0120fairness": 22692, "\u0120supplier": 22693, "\u0120catastrophic": 22694, "\u0120Helen": 22695, "oqu": 22696, "Marc": 22697, "\u0120Articles": 22698, "gie": 22699, "\u0120endangered": 22700, "\u0120destiny": 22701, "\u0120Volt": 22702, "olia": 22703, "axis": 22704, "\u0120cheat": 22705, "\u0120unified": 22706, "ICO": 22707, "quote": 22708, "302": 22709, "\u0120Sed": 22710, "\u0120suppression": 22711, "\u0120analyzing": 22712, "\u0120squat": 22713, "\u0120figuring": 22714, "\u0120coordinates": 22715, "\u0120chunks": 22716, "\u01201946": 22717, "\u0120subp": 22718, "\u0120wiki": 22719, "\u0120Forbes": 22720, "\u0120Jupiter": 22721, "\u0120Erik": 22722, "imer": 22723, "\u0120Commercial": 22724, "\\)": 22725, "\u0120legitimacy": 22726, "\u0120dental": 22727, "\u0120Mean": 22728, "\u0120deficits": 22729, "550": 22730, "Originally": 22731, "\u0120Horror": 22732, "\u0120contamination": 22733, "llah": 22734, "\u0120confisc": 22735, "\u0120Clare": 22736, "TB": 22737, "\u0120Failed": 22738, "aned": 22739, "\u0120ruler": 22740, "\u0120Controller": 22741, "\u0120feminists": 22742, "Fix": 22743, "gay": 22744, "207": 22745, "\u0120rabbit": 22746, "Third": 22747, "owntown": 22748, "\u0120glue": 22749, "\u0120volatile": 22750, "\u0120shining": 22751, "\u0120foll": 22752, "\u0120impaired": 22753, "\u0120supers": 22754, "\u00e6\u012a": 22755, "\u0120clutch": 22756, "\u013c\u00e9\u0128\u0134": 22757, "\u0120prolet": 22758, "\u0120(!": 22759, "\u0120yelled": 22760, "\u0120Kiev": 22761, "\u0120Ern": 22762, "\u0120Shock": 22763, "KB": 22764, "\u0120situated": 22765, "query": 22766, "\u0120Nas": 22767, "\u0120annex": 22768, "character": 22769, "\u0120Holiday": 22770, "\u0120automation": 22771, "\u0120Jill": 22772, "\u0120Remastered": 22773, "\u0120linem": 22774, "\u0120wilderness": 22775, "\u0120Horizon": 22776, "\u0120Guinea": 22777, "AZ": 22778, "\u0120mainland": 22779, "\u0120secrecy": 22780, "LEASE": 22781, "\u0120punk": 22782, "\u0120Province": 22783, "(),": 22784, "Speed": 22785, "\u0120handing": 22786, "\u0120Sebast": 22787, "Sir": 22788, "rase": 22789, "\u0120journals": 22790, "\u0120congest": 22791, "\u0120Tut": 22792, "irrel": 22793, "\u0120schizophrenia": 22794, "\u0120misogyn": 22795, "healthy": 22796, "Iron": 22797, "\u0120reacted": 22798, "-$": 22799, "252": 22800, "\u0120plural": 22801, "\u0120plum": 22802, "\u0120bargain": 22803, "\u0120grounded": 22804, "finder": 22805, "\u0120disse": 22806, "\u0120Laz": 22807, "OOD": 22808, "\u0120atroc": 22809, "Factory": 22810, "\u0120minions": 22811, "\u0120ori": 22812, "\u0120Brave": 22813, "\u0120PRE": 22814, "\u0120Myanmar": 22815, "\u0120Hod": 22816, "\u0120expedition": 22817, "\u0120explode": 22818, "\u0120Coord": 22819, "\u0120extr": 22820, "\u0120Brief": 22821, "\u0120ADHD": 22822, "\u0120hardcore": 22823, "feeding": 22824, "\u0120dile": 22825, "\u0120Fruit": 22826, "\u0120vaccination": 22827, "\u0120Mao": 22828, "osphere": 22829, "\u0120contests": 22830, "-|": 22831, "\u0120fren": 22832, "isphere": 22833, "Rom": 22834, "\u0120Sharp": 22835, "\u0120Trend": 22836, "\u0120disconnect": 22837, "\u00e2\u0122\u00a2\u00e2\u0122\u00a2": 22838, "\u0120persecution": 22839, "Earth": 22840, "\u0120healthier": 22841, "384": 22842, "\u0120cob": 22843, "\u0120Trinity": 22844, "OWS": 22845, "ANN": 22846, "\u0120specialty": 22847, "\u0120gru": 22848, "\u0120cooperative": 22849, "why": 22850, "Starting": 22851, "\u0120Issues": 22852, "stre": 22853, "ensor": 22854, "\u0120185": 22855, "Adv": 22856, "!?": 22857, "\u0120Revel": 22858, "emia": 22859, "\u0120Hulk": 22860, "\u0120celebrations": 22861, "\u0120Sou": 22862, "raud": 22863, "\u0120Klein": 22864, "\u0120unreal": 22865, "context": 22866, "\u0120partnerships": 22867, "\u0120adopting": 22868, "tical": 22869, "\u0120splash": 22870, "\u0120Hezbollah": 22871, "category": 22872, "cyclop": 22873, "xton": 22874, "\u0120Dot": 22875, "urdy": 22876, "tz": 22877, "\u0120envelope": 22878, "\u0120NL": 22879, "\u00e2\u0137": 22880, "\u0120wherein": 22881, "Spec": 22882, "184": 22883, "\u0120telev": 22884, "aliation": 22885, "\u0120myths": 22886, "\u00e5\u00b0": 22887, "\u0120rigorous": 22888, "\u0120communicating": 22889, "\u0120observer": 22890, "\u0120rehe": 22891, "\u0120Wash": 22892, "\u0120apologized": 22893, "\u0120Tin": 22894, "\u0120expenditures": 22895, "workers": 22896, "document": 22897, "\u0120hesitate": 22898, "\u0120Lenin": 22899, "\u0120unpredictable": 22900, "\u0120renewal": 22901, "cler": 22902, "okia": 22903, "\u0120CONT": 22904, "\u0120postseason": 22905, "Tokens": 22906, "\u0120exacerb": 22907, "\u0120betting": 22908, "\u0120147": 22909, "\u0120elevation": 22910, "Wood": 22911, "\u0120Solomon": 22912, "194": 22913, "004": 22914, "output": 22915, "\u0120redund": 22916, "\u0120Mumbai": 22917, "\u0120pH": 22918, "\u0120reproduce": 22919, "\u0120Duration": 22920, "MAX": 22921, "\u0120bog": 22922, "CBS": 22923, "\u0120Balance": 22924, "\u0120Sgt": 22925, "\u0120Recent": 22926, "\u0120cd": 22927, "\u0120popped": 22928, "\u0120incompet": 22929, "prop": 22930, "ayan": 22931, "guy": 22932, "Pacific": 22933, "\u0120tyr": 22934, "\u0120{{": 22935, "\u0120Mystic": 22936, "\u0120Dana": 22937, "\u0120masturb": 22938, "\u0120geometry": 22939, "\u00c3\u00a2": 22940, "\u0120Correct": 22941, "\u0120trajectory": 22942, "\u0120distracted": 22943, "\u0120foo": 22944, "\u0120Welsh": 22945, "Luc": 22946, "mith": 22947, "\u0120rugby": 22948, "\u0120respiratory": 22949, "\u0120triangle": 22950, "\u0120215": 22951, "\u0120undergraduate": 22952, "\u0120Superior": 22953, "changing": 22954, "_-": 22955, "\u0120rightly": 22956, "\u0120referee": 22957, "\u0120lucrative": 22958, "\u0120unauthorized": 22959, "\u0120resembles": 22960, "\u0120GNU": 22961, "\u0120Derby": 22962, "\u0120pathways": 22963, "\u0120Led": 22964, "\u0120endurance": 22965, "\u0120stint": 22966, "\u0120collector": 22967, "Fast": 22968, "\u0120dots": 22969, "\u0120nationals": 22970, "\u0120Securities": 22971, "\u0120whip": 22972, "Param": 22973, "\u0120learns": 22974, "Magic": 22975, "\u0120detailing": 22976, "moon": 22977, "\u0120broadcasting": 22978, "\u0120baked": 22979, "265": 22980, "holm": 22981, "\u0120Sah": 22982, "\u0120Hussein": 22983, "\u0120Courtesy": 22984, "174": 22985, "\u0120146": 22986, "\u0120geographic": 22987, "peace": 22988, "\u0120judging": 22989, "\u0120Stern": 22990, "Bur": 22991, "\u0120storyline": 22992, "Gun": 22993, "\u0120Stick": 22994, "245": 22995, "307": 22996, "\u00e3\u0124\u00b4\u00e3\u0125\u00b3": 22997, "\u0120Administrator": 22998, "\u0120burnt": 22999, "\u0120pave": 23000, "choes": 23001, "Exec": 23002, "\u0120campuses": 23003, "Result": 23004, "\u0120mutations": 23005, "\u0120Charter": 23006, "\u0120captures": 23007, "\u0120compares": 23008, "\u0120badge": 23009, "Scient": 23010, "\u0120erad": 23011, "iery": 23012, "oi": 23013, "ettes": 23014, "\u0120Estate": 23015, "\u0120strap": 23016, "\u0120proudly": 23017, "\u0120fried": 23018, "\u0120withdrawn": 23019, "\u0120Voy": 23020, "phony": 23021, "Items": 23022, "\u0120Pierce": 23023, "bard": 23024, "\u0120annotation": 23025, "anton": 23026, "illon": 23027, "Impro": 23028, "...)": 23029, "\u0120happier": 23030, "------": 23031, "adjust": 23032, "\u0120staffers": 23033, "\u0120activism": 23034, "\u0120perf": 23035, "\u0120alright": 23036, "Need": 23037, "\u0120commence": 23038, "\u0120opioid": 23039, "\u0120Amanda": 23040, "Es": 23041, "\u0120Pars": 23042, "\u0120Kaw": 23043, "Works": 23044, "248": 23045, "\u0120indo": 23046, "tc": 23047, "endant": 23048, "\u0120Moto": 23049, "\u0120legalization": 23050, "OTE": 23051, "\u0120tasked": 23052, "\u0120tsp": 23053, "\u0120ACTIONS": 23054, "166": 23055, "\u0120refreshing": 23056, "\u0120NR": 23057, "\u0120Perez": 23058, "\u0120infringement": 23059, "SY": 23060, "Listen": 23061, "inning": 23062, "ku": 23063, "\u0120rotate": 23064, "program": 23065, "arah": 23066, "Design": 23067, "\u0120(\u00c2\u00a3": 23068, "\u0120storing": 23069, "\u0120warrants": 23070, "\u0120judgement": 23071, "\u0120Brist": 23072, "usually": 23073, "photo": 23074, "\u0120Ran": 23075, "\u0120Pine": 23076, "\u0120outrageous": 23077, "\u0120Valentine": 23078, "luence": 23079, "\u0120Everybody": 23080, "Altern": 23081, "\u0120relevance": 23082, "\u0120terminated": 23083, "\u0120dessert": 23084, "\u0120fulfilled": 23085, "\u0120prosecuted": 23086, "\u0120Words": 23087, "\u0120migrant": 23088, "\u0120cultivation": 23089, "\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124": 23090, "idelity": 23091, "\u0120Vern": 23092, "\u0120Login": 23093, "\u0120metaphor": 23094, "\u0120Tip": 23095, "\u0120recruits": 23096, "\u0120Pig": 23097, "ribing": 23098, "\u0120enthusiasts": 23099, "exper": 23100, "\u0120frightening": 23101, "\u0120Hair": 23102, "anson": 23103, "strate": 23104, "\u0120hi": 23105, "Height": 23106, "\u0120owning": 23107, "none": 23108, "\u0120dislike": 23109, "\u0120knives": 23110, "pherd": 23111, "\u0120loudly": 23112, "\u0120APIs": 23113, "Display": 23114, "\u0120Lac": 23115, "\u0120USS": 23116, "abl": 23117, "verages": 23118, "Jew": 23119, "\u0120172": 23120, "\u0120Historical": 23121, "atoon": 23122, "\u0120Physics": 23123, "intern": 23124, "\u0120warmth": 23125, "\u0120topp": 23126, "DM": 23127, "\u0120gunman": 23128, "\u0120emperor": 23129, "odi": 23130, "\u00e3\u0125\u00a3": 23131, "inatory": 23132, "\u0120Rib": 23133, "\u0120131": 23134, "\u0120Saturn": 23135, "\u0120Shining": 23136, "\u0120waking": 23137, "Quotes": 23138, "\u0120comedian": 23139, "enberg": 23140, "\u00c2\u00bd": 23141, "\u0120believers": 23142, "\u0120paperwork": 23143, "custom": 23144, "\u0120lev": 23145, "\u0120lament": 23146, "\u0120pouring": 23147, "222": 23148, "political": 23149, "\u0120Supplement": 23150, "maid": 23151, "\u0120cruelty": 23152, "\u0120tread": 23153, "ysics": 23154, "Aw": 23155, "rites": 23156, "\u0120modifier": 23157, "\u0120Position": 23158, "Adam": 23159, "lb": 23160, "ubs": 23161, "\u0120imperfect": 23162, "\u0120clusters": 23163, "\u0120Engineer": 23164, "\u0120Cherry": 23165, "\u0120inauguration": 23166, "\u0120Sau": 23167, "\u0120embodiment": 23168, "\u0120Uncle": 23169, "\u0120overr": 23170, "\u0120explosions": 23171, "cule": 23172, "\u0120Princeton": 23173, "\u0120Andrea": 23174, "\u0120incorrectly": 23175, "\u0120earnest": 23176, "\u0120pilgr": 23177, "\u0120Sprint": 23178, "\u0120sleeve": 23179, "\u0120hears": 23180, "\u0120Amazing": 23181, "\u0120browsing": 23182, "agin": 23183, "\u0120homeland": 23184, "\u0120haw": 23185, "\u0120diving": 23186, "istered": 23187, "178": 23188, "\u0120bargaining": 23189, "\u0120Arcade": 23190, "\u0120delegate": 23191, "terson": 23192, "................................................................": 23193, "\u0120Jacksonville": 23194, "275": 23195, "\u0120stagn": 23196, "\u0120adam": 23197, "\u0120Sherman": 23198, "CB": 23199, "\u0120suburb": 23200, "\u0120Foods": 23201, "\u0120converting": 23202, "\u0120Arist": 23203, "\u0120chambers": 23204, "love": 23205, "\u0120amino": 23206, "\u0120Gan": 23207, "\u0120madness": 23208, "mc": 23209, "\u0120USE": 23210, "defined": 23211, "\u0120ultr": 23212, "indust": 23213, "\u0120wolves": 23214, "lance": 23215, "Additionally": 23216, "\u0120cracks": 23217, "asia": 23218, "\u0120Reason": 23219, "\u0120Pump": 23220, "\u0120accidental": 23221, "\u0120Laser": 23222, "\u0120Rid": 23223, "\u0120initialized": 23224, "elli": 23225, "\u0120unnamed": 23226, "\u0120noun": 23227, "\u0120Passed": 23228, "\u0120hostage": 23229, "\u0120Ethiop": 23230, "shirts": 23231, "\u0120unrel": 23232, "\u0120Embassy": 23233, "\u01201941": 23234, "\u0120atoms": 23235, "\u0120purported": 23236, "164": 23237, "\u0120Fi": 23238, "\u0120gallons": 23239, "\u0120Monica": 23240, "\u0120pg": 23241, "enment": 23242, "\u0120sorted": 23243, "\u0120Gospel": 23244, "\u0120heights": 23245, "\u0120traced": 23246, "\u0120undergoing": 23247, "Shell": 23248, "\u0120sacks": 23249, "\u0120proportions": 23250, "\u0120halluc": 23251, "Font": 23252, "acet": 23253, "\u0120warmer": 23254, "\u0120INTER": 23255, "\u0120grabbing": 23256, "Plug": 23257, "\u0120realization": 23258, "\u0120Burke": 23259, "\u0120enchant": 23260, "ATER": 23261, "\u0120Seed": 23262, "\u0120abundant": 23263, "FM": 23264, "\u0120civic": 23265, "Vs": 23266, "isi": 23267, "\u0120vow": 23268, "\u0120reper": 23269, "\u0120Partnership": 23270, "\u0120penetration": 23271, "\u0120axe": 23272, "\u0120shattered": 23273, "\u0120Zombies": 23274, "\u0120vinyl": 23275, "\u0120Alert": 23276, "eon": 23277, "\u0120obliged": 23278, "\u0120Illust": 23279, "\u0120Plaza": 23280, "\u0120Frontier": 23281, "\u0120davidjl": 23282, "\u0120Serial": 23283, "\u0120Hav": 23284, "\u0120Nutrition": 23285, "Bi": 23286, "\u0120\u00e2\u0138\u012a": 23287, "\u0120Jays": 23288, "linux": 23289, "\u0120hurry": 23290, "\u0120voy": 23291, "\u0120hopeless": 23292, "\u0120Stealth": 23293, "\u0120\u00e3\u0123": 23294, "essors": 23295, "ttle": 23296, "borg": 23297, "\u0120Safari": 23298, "fell": 23299, "\u0120wary": 23300, "due": 23301, "\u0120Above": 23302, "Ha": 23303, "ELL": 23304, "\u0120notor": 23305, "\u0120Won": 23306, "Too": 23307, "\u0120occupations": 23308, "\u0120possessions": 23309, "\u0120inviting": 23310, "\u0120predators": 23311, "\u0120accelerated": 23312, "\u0120157": 23313, "uterte": 23314, "\u0120Cube": 23315, "east": 23316, "account": 23317, "Give": 23318, "\u0120transplant": 23319, "redients": 23320, "idable": 23321, "\u0120screenshots": 23322, "\u0120Gund": 23323, "\u0120FS": 23324, "\u0120travelers": 23325, "\u0120sensory": 23326, "\u0120Fiat": 23327, "\u0120Rockets": 23328, "\u0130\u012d": 23329, "_{": 23330, "Friend": 23331, "\u0120charming": 23332, "ALS": 23333, "\u0120enjoyment": 23334, "mph": 23335, "\u01205000": 23336, "\u0120REG": 23337, "\u00d9\u0128": 23338, "bia": 23339, "\u0120compilation": 23340, "rost": 23341, "\u0120VP": 23342, "\u0120Schne": 23343, "2019": 23344, "\u0120copying": 23345, "MORE": 23346, "\u0120Flore": 23347, "falls": 23348, "215": 23349, "total": 23350, "\u0120disciples": 23351, "double": 23352, "\u0120exceeding": 23353, "\u0120smashed": 23354, "\u0120conceptual": 23355, "\u0120Romania": 23356, "\u0120Brent": 23357, "\u0120ICE": 23358, "\u0120Tou": 23359, "\u0120grap": 23360, "\u0120nails": 23361, "189": 23362, "\u00e3\u0125\u013a": 23363, "\u0120procure": 23364, "eur": 23365, "\u0120confirming": 23366, "\u0120Cec": 23367, "awi": 23368, "\u0120Eden": 23369, "\u0120ng": 23370, "\u0120engineered": 23371, "atics": 23372, "\u0120hooked": 23373, "\u0120disgusting": 23374, "\u0120Murder": 23375, "\u00e3\u0124\u00bf": 23376, "Library": 23377, "\u0120168": 23378, "Almost": 23379, "hematic": 23380, "Menu": 23381, "\u0120Notre": 23382, "\u0120Jur": 23383, "\u0120kidnapped": 23384, "\u0120hacker": 23385, "\u0120Jade": 23386, "\u0120creepy": 23387, "\u0120drawings": 23388, "\u0120Sponsor": 23389, "\u0120cyclists": 23390, "\u0120Goblin": 23391, "\u0120optimized": 23392, "\u0120staged": 23393, "\u0120McD": 23394, "between": 23395, "Age": 23396, "eno": 23397, "Sex": 23398, "\u0120Wide": 23399, "nings": 23400, "avis": 23401, "\u0120incapable": 23402, "\u0120Kob": 23403, "\u0120rewarding": 23404, "\u0120Lone": 23405, "olescent": 23406, "\u0120contracted": 23407, "\u0120sticky": 23408, "Jose": 23409, "Ball": 23410, "fest": 23411, "\u0120Input": 23412, "\u0120Recently": 23413, "\u0120tomat": 23414, "square": 23415, "Application": 23416, "\u0120nitrogen": 23417, "\u0120duplicate": 23418, "\u0120Recon": 23419, "\u0120Dear": 23420, "London": 23421, "\u0120intra": 23422, "\u0120dock": 23423, "\u0120outreach": 23424, "\u0120Million": 23425, "\u0120mammals": 23426, "ampton": 23427, "VAL": 23428, "\u0120snaps": 23429, "\u0120dos": 23430, "\u0120Whole": 23431, "\u0120Ready": 23432, "Try": 23433, "\u0120Winnipeg": 23434, "earance": 23435, "\u0120incurred": 23436, "renched": 23437, "\u0120NSW": 23438, "ilot": 23439, "raine": 23440, "\u0120cube": 23441, "got": 23442, "\u0120runway": 23443, "etermined": 23444, "\u0120Hawks": 23445, "\u0120survivor": 23446, "\u0120Wish": 23447, "\u0120Din": 23448, "\u0120DEF": 23449, "\u0120Vault": 23450, "187": 23451, "\u0120mushrooms": 23452, "\u0120crisp": 23453, "bey": 23454, "\u0120Discovery": 23455, "\u0120developmental": 23456, "\u0120paradigm": 23457, "\u0120chaotic": 23458, "\u0120Tsu": 23459, "\u0120333": 23460, "bons": 23461, "\u0120bacterial": 23462, "\u0120commits": 23463, "\u0120cosmic": 23464, "\u0120mega": 23465, "ocative": 23466, "\u0120Paint": 23467, "ophobic": 23468, "\u0120vain": 23469, "\u0120carved": 23470, "\u0120Thief": 23471, "\u0120Gul": 23472, "owship": 23473, "\u0120cites": 23474, "\u0120Edinburgh": 23475, "\u0120diminished": 23476, "\u0120acknowledges": 23477, "\u0120Kills": 23478, "\u0120microw": 23479, "\u0120Hera": 23480, "\u0120seniors": 23481, "\u0120whereby": 23482, "Hop": 23483, "atron": 23484, "\u0120unavailable": 23485, "\u0120Nate": 23486, "\u0120480": 23487, "\u0120slated": 23488, "\u0120Rebecca": 23489, "\u0120Battery": 23490, "\u0120grammar": 23491, "\u0120headset": 23492, "\u0120cursor": 23493, "\u0120excluding": 23494, "anye": 23495, "aundering": 23496, "ebin": 23497, "\u0120feasible": 23498, "\u0120Publishing": 23499, "\u0120Labs": 23500, "\u0120Cliff": 23501, "\u0120Ferrari": 23502, "\u0120pac": 23503, "visible": 23504, "marked": 23505, "pell": 23506, "\u0120polite": 23507, "\u0120staggering": 23508, "\u0120Galactic": 23509, "\u0120superst": 23510, "\u0120paran": 23511, "\u0120Officers": 23512, "\u00e3\u0122\u0123": 23513, "\u0120specifics": 23514, "ulus": 23515, "239": 23516, "\u0120Paste": 23517, "AMP": 23518, "\u0120Panama": 23519, "\u0120Delete": 23520, "anguard": 23521, "restrial": 23522, "\u0120heroic": 23523, "\u0120Dy": 23524, "\u00d8\u00a7\u00d9\u0126": 23525, "\u0120incumbent": 23526, "\u0120crunch": 23527, "tro": 23528, "\u0120scoop": 23529, "\u0120blogger": 23530, "\u0120sellers": 23531, "uren": 23532, "\u0120medicines": 23533, "\u0120Caps": 23534, "\u0120Animation": 23535, "oxy": 23536, "\u0120outward": 23537, "\u0120inquiries": 23538, "229": 23539, "\u0120psychologist": 23540, "\u0120Sask": 23541, "evil": 23542, "\u0120contaminated": 23543, "\u00e3\u0124\u00a8": 23544, "herence": 23545, "\u0120branded": 23546, "\u0120Abdul": 23547, "zh": 23548, "\u0120paragraphs": 23549, "\u0120mins": 23550, "\u0120correlated": 23551, "erb": 23552, "\u0120impart": 23553, "\u0120milestone": 23554, "\u0120Solutions": 23555, "otle": 23556, "\u0120undercover": 23557, "\u0120marched": 23558, "\u0120Chargers": 23559, "fax": 23560, "\u0120Secrets": 23561, "\u0120ruth": 23562, "weather": 23563, "\u0120feminine": 23564, "\u0120sham": 23565, "\u0120prestigious": 23566, "iggins": 23567, "\u0120sung": 23568, "history": 23569, "ettle": 23570, "ggie": 23571, "\u0120outdated": 23572, "oland": 23573, "\u0120perceptions": 23574, "\u0120Session": 23575, "\u0120Dodgers": 23576, "uj": 23577, "\u0120END": 23578, "Doc": 23579, "\u0120deficiency": 23580, "Grand": 23581, "\u0120Joker": 23582, "\u0120retrospect": 23583, "\u0120diagnostic": 23584, "\u0120harmless": 23585, "\u0120rogue": 23586, "\u0120Aval": 23587, "Equ": 23588, "\u0120transc": 23589, "\u0120Robertson": 23590, "\u0120Depending": 23591, "\u0120Burns": 23592, "ivo": 23593, "\u0120hostility": 23594, "Features": 23595, "\u0135\u013a": 23596, "\u0120discomfort": 23597, "\u0120LCD": 23598, "specified": 23599, "\u0120Expect": 23600, "340": 23601, "\u0120imperative": 23602, "\u0120Regular": 23603, "Chinese": 23604, "\u0120statewide": 23605, "\u0120symm": 23606, "\u0120loops": 23607, "\u0120autumn": 23608, "Nick": 23609, "\u0120shaping": 23610, "\u0120quot": 23611, "\u0120cherry": 23612, "\u0120Crossref": 23613, "\u00e8\u00a6\u013c\u00e9\u0128\u0134": 23614, "Standard": 23615, "heed": 23616, "\u0120Dell": 23617, "\u0120Vietnamese": 23618, "\u0120ost": 23619, "\u0120Valkyrie": 23620, "OA": 23621, "Assad": 23622, "\u0120rebound": 23623, "\u0120Traffic": 23624, "places": 23625, "\u00e6\u013a": 23626, "\u0120Buc": 23627, "172": 23628, "\u0120shelters": 23629, "\u0120insisting": 23630, "\u0120Certainly": 23631, "\u0120Kenneth": 23632, "\u0120TCP": 23633, "\u0120penal": 23634, "\u0120Replay": 23635, "heard": 23636, "\u0120dialect": 23637, "iza": 23638, "\u0120FY": 23639, "itcher": 23640, "\u0120DL": 23641, "\u0120spiral": 23642, "\u0120quarterbacks": 23643, "\u0120hull": 23644, "\u0120google": 23645, "\u0120todd": 23646, "\u0120Sterling": 23647, "\u0120Plate": 23648, "\u0120spying": 23649, "mbol": 23650, "\u0120Realm": 23651, "\u0120Proced": 23652, "\u0120Crash": 23653, "\u0120terminate": 23654, "\u0120protesting": 23655, "Center": 23656, "guided": 23657, "\u0120uncover": 23658, "\u0120boycott": 23659, "\u0120realizes": 23660, "sound": 23661, "\u0120pretending": 23662, "\u0120Vas": 23663, "1980": 23664, "\u0120framed": 23665, "\u0120139": 23666, "\u0120descended": 23667, "\u0120rehabilitation": 23668, "\u0120borrowing": 23669, "\u0120Buch": 23670, "\u0120blur": 23671, "Ron": 23672, "\u0120Frozen": 23673, "enza": 23674, "Chief": 23675, "\u0120Poor": 23676, "\u0120translates": 23677, "MIN": 23678, "\u0120212": 23679, "JECT": 23680, "\u0120erupted": 23681, "\u0120successes": 23682, "SEC": 23683, "\u0120plague": 23684, "\u0120gems": 23685, "doms": 23686, "\u0120stretches": 23687, "\u0120Spy": 23688, "\u0120storytelling": 23689, "Credit": 23690, "\u0120Push": 23691, "\u0120traction": 23692, "\u0120ineffective": 23693, "\u0120Luna": 23694, "\u0120tapes": 23695, "\u0120analytics": 23696, "ercise": 23697, "\u0120programmes": 23698, "\u0120Carbon": 23699, "\u0120behold": 23700, "heavy": 23701, "\u0120Conservation": 23702, "\u0120FIR": 23703, "\u0120sack": 23704, "termin": 23705, "ricks": 23706, "\u0120housed": 23707, "\u0120unusually": 23708, "Ice": 23709, "\u0120executing": 23710, "\u0120Moroc": 23711, "eday": 23712, "\u0120editions": 23713, "\u0120smarter": 23714, "\u0120BA": 23715, "\u0120outlaw": 23716, "\u0120vanished": 23717, "iba": 23718, "ALSE": 23719, "\u0120Silva": 23720, "238": 23721, "Could": 23722, "\u0120philosopher": 23723, "\u0120evacuated": 23724, "Secret": 23725, "142": 23726, "\u0120visas": 23727, "\u00e3\u0124\u00ac": 23728, "\u0120Malt": 23729, "\u0120Clearly": 23730, "\u0120Niger": 23731, "\u0120Cairo": 23732, "\u0120Fist": 23733, "380": 23734, "\u0120XML": 23735, "auto": 23736, "itant": 23737, "\u0120reinforced": 23738, "Record": 23739, "\u0120Survivor": 23740, "GHz": 23741, "\u0120screws": 23742, "parents": 23743, "\u0120oceans": 23744, "mares": 23745, "\u0120brakes": 23746, "vasive": 23747, "\u0120hello": 23748, "\u0120SIM": 23749, "rimp": 23750, "\u0120ore": 23751, "\u0120Armour": 23752, "247": 23753, "\u0120terrific": 23754, "\u0120tones": 23755, "141": 23756, "\u0120Minutes": 23757, "Episode": 23758, "\u0120curves": 23759, "\u0120inflammatory": 23760, "\u0120batting": 23761, "\u0120Beautiful": 23762, "Lay": 23763, "\u0120unpop": 23764, "vable": 23765, "\u0120riots": 23766, "\u0120Tactics": 23767, "baugh": 23768, "\u0120Cock": 23769, "\u0120orgasm": 23770, "\u0120Sas": 23771, "\u0120constructor": 23772, "etz": 23773, "Gov": 23774, "\u0120antagon": 23775, "\u0120theat": 23776, "\u0120deeds": 23777, "hao": 23778, "cuts": 23779, "\u0120McCl": 23780, "\u0120um": 23781, "\u0120Scientists": 23782, "\u0120grassroots": 23783, "yssey": 23784, "\"]=>": 23785, "\u0120surfaced": 23786, "\u0120shades": 23787, "\u0120neighbours": 23788, "\u0120advertis": 23789, "oya": 23790, "\u0120merged": 23791, "Upon": 23792, "\u0120gad": 23793, "\u0120anticipate": 23794, "Anyway": 23795, "\u0120slogan": 23796, "\u0120disrespect": 23797, "Iran": 23798, "\u0120TB": 23799, "acted": 23800, "\u0120subpoen": 23801, "mediately": 23802, "OOOO": 23803, "\u0120waiver": 23804, "\u0120vulnerabilities": 23805, "ottesville": 23806, "\u0120Huffington": 23807, "Josh": 23808, "\u0120DH": 23809, "Monday": 23810, "\u0120Ellen": 23811, "Know": 23812, "xon": 23813, "items": 23814, "228": 23815, "\u0120fills": 23816, "\u0120Nike": 23817, "\u0120cumulative": 23818, "andals": 23819, "Ir": 23820, "\u0120\u00ec": 23821, "\u0120friction": 23822, "igator": 23823, "\u0120scans": 23824, "\u0120Vienna": 23825, "ldom": 23826, "\u0120performers": 23827, "Prim": 23828, "\u0120bidding": 23829, "Mur": 23830, "\u0120leaned": 23831, "\u0120Prix": 23832, "alks": 23833, "\u0120[\u00e2\u0122\u00a6]": 23834, "\u0120Twitch": 23835, "\u0120Developer": 23836, "\u0120Gir": 23837, "\u0120callback": 23838, "Abstract": 23839, "\u0120accustomed": 23840, "\u0120freedoms": 23841, "\u0120PG": 23842, "uracy": 23843, "\u0120lump": 23844, "isman": 23845, ",,,,": 23846, "1992": 23847, "\u0120RED": 23848, "\u0120worm": 23849, "Match": 23850, "\u0120Platinum": 23851, "IJ": 23852, "\u0120Owner": 23853, "Trivia": 23854, "compl": 23855, "\u0120newborn": 23856, "\u0120fantas": 23857, "Own": 23858, "\u01201959": 23859, "\u0120sympath": 23860, "\u0120ubiqu": 23861, "\u0120outputs": 23862, "\u0120allev": 23863, "\u0120prag": 23864, "Kevin": 23865, "\u0120favors": 23866, "\u0120burial": 23867, "\u0120nurt": 23868, "solete": 23869, "cache": 23870, "\u0120156": 23871, "\u0120unlocks": 23872, "techn": 23873, "Making": 23874, "\u0120conquer": 23875, "adic": 23876, "\u00e6\u0138": 23877, "\u0120elf": 23878, "\u0120electorate": 23879, "\u0120Kurds": 23880, "\u0120Stack": 23881, "\u0120Samurai": 23882, "\u0120\u00e2\u013a\u0127": 23883, "\u0120{}": 23884, "\u0120Said": 23885, "\u0120Fallout": 23886, "\u0120kindness": 23887, "\u0120Customs": 23888, "\u0120Boulevard": 23889, "\u0120helicopters": 23890, "otics": 23891, "\u0120Veget": 23892, "comment": 23893, "\u0120criticised": 23894, "\u0120polished": 23895, "\u0120Remix": 23896, "\u0120Cultural": 23897, "\u0120recons": 23898, "\u0120doi": 23899, "atem": 23900, "Screen": 23901, "\u0120barred": 23902, "Comments": 23903, "\u0120Generally": 23904, "\u0120slap": 23905, "720": 23906, "Vari": 23907, "pine": 23908, "\u0120empt": 23909, "\u0120hats": 23910, "\u0120Playing": 23911, "lab": 23912, "average": 23913, "forms": 23914, "\u0120Cotton": 23915, "\u0120cans": 23916, "\u0120DON": 23917, "\u0120Somalia": 23918, "Crypt": 23919, "\u0120Increases": 23920, "Ever": 23921, "modern": 23922, "\u0120surgeon": 23923, "3000": 23924, "\u0120randomized": 23925, "================================================================": 23926, "Bern": 23927, "impl": 23928, "\u0120COR": 23929, "\u0120proclaim": 23930, "thouse": 23931, "\u0120toes": 23932, "\u0120ample": 23933, "\u0120preserving": 23934, "\u0120disbel": 23935, "grand": 23936, "Besides": 23937, "\u0120silk": 23938, "\u0120Pattern": 23939, "hm": 23940, "\u0120enterprises": 23941, "\u0120affidavit": 23942, "\u0120Advisory": 23943, "\u0120advertised": 23944, "\u0120Religious": 23945, "sections": 23946, "psych": 23947, "\u0120Fields": 23948, "aways": 23949, "\u0120hashtag": 23950, "\u0120Nightmare": 23951, "\u0120vampire": 23952, "\u0120forensic": 23953, "rossover": 23954, "nar": 23955, "\u0120navy": 23956, "\u0120vacant": 23957, "\u0120Duel": 23958, "\u0120hallway": 23959, "\u0120facebook": 23960, "identally": 23961, "\u0120NRA": 23962, "\u0120matt": 23963, "\u0120hurricane": 23964, "\u0120Kirby": 23965, "\u0120Puzzle": 23966, "\u0120skirt": 23967, "oust": 23968, "dullah": 23969, "\u0120analogy": 23970, "inion": 23971, "\u0120tomatoes": 23972, "\u0120NV": 23973, "\u0120Peak": 23974, "\u0120Meyer": 23975, "\u0120appointments": 23976, "\u0120masc": 23977, "\u0120alley": 23978, "rehend": 23979, "\u0120charities": 23980, "\u0120undo": 23981, "\u0120destinations": 23982, "\u0120Testing": 23983, "\">\"": 24618, "cats": 24619, "*.": 24620, "\u0120gestures": 24621, "general": 24622, "League": 24623, "\u0120packets": 24624, "\u0120Inspector": 24625, "\u0120Berg": 24626, "\u0120fraudulent": 24627, "\u0120criticize": 24628, "Fun": 24629, "\u0120blaming": 24630, "ndra": 24631, "\u0120slash": 24632, "\u0120Eston": 24633, "\u0120proposing": 24634, "\u0120whales": 24635, "\u0120therapist": 24636, "\u0120subset": 24637, "\u0120leisure": 24638, "ELD": 24639, "\u0120CVE": 24640, "\u0120Activity": 24641, "\u0120culmin": 24642, "shop": 24643, "\u0120DAY": 24644, "ischer": 24645, "\u0120Admiral": 24646, "\u0120Attacks": 24647, "\u01201958": 24648, "\u0120memoir": 24649, "\u0120folded": 24650, "\u0120sexist": 24651, "\u0120153": 24652, "\u0120LI": 24653, "\u0120readings": 24654, "\u0120embarrassment": 24655, "\u0120Employment": 24656, "wart": 24657, "chin": 24658, "\u0120continuation": 24659, "lia": 24660, "Recently": 24661, "\u0120duel": 24662, "\u0120evacuation": 24663, "\u0120Kashmir": 24664, "\u0120disposition": 24665, "\u0120Rig": 24666, "\u0120bolts": 24667, "\u0120insurers": 24668, "467": 24669, "Mex": 24670, "\u0120retaliation": 24671, "\u0120misery": 24672, "\u0120unreasonable": 24673, "raining": 24674, "Imm": 24675, "\u0120PU": 24676, "emer": 24677, "\u0120genital": 24678, "\u00e3\u0124\u00b3": 24679, "\u0120Candy": 24680, "\u0120onions": 24681, "\u0120Patt": 24682, "liner": 24683, "\u0120conceded": 24684, "\u0120fa": 24685, "\u0120forc": 24686, "\u0120Hernandez": 24687, "\u0120Geoff": 24688, "debian": 24689, "\u0120Teams": 24690, "\u0120cries": 24691, "\u0120homeowners": 24692, "237": 24693, "ABC": 24694, "\u0120stitch": 24695, "\u0120statistic": 24696, "\u0120headers": 24697, "\u0120Biology": 24698, "\u0120motors": 24699, "\u0120GEN": 24700, "\u0120Lip": 24701, "\u0120hates": 24702, "\u0120heel": 24703, "Self": 24704, "ipl": 24705, "EDIT": 24706, "orting": 24707, "\u0120annot": 24708, "\u0120Speech": 24709, "oldemort": 24710, "\u0120Javascript": 24711, "\u0120LeBron": 24712, "\u0120footprint": 24713, "\u0120fn": 24714, "\u0120seizures": 24715, "nas": 24716, "hide": 24717, "\u01201954": 24718, "\u0120Bee": 24719, "\u0120Declaration": 24720, "\u0120Katie": 24721, "\u0120reservations": 24722, "NR": 24723, "female": 24724, "\u0120saturated": 24725, "\u0120biblical": 24726, "\u0120trolls": 24727, "Device": 24728, "photos": 24729, "\u0120drums": 24730, "\u00e3\u0125\u012b\u00e3\u0125\u00a9\u00e3\u0124\u00b4\u00e3\u0125\u00b3": 24731, "Night": 24732, "fighter": 24733, "\u0120Hak": 24734, "riber": 24735, "\u0120cush": 24736, "\u0120disciplinary": 24737, "baum": 24738, "\u0120GH": 24739, "\u0120Schmidt": 24740, "ilibrium": 24741, "\u0120sixty": 24742, "\u0120Kushner": 24743, "rots": 24744, "\u0120pund": 24745, "\u0120Rac": 24746, "\u0120springs": 24747, "\u0120conve": 24748, "Business": 24749, "Fall": 24750, "\u0120qualifications": 24751, "\u0120verses": 24752, "\u0120narciss": 24753, "\u0120Koh": 24754, "\u0120Wow": 24755, "\u0120Charlottesville": 24756, "edo": 24757, "\u0120interrogation": 24758, "\u0120Wool": 24759, "365": 24760, "Brian": 24761, "\u0120\u00e2\u013e\u0135": 24762, "\u0120alleges": 24763, "onds": 24764, "idation": 24765, "\u0120Jackie": 24766, "yu": 24767, "\u0120lakes": 24768, "\u0120worthwhile": 24769, "\u0120crystals": 24770, "\u0120Juda": 24771, "\u0120comprehend": 24772, "\u0120flush": 24773, "\u0120absorption": 24774, "\u0120OC": 24775, "\u0120frightened": 24776, "\u0120Chocolate": 24777, "Martin": 24778, "\u0120buys": 24779, "\u0120bucks": 24780, "\u0120appell": 24781, "\u0120Championships": 24782, "\u0120listener": 24783, "\u0120Defensive": 24784, "\u0120cz": 24785, "uds": 24786, "\u0120Mate": 24787, "\u0120replay": 24788, "\u0120decorated": 24789, "\u0120sunk": 24790, "\u0120VIP": 24791, "\u0120Ank": 24792, "\u0120195": 24793, "aaaa": 24794, "Nobody": 24795, "\u0120Milk": 24796, "\u0120Gur": 24797, "\u0120Mk": 24798, "\u0120Sara": 24799, "\u0120seating": 24800, "\u0120Wid": 24801, "Track": 24802, "\u0120employs": 24803, "\u0120gigantic": 24804, "APP": 24805, "\u00e3\u0124\u00a7": 24806, "inventory": 24807, "\u0120towel": 24808, "atche": 24809, "lasting": 24810, "\u0120TL": 24811, "\u0120latency": 24812, "\u0120kne": 24813, "Ber": 24814, "meaning": 24815, "\u0120upheld": 24816, "\u0120playground": 24817, "\u0120mant": 24818, "Side": 24819, "\u0120stereo": 24820, "\u0120northwest": 24821, "\u0120exceptionally": 24822, "\u0120rays": 24823, "\u0120recurring": 24824, "Drive": 24825, "\u0120upright": 24826, "\u0120abduct": 24827, "\u0120Marathon": 24828, "\u0120goodbye": 24829, "\u0120alphabet": 24830, "hp": 24831, "\u0120courtroom": 24832, "rington": 24833, "othing": 24834, "Tag": 24835, "\u0120diplomats": 24836, "\u0120barbar": 24837, "\u0120Aqua": 24838, "183": 24839, "3333": 24840, "\u0120maturity": 24841, "\u0120instability": 24842, "\u0120Apache": 24843, "\u0120===": 24844, "\u0120fasting": 24845, "\u0120Grid": 24846, "ModLoader": 24847, "\u0120152": 24848, "Abs": 24849, "\u0120Operating": 24850, "etti": 24851, "\u0120acquaint": 24852, "Donnell": 24853, "\u0120Kem": 24854, "\u0120Forge": 24855, "\u0120armored": 24856, "Mil": 24857, "\u0120philosophers": 24858, "invest": 24859, "Players": 24860, "\u00e2\u012a": 24861, "\u0120myriad": 24862, "\u0120comrades": 24863, "Rot": 24864, "\u0120remembering": 24865, "\u0120corresponds": 24866, "\u0120programmers": 24867, "\u0120Lynn": 24868, "\u0120olig": 24869, "\u0120coherent": 24870, "ynchron": 24871, "\u0120Chemical": 24872, "\u0120jugg": 24873, "pair": 24874, "posts": 24875, "Eye": 24876, "\u0120Inner": 24877, "\u0120semester": 24878, "ottest": 24879, "\u0120Emirates": 24880, "ricanes": 24881, "orously": 24882, "mits": 24883, "\u0120Wis": 24884, "\u0120dodge": 24885, "location": 24886, "\u0120faded": 24887, "Amazon": 24888, "\u0120Proceed": 24889, "\u0120INFO": 24890, "journal": 24891, "\u0120Truck": 24892, "Ten": 24893, "\u0120217": 24894, "\u0120statutes": 24895, "mobile": 24896, "\u0120Types": 24897, "Recomm": 24898, "buster": 24899, "pex": 24900, "\u0120legends": 24901, "\u0120headache": 24902, "faced": 24903, "\u0120WiFi": 24904, "ifty": 24905, "\u0120HER": 24906, "\u0120circuits": 24907, "ERROR": 24908, "226": 24909, "olin": 24910, "\u0120cylinder": 24911, "ospace": 24912, "ikers": 24913, "Prem": 24914, "Quant": 24915, "\u0120conflicting": 24916, "\u0120slightest": 24917, "\u0120forged": 24918, "ionage": 24919, "Stephen": 24920, "\u0120Kub": 24921, "\u0120Opportun": 24922, "\u0120Heal": 24923, "\u0120blo": 24924, "\u0120rulers": 24925, "\u0120huh": 24926, "\u0120submarine": 24927, "fy": 24928, "asser": 24929, "\u0120allowance": 24930, "\u0120Kasich": 24931, "\u0120Tas": 24932, "\u0120Australians": 24933, "ForgeModLoader": 24934, "\u0120\u00e2\u0128\u0133": 24935, "\u0120Matrix": 24936, "amins": 24937, "\u01201200": 24938, "\u0120Acqu": 24939, "236": 24940, "Document": 24941, "\u0120Breaking": 24942, "193": 24943, "\u0120Subst": 24944, "\u0120Roller": 24945, "\u0120Properties": 24946, "\u0120NI": 24947, "tier": 24948, "\u0120crushing": 24949, "\u0120advocating": 24950, "Furthermore": 24951, "keepers": 24952, "\u0120sexism": 24953, "xd": 24954, "\u0120caller": 24955, "\u0120Sense": 24956, "chieve": 24957, "\u0120TF": 24958, "\u0120fueled": 24959, "\u0120reminiscent": 24960, "\u0120obsess": 24961, "urst": 24962, "\u0120uphold": 24963, "\u0120Fans": 24964, "hetics": 24965, "\u0120\u00e2\u0139": 24966, "\u0120Bath": 24967, "\u0120beverage": 24968, "\u0120oscill": 24969, "254": 24970, "\u0120poles": 24971, "\u0120gradual": 24972, "\u0120exting": 24973, "\u0120Suff": 24974, "\u0120Suddenly": 24975, "\u0120liking": 24976, "\u01201949": 24977, "unciation": 24978, "amination": 24979, "\u0120Omar": 24980, "\u0120LV": 24981, "\u0120Consequently": 24982, "\u0120synthes": 24983, "\u0120GIF": 24984, "\u0120pains": 24985, "\u0120interacting": 24986, "uously": 24987, "incre": 24988, "\u0120rumor": 24989, "\u0120Scientology": 24990, "197": 24991, "\u0120Zig": 24992, "\u0120spelling": 24993, "\u0120ASS": 24994, "\u0120extingu": 24995, "mson": 24996, "\u0120gh": 24997, "\u0120remarked": 24998, "\u0120Strategic": 24999, "\u0120MON": 25000, "\u00e5\u00a5": 25001, "gae": 25002, "\u0120WHAT": 25003, "Eric": 25004, "\u0120Campus": 25005, "\u0120methane": 25006, "\u0120imagin": 25007, "JUST": 25008, "\u0120Alm": 25009, "XT": 25010, "iq": 25011, "\u0120RSS": 25012, "\u0120wrongdoing": 25013, "atta": 25014, "\u0120bigot": 25015, "\u0120demonstrators": 25016, "\u0120Calvin": 25017, "\u0120Villa": 25018, "\u0120membrane": 25019, "\u0120Awesome": 25020, "\u0120benefic": 25021, "268": 25022, "\u0120magnificent": 25023, "\u0120Lots": 25024, "Greg": 25025, "\u0120Boris": 25026, "\u0120detainees": 25027, "\u0120Herman": 25028, "\u0120whispered": 25029, "\u0120awe": 25030, "Professor": 25031, "funding": 25032, "\u0120physiological": 25033, "\u0120Destruction": 25034, "\u0120limb": 25035, "\u0120manipulated": 25036, "\u0120bubbles": 25037, "\u0120pseud": 25038, "\u0120hydra": 25039, "\u0120Bristol": 25040, "\u0120stellar": 25041, "\u0120Expansion": 25042, "\u0120Kell": 25043, "\u0120Interestingly": 25044, "\u0120mans": 25045, "\u0120dragging": 25046, "\u0120ecological": 25047, "\u0120Fit": 25048, "\u0120gent": 25049, "\u0120benefited": 25050, "\u0120Haiti": 25051, "\u0120polyg": 25052, "\u00e3\u0125\u0130": 25053, "\u01202030": 25054, "\u0120prow": 25055, "\u0120reconstruction": 25056, "\u0120wast": 25057, "\u0120psychic": 25058, "\u0120Greeks": 25059, "Handler": 25060, "162": 25061, "\u0120Pulse": 25062, "\u0120solicit": 25063, "\u0120sys": 25064, "\u0120influx": 25065, "\u0120Gentle": 25066, "percent": 25067, "\u0120proliferation": 25068, "\u0120taxable": 25069, "\u0120disregard": 25070, "\u0120escaping": 25071, "\u0120ginger": 25072, "\u0120withstand": 25073, "\u0120devastated": 25074, "\u0120Dew": 25075, "series": 25076, "\u0120injected": 25077, "elaide": 25078, "\u0120turnover": 25079, "heat": 25080, "\u013b\u0124": 25081, "Happy": 25082, "\u0120Silent": 25083, "\u00e3\u0124\u0143": 25084, "ivism": 25085, "\u0120irrational": 25086, "AMA": 25087, "\u0120reef": 25088, "rub": 25089, "\u0120162": 25090, "\u0120bankers": 25091, "\u0120Ethics": 25092, "vv": 25093, "\u0120criticisms": 25094, "Kn": 25095, "186": 25096, "Movie": 25097, "\u0120Tories": 25098, "\u0120nood": 25099, "\u0120distortion": 25100, "False": 25101, "odore": 25102, "\u0120tasty": 25103, "Research": 25104, "\u0120UID": 25105, "-)": 25106, "\u0120divorced": 25107, "\u0120MU": 25108, "\u0120Hayes": 25109, "\u0120Isn": 25110, "iani": 25111, "\u0120HQ": 25112, "\u0120\"#": 25113, "ignant": 25114, "\u0120traumatic": 25115, "\u0120Ling": 25116, "Hun": 25117, "\u0120sabot": 25118, "online": 25119, "random": 25120, "\u0120renamed": 25121, "rared": 25122, "KA": 25123, "dead": 25124, "\u00c3\u00a9t": 25125, "\u0120Assistance": 25126, "\u0120seaf": 25127, "++++++++": 25128, "\u0120seldom": 25129, "\u0120Webb": 25130, "\u0120boolean": 25131, "ulet": 25132, "\u0120refrain": 25133, "\u0120DIY": 25134, "rule": 25135, "\u0120shutting": 25136, "\u0120utilizing": 25137, "loading": 25138, "\u0120Param": 25139, "coal": 25140, "ooter": 25141, "\u0120attracting": 25142, "\u0120Dol": 25143, "\u0120hers": 25144, "agnetic": 25145, "\u0120Reach": 25146, "imo": 25147, "\u0120discarded": 25148, "\u0120Pip": 25149, "015": 25150, "\u00c3\u00bcr": 25151, "\u0120mug": 25152, "Imagine": 25153, "COL": 25154, "\u0120cursed": 25155, "\u0120Shows": 25156, "\u0120Curtis": 25157, "\u0120Sachs": 25158, "speaking": 25159, "\u0120Vista": 25160, "\u0120Framework": 25161, "ongo": 25162, "\u0120subreddit": 25163, "\u0120crus": 25164, "\u0120Oval": 25165, "Row": 25166, "growing": 25167, "\u0120installment": 25168, "\u0120glac": 25169, "\u0120Advance": 25170, "ECK": 25171, "\u0120LGBTQ": 25172, "LEY": 25173, "\u0120acet": 25174, "\u0120successive": 25175, "\u0120Nicole": 25176, "\u01201957": 25177, "Quote": 25178, "\u0120circumstance": 25179, "ackets": 25180, "\u0120142": 25181, "ortium": 25182, "\u0120guessed": 25183, "\u0120Frame": 25184, "\u0120perpetrators": 25185, "\u0120Aviation": 25186, "\u0120Bench": 25187, "\u0120handc": 25188, "Ap": 25189, "\u01201956": 25190, "259": 25191, "rand": 25192, "NetMessage": 25193, "din": 25194, "urtles": 25195, "hig": 25196, "\u0120VIII": 25197, "ffiti": 25198, "\u0120Swords": 25199, "bial": 25200, "\u0120kidnapping": 25201, "device": 25202, "\u0120barn": 25203, "\u0120Eli": 25204, "aucas": 25205, "Send": 25206, "Constructed": 25207, "\u0120\u00c2\u00bd": 25208, "\u0120needles": 25209, "\u0120advertisements": 25210, "\u0120vou": 25211, "\u0120exhibited": 25212, "\u0120Fortress": 25213, "Ask": 25214, "Berry": 25215, "TYPE": 25216, "\u0120cancers": 25217, "umping": 25218, "\u0120Territory": 25219, "\u0120prud": 25220, "\u0120nas": 25221, "\u0120atheist": 25222, "\u0120balances": 25223, "\u00e3\u0123\u0141": 25224, "\u0120Shawn": 25225, "&&": 25226, "\u0120landsc": 25227, "\u0120RGB": 25228, "\u0120petty": 25229, "\u0120excellence": 25230, "\u0120translations": 25231, "\u0120parcel": 25232, "\u0120Chev": 25233, "East": 25234, "\u0120Output": 25235, "imi": 25236, "\u0120ambient": 25237, "\u0120Threat": 25238, "\u0120villains": 25239, "\u0120550": 25240, "ICA": 25241, "\u0120taller": 25242, "\u0120leaking": 25243, "cup": 25244, "\u0120polish": 25245, "\u0120infectious": 25246, "\u0120KC": 25247, "\u0120@@": 25248, "background": 25249, "\u0120bureaucracy": 25250, "\u0120Sai": 25251, "unless": 25252, "itious": 25253, "\u0120Skype": 25254, "Atl": 25255, "IDENT": 25256, "008": 25257, "\u0120hypocr": 25258, "\u0120pitchers": 25259, "\u0120guessing": 25260, "\u0120FINAL": 25261, "Between": 25262, "\u0120villagers": 25263, "\u0120252": 25264, "fashion": 25265, "\u0120Tunis": 25266, "Beh": 25267, "\u0120Exc": 25268, "\u0120MID": 25269, "288": 25270, "\u0120Haskell": 25271, "196": 25272, "\u0120NOR": 25273, "\u0120specs": 25274, "\u0120invari": 25275, "\u0120glut": 25276, "\u0120Cars": 25277, "\u0120impulse": 25278, "\u0120honors": 25279, "gel": 25280, "\u0120jurisdictions": 25281, "\u0120Bundle": 25282, "ulas": 25283, "California": 25284, "\u0120Increase": 25285, "\u0120pear": 25286, "\u0120singles": 25287, "\u0120cues": 25288, "\u0120underwent": 25289, "\u0120WS": 25290, "\u0120exaggerated": 25291, "\u0120dubious": 25292, "\u0120flashing": 25293, "LOG": 25294, ")].": 25295, "Journal": 25296, "tg": 25297, "Van": 25298, "\u0120Istanbul": 25299, "\u0120Insp": 25300, "\u0120Franken": 25301, "Draw": 25302, "\u0120sadness": 25303, "\u0120ironic": 25304, "\u0120Fry": 25305, "xc": 25306, "\u0120164": 25307, "isch": 25308, "Way": 25309, "\u0120Protestant": 25310, "horn": 25311, "\u0120unaff": 25312, "\u0120Viv": 25313, "illas": 25314, "\u0120Productions": 25315, "\u0120Hogan": 25316, "\u0120perimeter": 25317, "\u0120Sisters": 25318, "\u0120spontaneous": 25319, "\u0120downside": 25320, "\u0120descendants": 25321, "\u0120orn": 25322, "worm": 25323, "Japanese": 25324, "\u01201955": 25325, "\u0120151": 25326, "\u0120Doing": 25327, "elsen": 25328, "umbles": 25329, "\u0120radically": 25330, "\u0120Drum": 25331, "\u0120Bach": 25332, "\u0120liabilities": 25333, "\u0120OB": 25334, "\u0120Elementary": 25335, "\u0120meme": 25336, "ynes": 25337, "\u0120fingerprint": 25338, "\u0120Grab": 25339, "\u0120undertake": 25340, "Members": 25341, "\u0120Reader": 25342, "\u0120Sims": 25343, "god": 25344, "\u0120hypothetical": 25345, "scient": 25346, "\u0120AJ": 25347, "\u0120charism": 25348, "\u0120admissions": 25349, "\u0120Missile": 25350, "trade": 25351, "\u0120exercising": 25352, "\u0120Background": 25353, "Written": 25354, "\u0120vocals": 25355, "whether": 25356, "\u0120vi": 25357, "\u0120Winner": 25358, "\u0120litter": 25359, "\u0120Shooting": 25360, "STEM": 25361, "\u00e3\u0124\u00a1": 25362, "\u0120AFL": 25363, "\u0120variability": 25364, "\u0120eats": 25365, "\u0120DPS": 25366, "brow": 25367, "\u0120elephants": 25368, "\u0120strat": 25369, "\u0120\u00c5": 25370, "\u0120settlers": 25371, "Matthew": 25372, "\u0120inadvert": 25373, "HI": 25374, "\u0120IMF": 25375, "\u0120Goal": 25376, "\u0120nerves": 25377, "Johnson": 25378, "eye": 25379, "ablishment": 25380, "Thursday": 25381, "BILITY": 25382, "Had": 25383, "amoto": 25384, "hetamine": 25385, "eps": 25386, "\u0120mitochond": 25387, "\u0120compressed": 25388, "\u0120Trevor": 25389, "\u0120Animals": 25390, "Tool": 25391, "Lock": 25392, "\u0120tweak": 25393, "\u0120pinch": 25394, "\u0120cancellation": 25395, "Pot": 25396, "\u0120focal": 25397, "\u0120Astron": 25398, "173": 25399, "\u0120ASC": 25400, "\u0120OTHER": 25401, "umni": 25402, "\u0120demise": 25403, "dl": 25404, "\u00d9\u0127": 25405, "Semitism": 25406, "\u0120cracking": 25407, "\u0120collaborative": 25408, "\u0120explores": 25409, "sql": 25410, "\u0120herbs": 25411, "\u0120configurations": 25412, "mis": 25413, "\u0120Result": 25414, "acey": 25415, "\u0120Smoke": 25416, "\u0120sanct": 25417, "elia": 25418, "\u0120degener": 25419, "\u0120deepest": 25420, "\u0120screamed": 25421, "\u0120nap": 25422, "Software": 25423, "\u0120STAR": 25424, "EF": 25425, "\u0120Xin": 25426, "sponsored": 25427, "manship": 25428, "233": 25429, "\u0120primaries": 25430, "\u0120filtering": 25431, "\u0120assemble": 25432, "mil": 25433, "\u0120Myers": 25434, "bows": 25435, "\u0120punched": 25436, "Mic": 25437, "\u0120innovations": 25438, "\u0120func": 25439, "ando": 25440, "\u0120fracking": 25441, "\u0120Vul": 25442, "\u00d0\u00be\u00d0": 25443, "oshop": 25444, "\u0120Immun": 25445, "\u0120settling": 25446, "\u0120adolescents": 25447, "\u0120rebuilding": 25448, "\u0120transforming": 25449, "\u0120parole": 25450, "\u0120harbor": 25451, "\u0120booking": 25452, "otional": 25453, "ongevity": 25454, "\u0120Yo": 25455, "bug": 25456, "\u0120emerges": 25457, "\u0120Methods": 25458, "\u0120Chu": 25459, "Pres": 25460, "\u0120Dungeons": 25461, "\u0120trailing": 25462, "\u0120Rum": 25463, "\u0120Hugh": 25464, "\u00e5\u00a4\u00a9": 25465, "\u0120Era": 25466, "\u0120Battles": 25467, "Results": 25468, "\u0120Trading": 25469, "\u0120versa": 25470, "css": 25471, "axies": 25472, "heet": 25473, "\u0120greed": 25474, "1989": 25475, "\u0120gardens": 25476, "\u0120contingent": 25477, "Park": 25478, "\u0120Leafs": 25479, "hook": 25480, "robe": 25481, "\u0120diplomacy": 25482, "\u0120Fuel": 25483, "\u0120Invasion": 25484, "\u0120upgrading": 25485, "Male": 25486, "\u0120elic": 25487, "\u0120relentless": 25488, "\u0120Covenant": 25489, "apesh": 25490, "\u0120Trop": 25491, "Ty": 25492, "production": 25493, "arty": 25494, "\u0120punches": 25495, "ako": 25496, "cyclopedia": 25497, "\u0120Rabbit": 25498, "\u0120HDMI": 25499, "\u0120141": 25500, "\u0120foil": 25501, "ItemImage": 25502, "\u0120FG": 25503, "\u0120implementations": 25504, "\u0120Pom": 25505, "ixtures": 25506, "\u0120await": 25507, "\u0120330": 25508, "amus": 25509, "\u0120umbrella": 25510, "\u0120foresee": 25511, "separ": 25512, "\u0120circumcision": 25513, "\u0120peripheral": 25514, "Say": 25515, "\u0120Expert": 25516, "Inc": 25517, "\u0120withdrew": 25518, "\u0120Anders": 25519, "fried": 25520, "\u0120radioactive": 25521, "\u0120Opening": 25522, "\u0120boarding": 25523, "\u0120ND": 25524, "\u0120overthrow": 25525, "Activ": 25526, "WP": 25527, "\u0120Acts": 25528, "\u00d7\u013b": 25529, "\u0120motions": 25530, "vic": 25531, "\u0120Mighty": 25532, "\u0120Defender": 25533, "aer": 25534, "\u0120thankful": 25535, "\u0120Killing": 25536, "\u0120Bris": 25537, "moil": 25538, "\u0120predicting": 25539, "266": 25540, "choice": 25541, "\u0120killers": 25542, "\u0120incub": 25543, "\u0120Chest": 25544, "athering": 25545, "\u0120proclaimed": 25546, "flower": 25547, "ossom": 25548, "umbledore": 25549, "\u0120Cycling": 25550, "\u0120Occupy": 25551, "AGES": 25552, "Pen": 25553, "\u0120Yug": 25554, "\u0120packaged": 25555, "\u0120heightened": 25556, "cot": 25557, "stack": 25558, "Cond": 25559, "\u0120stamps": 25560, "mage": 25561, "\u0120persuaded": 25562, "\u0120ensl": 25563, "\u0120Cardinal": 25564, "\u0120solitary": 25565, "\u0120possessing": 25566, "\u0120Cork": 25567, "\u0120evid": 25568, "\u0120Tay": 25569, "\u0120blues": 25570, "\u0120extremism": 25571, "\u0120lunar": 25572, "\u0120clown": 25573, "Techn": 25574, "\u0120festivals": 25575, "\u0120PvP": 25576, "\u0120Lar": 25577, "\u0120consequently": 25578, "present": 25579, "\u0120someday": 25580, "\u00e7\u0130\u012d": 25581, "\u0120Meteor": 25582, "\u0120touring": 25583, "culture": 25584, "\u0120beaches": 25585, "Ship": 25586, "cause": 25587, "\u0120Flood": 25588, "\u00e3\u0125\u00af": 25589, "\u0120purity": 25590, "those": 25591, "\u0120emission": 25592, "bolt": 25593, "\u0120chord": 25594, "\u0120Scripture": 25595, "Lu": 25596, "\u0120${": 25597, "created": 25598, "Others": 25599, "258": 25600, "\u0120elemental": 25601, "\u0120annoyed": 25602, "\u0120AE": 25603, "dan": 25604, "\u0120Sag": 25605, "Researchers": 25606, "\u0120fairy": 25607, "\u00e2\u0122\u0135\u00e2\u0122\u0135": 25608, "============": 25609, "Smart": 25610, "GGGG": 25611, "\u0120skeletons": 25612, "\u0120pupils": 25613, "linked": 25614, "\u0120urgency": 25615, "enabled": 25616, "\u0120Fuck": 25617, "\u0120councill": 25618, "rab": 25619, "UAL": 25620, "TI": 25621, "\u0120lifes": 25622, "\u0120confessed": 25623, "Bug": 25624, "\u0120harmon": 25625, "\u0120CONFIG": 25626, "\u0120Neutral": 25627, "Double": 25628, "\u0120staple": 25629, "\u0120SHA": 25630, "British": 25631, "\u0120SNP": 25632, "ATOR": 25633, "oco": 25634, "\u0120swinging": 25635, "gex": 25636, "oleon": 25637, "plain": 25638, "\u0120Missing": 25639, "\u0120Trophy": 25640, "vari": 25641, "ranch": 25642, "\u0120301": 25643, "440": 25644, "0000000000000000": 25645, "\u0120restoring": 25646, "\u0120haul": 25647, "ucing": 25648, "nerg": 25649, "\u0120futures": 25650, "\u0120strategist": 25651, "question": 25652, "\u0120lateral": 25653, "\u0120Bard": 25654, "\u0120sor": 25655, "\u0120Rhodes": 25656, "\u0120Downtown": 25657, "?????-": 25658, "\u0120Lit": 25659, "\u0120Bened": 25660, "\u0120coil": 25661, "street": 25662, "\u0120Portal": 25663, "FILE": 25664, "\u0120Gru": 25665, "*,": 25666, "231": 25667, "neum": 25668, "\u0120sucked": 25669, "\u0120rapper": 25670, "\u0120tendencies": 25671, "\u0120Lauren": 25672, "cellaneous": 25673, "267": 25674, "\u0120browse": 25675, "\u0120overc": 25676, "header": 25677, "oise": 25678, "\u0120beet": 25679, "\u0120Gle": 25680, "Stay": 25681, "\u0120mum": 25682, "\u0120typed": 25683, "\u0120discounts": 25684, "Talk": 25685, "\u0120Og": 25686, "existing": 25687, "\u0120Sell": 25688, "uph": 25689, "CI": 25690, "\u0120Austrian": 25691, "\u0120Warm": 25692, "\u0120dismissal": 25693, "\u0120averages": 25694, "camera": 25695, "\u0120allegiance": 25696, "LAN": 25697, "=\"#": 25698, "\u0120commentators": 25699, "\u0120Setting": 25700, "\u0120Midwest": 25701, "\u0120pharmac": 25702, "\u0120EXP": 25703, "\u0120stainless": 25704, "Chicago": 25705, "\u0120tan": 25706, "244": 25707, "\u0120countryside": 25708, "\u0120Vac": 25709, "295": 25710, "\u0120pinned": 25711, "\u0120crises": 25712, "\u0120standardized": 25713, "Task": 25714, "\u0120Jail": 25715, "\u0120Docker": 25716, "colored": 25717, "forth": 25718, "\"},": 25719, "\u0120patrons": 25720, "\u0120spice": 25721, "\u0120mourn": 25722, "\u0120Mood": 25723, "\u0120laundry": 25724, "\u0120equip": 25725, "\u0120Mole": 25726, "yll": 25727, "\u0120THC": 25728, "nation": 25729, "\u0120Sherlock": 25730, "\u0120issu": 25731, "\u0120Kre": 25732, "\u0120Americas": 25733, "\u0120AAA": 25734, "\u0120systematically": 25735, "\u0120contra": 25736, "\u0120Sally": 25737, "\u0120rationale": 25738, "\u0120carriage": 25739, "\u0120peaks": 25740, "\u0120contradiction": 25741, "ensation": 25742, "\u0120Failure": 25743, "\u0120props": 25744, "\u0120namespace": 25745, "\u0120cove": 25746, "fields": 25747, "\u00e3\u0124\u012d": 25748, "\u0120wool": 25749, "\u0120Catch": 25750, "\u0120presumed": 25751, "\u0120Diana": 25752, "ragon": 25753, "igi": 25754, "\u0120hamm": 25755, "\u0120stunt": 25756, "\u0120GUI": 25757, "\u0120Observatory": 25758, "\u0120Shore": 25759, "\u0120smells": 25760, "annah": 25761, "\u0120cockpit": 25762, "\u0120Duterte": 25763, "850": 25764, "\u0120oppressed": 25765, "breaker": 25766, "\u0120Contribut": 25767, "\u0120Peru": 25768, "\u0120Monsanto": 25769, "\u0120Attempt": 25770, "\u0120commanding": 25771, "\u0120fridge": 25772, "\u0120Rin": 25773, "\u0120Chess": 25774, "uality": 25775, "\u0120ol": 25776, "Republican": 25777, "\u0120Glory": 25778, "\u0120WIN": 25779, ".......": 25780, "agent": 25781, "reading": 25782, "\u0120inh": 25783, "Jones": 25784, "\u0120clicks": 25785, "alan": 25786, "\u0120[];": 25787, "\u0120Majesty": 25788, "\u0120Ced": 25789, "opus": 25790, "atel": 25791, "\u00c3\u00aa": 25792, "ARC": 25793, "\u0120Ecuador": 25794, "\u00e3\u0125\u0142": 25795, "\u0120Kuro": 25796, "\u0120rituals": 25797, "\u0120captive": 25798, "\u0120ounce": 25799, "\u0120disagreement": 25800, "\u0120slog": 25801, "fuel": 25802, "Pet": 25803, "Mail": 25804, "\u0120exercised": 25805, "\u0120solic": 25806, "\u0120rainfall": 25807, "\u0120devotion": 25808, "\u0120Assessment": 25809, "\u0120robotic": 25810, "options": 25811, "\u0120RP": 25812, "\u0120Families": 25813, "\u0120Flames": 25814, "\u0120assignments": 25815, "007": 25816, "akedown": 25817, "\u0120vocabulary": 25818, "Reilly": 25819, "\u0120caval": 25820, "gars": 25821, "\u0120suppressed": 25822, "\u0120SET": 25823, "\u0120Johns": 25824, "\u0120warp": 25825, "broken": 25826, "\u0120statues": 25827, "\u0120advocated": 25828, "\u0120275": 25829, "\u0120peril": 25830, "omorph": 25831, "\u0120Femin": 25832, "perfect": 25833, "\u0120hatch": 25834, "Lib": 25835, "512": 25836, "\u0120lifelong": 25837, "313": 25838, "\u0120cheeks": 25839, "\u0120numbered": 25840, "\u0120Mug": 25841, "Body": 25842, "ravel": 25843, "Weight": 25844, "\u0120Jak": 25845, "\u0120Heath": 25846, "\u0120kissing": 25847, "\u0120JUST": 25848, "\u0120waving": 25849, "upload": 25850, "\u0120insider": 25851, "\u0120Progressive": 25852, "\u0120Filter": 25853, "tta": 25854, "\u0120Beam": 25855, "\u0120violently": 25856, "ipation": 25857, "\u0120skepticism": 25858, "\u01201918": 25859, "\u0120Annie": 25860, "\u0120SI": 25861, "\u0120genetics": 25862, "\u0120onboard": 25863, "atl": 25864, "\u0120Friedman": 25865, "\u0120Bri": 25866, "ceptive": 25867, "\u0120pirate": 25868, "\u0120Reporter": 25869, "278": 25870, "\u0120mythology": 25871, "\u0120eclipse": 25872, "\u0120skins": 25873, "\u0120glyph": 25874, "ingham": 25875, "Files": 25876, "Cour": 25877, "women": 25878, "\u0120regimes": 25879, "\u0120photographed": 25880, "Kat": 25881, "\u0120MAX": 25882, "Officials": 25883, "\u0120unexpectedly": 25884, "\u0120impressions": 25885, "Front": 25886, ";;;;;;;;": 25887, "\u0120supremacy": 25888, "\u0120sang": 25889, "\u0120aggravated": 25890, "\u0120abruptly": 25891, "\u0120Sector": 25892, "\u0120excuses": 25893, "\u0120costing": 25894, "idepress": 25895, "Stack": 25896, "\u0120RNA": 25897, "obil": 25898, "\u0120ghosts": 25899, "ldon": 25900, "atibility": 25901, "Topics": 25902, "\u0120reimburse": 25903, "\u0120HM": 25904, "\u0120Deg": 25905, "\u0120thief": 25906, "yet": 25907, "ogenesis": 25908, "leaning": 25909, "\u0120Kol": 25910, "\u0120Basketball": 25911, "\u0120fi": 25912, "\u0120Seeing": 25913, "\u0120recycling": 25914, "\u0120[-": 25915, "Congress": 25916, "\u0120lectures": 25917, "Psy": 25918, "\u0120nep": 25919, "\u0120maid": 25920, "\u0120oriented": 25921, "AX": 25922, "\u0120respectful": 25923, "rene": 25924, "flush": 25925, "\u0120Unloaded": 25926, "request": 25927, "grid": 25928, "\u0120Alternatively": 25929, "\u0120Hugo": 25930, "\u0120decree": 25931, "\u0120Buddhism": 25932, "andum": 25933, "Android": 25934, "\u0120Congo": 25935, "\u0120Joyce": 25936, "\u0120acknowledging": 25937, "hesive": 25938, "\u0120Tomorrow": 25939, "\u0120Hiro": 25940, "thren": 25941, "\u0120Maced": 25942, "\u0120hoax": 25943, "\u0120Increased": 25944, "\u0120Pradesh": 25945, "Wild": 25946, "______": 25947, "161": 25948, "\u0120aunt": 25949, "\u0120distributing": 25950, "\u0120Tucker": 25951, "\u0120SSL": 25952, "\u0120Wolves": 25953, "Building": 25954, "oult": 25955, "\u0120Luo": 25956, "\u0120Yas": 25957, "\u0120Spir": 25958, "\u0120Shape": 25959, "\u0120Cambod": 25960, "\u0120IPv": 25961, "\u0120ml": 25962, "\u0120extrad": 25963, "390": 25964, "\u0120Penny": 25965, "dream": 25966, "\u0120stationed": 25967, "optional": 25968, "eworthy": 25969, ".": 26700, "\u0120Workshop": 26701, "\u0120Retail": 26702, "\u0120Avatar": 26703, "625": 26704, "Na": 26705, "\u0120VC": 26706, "\u0120Secure": 26707, "MY": 26708, "1988": 26709, "ossip": 26710, "\u0120prostate": 26711, "\u0120unden": 26712, "\u0120gamer": 26713, "\u0120Contents": 26714, "\u0120Warhammer": 26715, "\u0120Sentinel": 26716, "310": 26717, "\u0120segregation": 26718, "\u0120Flex": 26719, "\u0120MAY": 26720, "\u0120drills": 26721, "\u0120Drugs": 26722, "Islamic": 26723, "\u0120spur": 26724, "\u0120cafe": 26725, "\u0120imaginary": 26726, "\u0120guiding": 26727, "\u0120swings": 26728, "\u0120Theme": 26729, "oby": 26730, "\u0120nud": 26731, "\u0120begging": 26732, "\u0120strongh": 26733, "\u0120rejecting": 26734, "\u0120pedestrians": 26735, "\u0120Prospect": 26736, "Rare": 26737, "sle": 26738, "\u0120concessions": 26739, "\u0120Constitutional": 26740, "\u0120beams": 26741, "\u0120fibers": 26742, "poon": 26743, "\u0120instincts": 26744, "property": 26745, "\u0120BIG": 26746, "Sanders": 26747, "imates": 26748, "\u0120coating": 26749, "\u0120corpses": 26750, "\u0120TRUE": 26751, "checked": 26752, "\u0120166": 26753, "Ash": 26754, "\u0120JS": 26755, "\u0120Fiction": 26756, "\u0120communal": 26757, "\u0120energetic": 26758, "oooooooo": 26759, "\u0120nowadays": 26760, "ILD": 26761, "ibo": 26762, "\u0120SUV": 26763, "Ren": 26764, "\u0120dwelling": 26765, "Silver": 26766, "\u0120tally": 26767, "\u0120Moving": 26768, "\u0120coward": 26769, "\u0120generals": 26770, "\u0120horns": 26771, "\u0120circulated": 26772, "\u0120robbed": 26773, "\u0120Unlimited": 26774, "\u0120harassed": 26775, "\u0120inhibit": 26776, "\u0120composer": 26777, "\u0120Spotify": 26778, "\u0120spreads": 26779, "364": 26780, "\u0120suicidal": 26781, "\u0120noises": 26782, "\u0120Stur": 26783, "\u0120saga": 26784, "\u0120Kag": 26785, "iso": 26786, "\u0120theoretically": 26787, "Money": 26788, "\u0120similarity": 26789, "\u0120sliced": 26790, "utils": 26791, "inges": 26792, "\"-": 26793, "\u0120anth": 26794, "\u0120imped": 26795, "Module": 26796, "Throughout": 26797, "\u0120menus": 26798, "committee": 26799, "andi": 26800, "obj": 26801, "inav": 26802, "fired": 26803, "\u0120Abdullah": 26804, "\u0120undead": 26805, "\u0120fonts": 26806, "Hold": 26807, "ENG": 26808, "\u0120sustainability": 26809, "\u0120flick": 26810, "\u0120razor": 26811, "\u0120Fest": 26812, "\u0120Characters": 26813, "\u0120wording": 26814, "\u0120populist": 26815, "\u0120criticizing": 26816, "\u0120muse": 26817, "vine": 26818, "\u0120cardboard": 26819, "\u0120kindly": 26820, "\u0120fringe": 26821, "\u0120Theft": 26822, "icultural": 26823, "\u0120governors": 26824, "\u0120\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd": 26825, "\u0120163": 26826, "\u0120timeout": 26827, "\u0120Auth": 26828, "Children": 26829, "AU": 26830, "\u0120redemption": 26831, "\u0120Alger": 26832, "\u01201914": 26833, "\u0120waved": 26834, "\u0120astronauts": 26835, "ograms": 26836, "\u0120swamp": 26837, "\u0120Finnish": 26838, "\u0120candle": 26839, "\u0120tonnes": 26840, "utm": 26841, "\u0120ray": 26842, "\u0120spun": 26843, "\u0120fearful": 26844, "articles": 26845, "\u0120caus": 26846, "orically": 26847, "\u0120Requires": 26848, "\u0120Gol": 26849, "\u0120pope": 26850, "\u0120inaugural": 26851, "\u0120gle": 26852, "ADA": 26853, "\u0120ISIL": 26854, "\u0120Offensive": 26855, "\u0120watchdog": 26856, "\u0120balcon": 26857, "entity": 26858, "\u0120Hoo": 26859, "\u0120gallon": 26860, "ACC": 26861, "\u0120doubling": 26862, "\u0120implication": 26863, "\u0120Sight": 26864, "\u0120doctr": 26865, "-------": 26866, "\u0120\\\\": 26867, "\u0120malt": 26868, "Roll": 26869, "\u0120\u00e2\u012b\u00a5": 26870, "\u0120recap": 26871, "adding": 26872, "uces": 26873, "\u0120Bend": 26874, "figure": 26875, "\u0120turkey": 26876, "\u0120societal": 26877, "\u0120Tickets": 26878, "\u0120commercially": 26879, "\u0120spicy": 26880, "\u0120216": 26881, "\u0120Ramp": 26882, "\u0120superiority": 26883, "\u00c3\u00af": 26884, "\u0120Tracker": 26885, "Carl": 26886, "\u0120Coy": 26887, "\u0120Patriot": 26888, "\u0120consulted": 26889, "\u0120listings": 26890, "\u0120slew": 26891, "reenshot": 26892, "\u0120Gone": 26893, "\u0120[...]": 26894, "309": 26895, "\u0120hottest": 26896, "\u00d8\u00b1": 26897, "\u0120rocky": 26898, "\u0120Diaz": 26899, "\u0120massage": 26900, "\u0120paraly": 26901, "\u0120pony": 26902, "Az": 26903, "\u0120cartridge": 26904, "\u0120NZ": 26905, "\u0120snack": 26906, "\u0120Lamar": 26907, "plement": 26908, "\u0120Leslie": 26909, "\u0120mater": 26910, "\u0120snipp": 26911, "246": 26912, "\u0120jointly": 26913, "\u0120Brisbane": 26914, "\u0120iPod": 26915, "\u0120pumping": 26916, "\u0120goat": 26917, "\u0120Sharon": 26918, "ealing": 26919, "\u0120coron": 26920, "\u0120anomal": 26921, "rahim": 26922, "\u0120Connection": 26923, "\u0120sculpture": 26924, "\u0120scheduling": 26925, "\u0120Daddy": 26926, "athing": 26927, "\u0120eyebrows": 26928, "\u0120curved": 26929, "\u0120sentiments": 26930, "\u0120drafting": 26931, "Drop": 26932, "([": 26933, "\u0120nominal": 26934, "\u0120Leadership": 26935, "\u0120Grow": 26936, "\u0120176": 26937, "\u0120constructive": 26938, "ivation": 26939, "\u0120corrupted": 26940, "gerald": 26941, "\u0120Cros": 26942, "\u0120Chester": 26943, "\u0120Lap": 26944, "\u00e3\u0123\u00aa": 26945, "OTH": 26946, "DATA": 26947, "\u0120almond": 26948, "probably": 26949, "Imp": 26950, "\u0120feast": 26951, "\u0120Warcraft": 26952, "Flor": 26953, "\u0120checkpoint": 26954, "\u0120transcription": 26955, "\u0120204": 26956, "\u0120tweaks": 26957, "\u0120relieve": 26958, "Science": 26959, "\u0120performer": 26960, "Zone": 26961, "\u0120turmoil": 26962, "igated": 26963, "hibit": 26964, "\u0120Cafe": 26965, "themed": 26966, "\u0120fluor": 26967, "bench": 26968, "\u0120decom": 26969, "\u0120Unt": 26970, "\u0120Barrett": 26971, "\u0120Facts": 26972, "\u0120tasting": 26973, "\u0120PTSD": 26974, "\u0120Seal": 26975, "\u0120Judaism": 26976, "\u0120Dynamic": 26977, "\u0120Cors": 26978, "Ve": 26979, "\u0120Ming": 26980, "\u0120Transform": 26981, "von": 26982, "\u0120Defenders": 26983, "\u0120Tactical": 26984, "\u0120Von": 26985, "\u0120Univers": 26986, "\u0120distorted": 26987, "\u0120Breath": 26988, "?'\"": 26989, "\u0120agon": 26990, "\u0120Deadly": 26991, "\u0120lan": 26992, "\u0120Cycle": 26993, "orned": 26994, "\u0120reliably": 26995, "\u0120glor": 26996, "\u0120Monkey": 26997, "\u00e3\u0125\u00a1": 26998, "\u0120adren": 26999, "\u0120microwave": 27000, "\u0120Alban": 27001, "ircraft": 27002, "digit": 27003, "smart": 27004, "\u0120Dread": 27005, "\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af\u00c2\u00af": 27006, "{{": 27007, "\u0120Rochester": 27008, "\u0120simplified": 27009, "\u0120inflicted": 27010, "\u0120takeover": 27011, "\u0120yourselves": 27012, "aditional": 27013, "\u0120muscular": 27014, "KS": 27015, "\u0120ingen": 27016, "Tax": 27017, "\u0120Feature": 27018, "277": 27019, "\u0120cruc": 27020, "\u0120crate": 27021, "\u0120unidentified": 27022, "\u0120acclaimed": 27023, "\u0120Manga": 27024, "\u0120Frances": 27025, "\u0120Nepal": 27026, "\u0120Gerald": 27027, "\u0120Kuwait": 27028, "\u0120slain": 27029, "\u0120Heb": 27030, "\u0120Goku": 27031, "\u00e3\u0123\u00ae\u00e6": 27032, "286": 27033, "Mrs": 27034, "\u0120Cody": 27035, "\u0120Sanctuary": 27036, "016": 27037, "\u0120dismant": 27038, "\u0120dataset": 27039, "\u0120Hond": 27040, "buck": 27041, "\u0120Patterson": 27042, "\u0120palette": 27043, "\u0120GD": 27044, "icol": 27045, "\u0120Lodge": 27046, "\u0120planetary": 27047, "akin": 27048, "\u0120Registered": 27049, "abwe": 27050, "\u0120Petersburg": 27051, "\u0120hailed": 27052, "\u0120Piece": 27053, "Sche": 27054, "\u0120DOJ": 27055, "\u0120enumer": 27056, "181": 27057, "\u0120Observer": 27058, "\u0120Bold": 27059, "founded": 27060, "commerce": 27061, "\u0120exploits": 27062, "\u0120Finding": 27063, "URN": 27064, "\u0120Sne": 27065, "\u0120Acid": 27066, "ayette": 27067, "\u0120Values": 27068, "\u0120drastic": 27069, "\u0120architectural": 27070, "\u0120\".": 27071, "\u00d7\u0137": 27072, "umped": 27073, "\u0120wrapping": 27074, "\u0120widow": 27075, "\u0120Slayer": 27076, "lace": 27077, "once": 27078, "Germany": 27079, "avoid": 27080, "\u0120temples": 27081, "PAR": 27082, "\u00c3\u00b4": 27083, "\u0120Lucifer": 27084, "\u0120Flickr": 27085, "lov": 27086, "forces": 27087, "\u0120scouting": 27088, "\u0120louder": 27089, "tesy": 27090, "\u0120beforehand": 27091, "\u00c4\u0135": 27092, "\u0120Neon": 27093, "\u0120Wol": 27094, "\u0120Typically": 27095, "\u0120Politico": 27096, "-+-+": 27097, "\u0120builder": 27098, "\u0120derive": 27099, "Kill": 27100, "\u0120poker": 27101, "\u0120ambiguous": 27102, "\u0120lifts": 27103, "\u0120cyt": 27104, "\u0120ribs": 27105, "oodle": 27106, "\u0120Sounds": 27107, "hair": 27108, "\u0120Syndrome": 27109, "tf": 27110, "\u0120proportional": 27111, "uid": 27112, "\u0120pertaining": 27113, "\u0120Kindle": 27114, "\u0120Negro": 27115, "\u0120reiterated": 27116, "\u0120Tonight": 27117, "oths": 27118, "\u0120Cornell": 27119, "\u0120owing": 27120, "\u0120208": 27121, "elfare": 27122, "ocating": 27123, "\u0120Birds": 27124, "Subscribe": 27125, "\u0120essays": 27126, "\u0120burdens": 27127, "\u0120illustrations": 27128, "arious": 27129, "ERAL": 27130, "\u0120Calcul": 27131, "\u0120xen": 27132, "\u0120LinkedIn": 27133, "\u0120Jung": 27134, "\u0120redesign": 27135, "Connor": 27136, "296": 27137, "\u0120reversal": 27138, "\u0120Adelaide": 27139, "\u0120LL": 27140, "\u0120sinking": 27141, "\u0120gum": 27142, "USH": 27143, "capt": 27144, "\u0120Grimm": 27145, "\u0120footsteps": 27146, "\u0120CBD": 27147, "ispers": 27148, "\u0120prose": 27149, "Wednesday": 27150, "\u0120Movies": 27151, "edin": 27152, "\u0120overturned": 27153, "\u0120contentious": 27154, "USB": 27155, "~~~~~~~~~~~~~~~~": 27156, "\u0120Copper": 27157, "\u0120pointless": 27158, "NV": 27159, "values": 27160, "olphin": 27161, "dain": 27162, "\u0120deposited": 27163, "\u0120GW": 27164, "\u0120preceded": 27165, "\u0120Cla": 27166, "\u0120Golem": 27167, "\u0120Nim": 27168, "\u0120\u00ce\u00b2": 27169, "\u0120Engineers": 27170, "middle": 27171, "\u0120flatt": 27172, "operative": 27173, "\u0120councils": 27174, "imbabwe": 27175, "elin": 27176, "\u0120stressful": 27177, "\u0120LD": 27178, "\u0120resh": 27179, "lake": 27180, "\u0120wheelchair": 27181, "\u0120Alternative": 27182, "\u0120optimize": 27183, "operation": 27184, "\u0120peek": 27185, "\u0120oneself": 27186, "igil": 27187, "\u0120transitions": 27188, "opathy": 27189, "blank": 27190, "\u0120169": 27191, "171": 27192, "________________________________________________________________": 27193, "\u0120laundering": 27194, "Enc": 27195, "\u0120DEC": 27196, "\u0120workouts": 27197, "\u0120spikes": 27198, "\u0120dinosaurs": 27199, "\u0120discriminatory": 27200, "Pool": 27201, "Rather": 27202, "385": 27203, "RNA": 27204, "testers": 27205, "eto": 27206, "\u0120Identity": 27207, "\u0120vein": 27208, "\u0120Burton": 27209, "\u0120arcade": 27210, "420": 27211, "Ultimately": 27212, "\u0120Sadly": 27213, "\u00c3\u00b0": 27214, "pill": 27215, "\u0120cubic": 27216, "\u0120Spectrum": 27217, "these": 27218, "states": 27219, "\u0120unofficial": 27220, "hawks": 27221, "\u0120EVERY": 27222, "\u0120rainbow": 27223, "\u0120incarceration": 27224, "anding": 27225, "\u0120syll": 27226, "\u0120Everton": 27227, "\u0120179": 27228, "\u0120Serbia": 27229, "\u0120189": 27230, "meter": 27231, "\u0120Mickey": 27232, "\u0120antiqu": 27233, "\u0120factual": 27234, "neck": 27235, "\u0120Nare": 27236, "norm": 27237, "must": 27238, "\u0120highways": 27239, "\u0120glam": 27240, "\u0120dividing": 27241, "\u0120Squadron": 27242, "\u0120Martha": 27243, "\u0120births": 27244, "Cover": 27245, "////////////////": 27246, "\u0120Wong": 27247, "Phot": 27248, "\u0120ALS": 27249, "rio": 27250, "\u0120Nonetheless": 27251, "\u0120Lemon": 27252, "\u0120206": 27253, "\u0120EE": 27254, "\u0120derivative": 27255, "\u0120WWII": 27256, "vote": 27257, "\u0120therein": 27258, "\u0120separating": 27259, "446": 27260, "sync": 27261, "\u0120Streets": 27262, "\u0120ratt": 27263, "\u0120municipality": 27264, "\u0120Shortly": 27265, "\u0120monk": 27266, "),\"": 27267, "\u0120scrub": 27268, "\u0120operatives": 27269, "Neither": 27270, "Place": 27271, "\u0120Limit": 27272, "Female": 27273, "\u0120Actor": 27274, "Character": 27275, "\u0120constituted": 27276, "357": 27277, "\u0120protested": 27278, "\u0120Straw": 27279, "\u0120Height": 27280, "ilda": 27281, "\u0120Typh": 27282, "\u0120floods": 27283, "\u0120cosmetic": 27284, "WAY": 27285, "perture": 27286, "upon": 27287, "tons": 27288, "essing": 27289, "\u0120Pocket": 27290, "\u0120rooft": 27291, "\u0120Caucas": 27292, "\u0120antidepress": 27293, "\u0120incompatible": 27294, "ECD": 27295, "\u0120opera": 27296, "\u0120Contest": 27297, "\u0120generators": 27298, "lime": 27299, "Defense": 27300, "1987": 27301, "forum": 27302, "\u0120savage": 27303, "\u0120Hungarian": 27304, "nz": 27305, "\u0120metallic": 27306, "\u0120expelled": 27307, "\u0120residency": 27308, "\u0120dresses": 27309, "666": 27310, "\u0120Clement": 27311, "fires": 27312, "Category": 27313, "\u0120geek": 27314, "alis": 27315, "\u0120cemetery": 27316, "educated": 27317, "\u0120crawl": 27318, "\u0120Unable": 27319, "\u0120Tyson": 27320, "akis": 27321, "\u0120pardon": 27322, "\u0120Wra": 27323, "\u0120strengthened": 27324, "\u0120Fors": 27325, "335": 27326, "\u0120HC": 27327, "\u0120Mond": 27328, "\u0120visuals": 27329, "\u0120Beatles": 27330, "ettlement": 27331, "\u0120\u00ef": 27332, "gro": 27333, "\u0120bash": 27334, "\u0120poorest": 27335, "\u0120excel": 27336, "\u0120aspirations": 27337, "\u0120Municip": 27338, "ensible": 27339, "\u0120ceremonies": 27340, "\u0120intimidation": 27341, "\u0120CONTR": 27342, "beck": 27343, "\u0120Kap": 27344, "asu": 27345, "\u0120trademarks": 27346, "\u0120Sew": 27347, "\u0120Competition": 27348, "network": 27349, "\u0120Arri": 27350, "\u0120Tet": 27351, "Roaming": 27352, "WC": 27353, "Dat": 27354, "\u0120sob": 27355, "\u0120pairing": 27356, "\u0120overdose": 27357, "SAY": 27358, "aber": 27359, "\u0120revolt": 27360, "\u0120Fah": 27361, "acting": 27362, "eq": 27363, "estation": 27364, "Fight": 27365, "\u0120Marks": 27366, "273": 27367, "\u0120178": 27368, "Raw": 27369, "\u00e3\u0123\u012d": 27370, "349": 27371, "blocks": 27372, "\u0120verge": 27373, "estine": 27374, "\u0120Podesta": 27375, "\u0120invasive": 27376, "\u0120profoundly": 27377, "\u0120Ao": 27378, "each": 27379, "\u0120lest": 27380, "interpret": 27381, "\u0120shrinking": 27382, "\u0120errone": 27383, "\u0120chees": 27384, "lys": 27385, "\u0120Ivy": 27386, "\u0120Directory": 27387, "\u0120hinted": 27388, "VICE": 27389, "\u0120contacting": 27390, "\u0120Gent": 27391, "hei": 27392, "\u0120labeling": 27393, "\u0120mercury": 27394, "\u0120Lite": 27395, "\u0120expires": 27396, "\u0120destabil": 27397, "ritis": 27398, "cu": 27399, "\u0120feathers": 27400, "\u0120steer": 27401, "\u0120programmed": 27402, "\u0120Vader": 27403, "Going": 27404, "\u0120Elim": 27405, "\u0120yo": 27406, "\u0120Miche": 27407, "\u0120203": 27408, "\u0120sleeves": 27409, "\u0120bully": 27410, "\u0120Humans": 27411, "368": 27412, "\u0120compress": 27413, "\u0120Banner": 27414, "ARS": 27415, "\u0120awhile": 27416, "\u0120calib": 27417, "\u0120sponsorship": 27418, "\u0120Difficulty": 27419, "\u0120Papers": 27420, "\u0120identifier": 27421, "}.": 27422, "\u0120yog": 27423, "\u0120Shia": 27424, "\u0120cleanup": 27425, "\u0120vibe": 27426, "introdu": 27427, "imming": 27428, "Australia": 27429, "\u0120outlines": 27430, "\u0120Youtube": 27431, "train": 27432, "\u0120Makes": 27433, "\u0120deported": 27434, "\u0120centr": 27435, "\u0120Dug": 27436, "\u0120Boulder": 27437, "\u0120Buffy": 27438, "\u0120injunction": 27439, "\u0120Harley": 27440, "\u0120Groups": 27441, "\u0120Dumbledore": 27442, "\u0120Clara": 27443, "\u0120\"-": 27444, "\u0120sacrificed": 27445, "eph": 27446, "Shadow": 27447, "ibling": 27448, "\u0120freelance": 27449, "\u0120evidently": 27450, "phal": 27451, "\u0120retains": 27452, "Mir": 27453, "\u0120finite": 27454, "dar": 27455, "\u0120Cous": 27456, "\u0120repaired": 27457, "\u0120periodic": 27458, "\u0120championships": 27459, "\u0120asteroid": 27460, "blind": 27461, "\u0120expressly": 27462, "\u0120Astros": 27463, "\u0120scaled": 27464, "\u0120geographical": 27465, "\u0120Rapids": 27466, "Enjoy": 27467, "\u0120elastic": 27468, "\u0120Mohamed": 27469, "Market": 27470, "begin": 27471, "\u0120discovers": 27472, "\u0120telecommunications": 27473, "\u0120scanner": 27474, "\u0120enlarge": 27475, "\u0120sharks": 27476, "\u0120psychedel": 27477, "\u0120Rouge": 27478, "\u0120snapshot": 27479, "isine": 27480, "XP": 27481, "\u0120pesticides": 27482, "\u0120LSD": 27483, "\u0120Distribution": 27484, "really": 27485, "\u0120degradation": 27486, "\u0120disguise": 27487, "\u0120biom": 27488, "\u0120EXT": 27489, "\u0120equations": 27490, "\u0120hazards": 27491, "\u0120Compared": 27492, ")*": 27493, "\u0120virtues": 27494, "\u0120elders": 27495, "\u0120enhancing": 27496, "\u0120Across": 27497, "eros": 27498, "angling": 27499, "\u0120combust": 27500, "ucci": 27501, "\u0120concussion": 27502, "\u0120contraception": 27503, "\u0120Kang": 27504, "\u0120expresses": 27505, "\u0120aux": 27506, "\u0120Pione": 27507, "\u0120exhibits": 27508, "Debug": 27509, "OTAL": 27510, "\u0120Already": 27511, "\u0120Wheeler": 27512, "\u0120expands": 27513, "?:": 27514, "\u0120reconciliation": 27515, "\u0120pirates": 27516, "\u0120purse": 27517, "\u0120discourage": 27518, "\u0120spectacle": 27519, "Rank": 27520, "\u0120wraps": 27521, "\u0120Thought": 27522, "\u0120impending": 27523, "Opp": 27524, "\u0120Anglo": 27525, "\u0120EUR": 27526, "\u0120screwed": 27527, "retched": 27528, "\u0120encouragement": 27529, "models": 27530, "\u0120confuse": 27531, "mmm": 27532, "\u0120Vitamin": 27533, "\u00e2\u0138\u0133\u00e2\u0138\u0133": 27534, "Cru": 27535, "\u0120knights": 27536, "\u0120discard": 27537, "\u0120bishops": 27538, "\u0120Wear": 27539, "\u0120Garrett": 27540, "kan": 27541, "\u00e3\u0125\u0141": 27542, "\u0120masculine": 27543, "capital": 27544, "\u0120Aus": 27545, "\u0120fatally": 27546, "thanks": 27547, "\u0120AU": 27548, "\u0120Gut": 27549, "1200": 27550, "\u012000000000": 27551, "\u0120surrog": 27552, "\u0120BIOS": 27553, "raits": 27554, "\u0120Watts": 27555, "\u0120resurrection": 27556, "\u0120Electoral": 27557, "\u0120Tips": 27558, "4000": 27559, "\u0120nutrient": 27560, "\u0120depicting": 27561, "\u0120sprink": 27562, "\u0120muff": 27563, "\u0120LIM": 27564, "\u0120Sample": 27565, "psc": 27566, "ibi": 27567, "generated": 27568, "\u0120specimens": 27569, "\u0120dissatisf": 27570, "\u0120tailored": 27571, "\u0120holdings": 27572, "\u0120Monthly": 27573, "\u0120Eat": 27574, "poons": 27575, "\u0120nec": 27576, "\u0120Cage": 27577, "\u0120Lotus": 27578, "\u0120Lantern": 27579, "\u0120frontier": 27580, "\u0120pensions": 27581, "\u0120joked": 27582, "\u0120Hardy": 27583, "=-=-=-=-": 27584, "rade": 27585, "UID": 27586, "\u0120rails": 27587, "\u0120emit": 27588, "\u0120slate": 27589, "\u0120smug": 27590, "\u0120spit": 27591, "\u0120Calls": 27592, "\u0120Jacobs": 27593, "feat": 27594, "\u0120UE": 27595, "\u0120restruct": 27596, "\u0120regeneration": 27597, "\u0120energies": 27598, "\u0120Connor": 27599, "OHN": 27600, "\u0120Cheese": 27601, "\u0120ger": 27602, "\u0120resurrect": 27603, "management": 27604, "NW": 27605, "\u0120presently": 27606, "\u0120Bruins": 27607, "Member": 27608, "\u0120Mang": 27609, "idan": 27610, "\u0120boosting": 27611, "wyn": 27612, "+.": 27613, "requisite": 27614, "\u0120NYPD": 27615, "\u0120Megan": 27616, "\u0120Conditions": 27617, "\u0120pics": 27618, "nesium": 27619, "\u0120Rash": 27620, "\u0120174": 27621, "\u0120Ducks": 27622, "\u0120embro": 27623, "zu": 27624, "onian": 27625, "religious": 27626, "\u0120craz": 27627, "\u0120ACA": 27628, "\u0120Zucker": 27629, "EMA": 27630, "\u0120Pros": 27631, "Weapon": 27632, "\u0120Knox": 27633, "\u0120Arduino": 27634, "\u0120stove": 27635, "\u0120heavens": 27636, "\u0120Purchase": 27637, "\u0120herd": 27638, "\u0120fundraiser": 27639, "Digital": 27640, "5000": 27641, "\u0120proponents": 27642, "/\u00e2\u0122\u012d": 27643, "\u0120jelly": 27644, "\u0120Visa": 27645, "\u0120monks": 27646, "\u0120advancement": 27647, "\u0120Wer": 27648, "\u0120187": 27649, "eus": 27650, "ertility": 27651, "\u0120fetal": 27652, "\u01201936": 27653, "Lo": 27654, "\u0120outfits": 27655, "\u0120staircase": 27656, "bomb": 27657, "\u0120customized": 27658, "clair": 27659, "Tree": 27660, "\u0120mapped": 27661, "\u0120Considering": 27662, "\u0120Torres": 27663, "\u0120methyl": 27664, "\u0120approximate": 27665, "\u0120doom": 27666, "\u0120Hansen": 27667, "\u0120crossover": 27668, "\u0120standalone": 27669, "\u00e4\u00bc": 27670, "\u0120invites": 27671, "\u0120graveyard": 27672, "\u0120hp": 27673, "DonaldTrump": 27674, "\u0120escort": 27675, "Gar": 27676, "\u0120predecessors": 27677, "\u0120hay": 27678, "\u0120enzyme": 27679, "\u0120Straight": 27680, "visors": 27681, "Ing": 27682, "aneously": 27683, "\u0120Applied": 27684, "\u0120fec": 27685, "\u0120Durant": 27686, "\u0120outspoken": 27687, "orb": 27688, "\u0120zeal": 27689, "\u0120disgrace": 27690, "').": 27691, "\u0120Cheng": 27692, "289": 27693, "\u0120Rena": 27694, "\u0120Suicide": 27695, "294": 27696, "\u0120outraged": 27697, "\u0120Newman": 27698, "\u0120Nvidia": 27699, "\u0120Aber": 27700, "\u0120Bers": 27701, "\u0120recreation": 27702, "Window": 27703, "\u0120DP": 27704, "xe": 27705, "\u0120pedoph": 27706, "\u0120fallout": 27707, "amboo": 27708, "\u0120presentations": 27709, "\u0120Apps": 27710, "\u0120html": 27711, "345": 27712, "\u0120XXX": 27713, "\u0120rubbing": 27714, "\u0120Leather": 27715, "\u0120humidity": 27716, "seys": 27717, "established": 27718, "\u0120Units": 27719, "646": 27720, "\u0120respectable": 27721, "Auto": 27722, "\u0120thriving": 27723, "\u0120Innovation": 27724, "angs": 27725, "Extra": 27726, "regulation": 27727, "298": 27728, "pick": 27729, "Examples": 27730, "\u0120CJ": 27731, "Attack": 27732, "\u0120dracon": 27733, "LT": 27734, "\u0120sticker": 27735, "rers": 27736, "\u0120sunny": 27737, "Iss": 27738, "regulated": 27739, "dim": 27740, "\u0120Abstract": 27741, "\u0120husbands": 27742, "Office": 27743, "omination": 27744, "itars": 27745, "ANGE": 27746, "ascal": 27747, "\u0120Kris": 27748, "\u0120Infantry": 27749, "\u0120malf": 27750, "\u0120Athe": 27751, "\u0120Rally": 27752, "balanced": 27753, "........................": 27754, "OUP": 27755, "\u0120molecule": 27756, "metics": 27757, "\u0120Split": 27758, "\u0120Instructions": 27759, "\u0120Nights": 27760, "cards": 27761, "\u0120tug": 27762, "\u0120cone": 27763, "\u00e5\u0143": 27764, "\u0120tx": 27765, "\u0120Discussion": 27766, "\u0120catastrophe": 27767, "ppe": 27768, "gio": 27769, "\u0120communism": 27770, "\u0120halted": 27771, "\u0120Guant": 27772, "clean": 27773, "\u0120Sched": 27774, "\u0120Kanye": 27775, "\u0120wander": 27776, "\u0120Seriously": 27777, "\u0120188": 27778, "ennial": 27779, "follow": 27780, "productive": 27781, "\u0120Flow": 27782, "\u0120Sail": 27783, "\u0120craw": 27784, "\u0120simulations": 27785, "oru": 27786, "angles": 27787, "\u0120Nolan": 27788, "\u0120menstru": 27789, "470": 27790, "\u0120207": 27791, "aja": 27792, "\u0120casually": 27793, "boarding": 27794, "\u0120222": 27795, "ovy": 27796, "\u0120Numbers": 27797, "umat": 27798, "OE": 27799, "287": 27800, "\u0120Clemson": 27801, "\u0120certs": 27802, "\u0120slid": 27803, "\u0120Tribe": 27804, "\u0120toast": 27805, "\u0120fortunes": 27806, "\u0120fals": 27807, "\u0120Committees": 27808, "\u0120gp": 27809, "\u0120fiery": 27810, "\u0120Nets": 27811, "\u0120Anime": 27812, "Package": 27813, "\u0120Compare": 27814, "laughter": 27815, "infect": 27816, "\u0120atrocities": 27817, "\u0120justices": 27818, "\u0120insults": 27819, "\u0120Vernon": 27820, "\u0120shaken": 27821, "\u0120persona": 27822, "estamp": 27823, "367": 27824, "brain": 27825, "\u0120experimenting": 27826, "Ken": 27827, "\u0120Electronics": 27828, "\u0120161": 27829, "domain": 27830, "\u0120graphical": 27831, "bishop": 27832, "\u0120whopping": 27833, "\u0120Evangel": 27834, "\u0120advertisers": 27835, "\u0120Spear": 27836, "\u0120bids": 27837, "\u0120destroys": 27838, "utz": 27839, "\u0120undersc": 27840, "\u0120ADD": 27841, "\u0120ants": 27842, "\u0120Cum": 27843, "ipples": 27844, "\u0120Fill": 27845, "\u0120glanced": 27846, "\u0120indicted": 27847, "\u0120Eff": 27848, "\u0120miscon": 27849, "\u0120Desktop": 27850, "\u0120abide": 27851, "\u00e3\u0125\u0122": 27852, "\u0120Io": 27853, "\u0120Coul": 27854, "\u0120capsule": 27855, "\u0120Chrys": 27856, "MON": 27857, "\u0120undes": 27858, "\u0120IRA": 27859, "\u0120citation": 27860, "\u0120dictate": 27861, "\u0120Networks": 27862, "\u0120Conflict": 27863, "\u0120Stuff": 27864, "xa": 27865, "isec": 27866, "\u0120Chemistry": 27867, "\u0120quarterly": 27868, "Williams": 27869, "anan": 27870, "Opt": 27871, "\u0120Alexandria": 27872, "outheastern": 27873, "\u0120Springfield": 27874, "\u0120Blacks": 27875, "\u0120geography": 27876, "242": 27877, "\u0120utmost": 27878, "\u0120Exxon": 27879, "abouts": 27880, "EVA": 27881, "\u0120Enable": 27882, "\u0120Barr": 27883, "\u0120disagreed": 27884, "\u0120Cyprus": 27885, "\u0120dementia": 27886, "\u0120labs": 27887, "\u0120ubiquitous": 27888, "\u0120LOVE": 27889, "\u0120consolidated": 27890, "sr": 27891, "\u0120creamy": 27892, "\u0120Timber": 27893, "Regardless": 27894, "\u0120Certificate": 27895, "\u0120\"...": 27896, "ogenous": 27897, "Captain": 27898, "\u0120insulting": 27899, "\u0120Soros": 27900, "\u0120Instr": 27901, "\u0120Bulgaria": 27902, "better": 27903, "\u0120sucking": 27904, "\u0120Davidson": 27905, "atz": 27906, "\u0120collateral": 27907, "gif": 27908, "\u0120plagued": 27909, "\u0120Cancel": 27910, "\u0120Gardner": 27911, "RB": 27912, "\u0120sixteen": 27913, "Remove": 27914, "uristic": 27915, "cook": 27916, "Rod": 27917, "\u0120comprising": 27918, "fle": 27919, ")\u00e2\u0122\u0136": 27920, "\u0120Viking": 27921, "growth": 27922, "agonal": 27923, "\u0120srf": 27924, "afety": 27925, "mot": 27926, "Nearly": 27927, "stown": 27928, "\u0120Factor": 27929, "\u0120automobile": 27930, "\u0120procedural": 27931, "mask": 27932, "ampires": 27933, "\u0120disappears": 27934, "jab": 27935, "315": 27936, "\u01201951": 27937, "needed": 27938, "\u0120daring": 27939, "leader": 27940, "\u0120podium": 27941, "\u0120unhealthy": 27942, "\u0120mund": 27943, "\u0120pyramid": 27944, "ocre": 27945, "\u0120kissed": 27946, "\u0120dreamed": 27947, "\u0120Fantastic": 27948, "\u0120Gly": 27949, "\u00e5\u012c": 27950, "\u0120greatness": 27951, "\u0120spices": 27952, "\u0120metropolitan": 27953, "\u0120compuls": 27954, "iets": 27955, "1016": 27956, "\u0120Sham": 27957, "\u0120Pyr": 27958, "flies": 27959, "\u0120Midnight": 27960, "\u0120swallowed": 27961, "\u0120genres": 27962, "\u0120Lucky": 27963, "\u0120Rewards": 27964, "\u0120dispatch": 27965, "\u0120IPA": 27966, "\u0120Apply": 27967, "\u0120aven": 27968, "alities": 27969, "312": 27970, "things": 27971, "\u0120().": 27972, "\u0120mates": 27973, "\u0120Sz": 27974, "\u0120COP": 27975, "olate": 27976, "OFF": 27977, "\u0120recharge": 27978, "caps": 27979, "\u0120Yorker": 27980, "icone": 27981, "\u0120galaxies": 27982, "ileaks": 27983, "Dave": 27984, "\u0120Puzz": 27985, "\u0120Celtic": 27986, "\u0120AFC": 27987, "276": 27988, "\u0120Sons": 27989, "\u0120affirmative": 27990, "Hor": 27991, "\u0120tutorials": 27992, "\u0120CITY": 27993, "\u0120Rosa": 27994, "\u0120Extension": 27995, "Series": 27996, "\u0120fats": 27997, "\u0120rab": 27998, "lis": 27999, "\u0120unic": 28000, "\u0120eve": 28001, "\u0120Spin": 28002, "\u0120adulthood": 28003, "typ": 28004, "\u0120sectarian": 28005, "\u0120checkout": 28006, "\u0120Cycl": 28007, "Single": 28008, "\u0120martyr": 28009, "\u0120chilling": 28010, "888": 28011, "oufl": 28012, "\u0120];": 28013, "\u0120congestion": 28014, "mk": 28015, "\u0120Whereas": 28016, "\u01201938": 28017, "urrencies": 28018, "erion": 28019, "\u0120boast": 28020, "\u0120Patients": 28021, "\u0120chap": 28022, "\u0120BD": 28023, "realDonaldTrump": 28024, "\u0120examines": 28025, "hov": 28026, "\u0120startling": 28027, "\u0120Babylon": 28028, "wid": 28029, "omew": 28030, "brance": 28031, "\u0120Odyssey": 28032, "wig": 28033, "\u0120torch": 28034, "\u0120Vox": 28035, "\u0120Moz": 28036, "\u0120Troll": 28037, "\u0120Ans": 28038, "Similarly": 28039, "\u0120Ful": 28040, "006": 28041, "Unless": 28042, "\u0120Alone": 28043, "stead": 28044, "\u0120Publisher": 28045, "rights": 28046, "tu": 28047, "\u0120Doesn": 28048, "\u0120professionally": 28049, "\u0120clo": 28050, "icz": 28051, "\u0120steals": 28052, "\u0120\u00e1": 28053, "1986": 28054, "\u0120sturdy": 28055, "\u0120Johann": 28056, "\u0120medals": 28057, "\u0120filings": 28058, "\u0120Fraser": 28059, "done": 28060, "\u0120multinational": 28061, "\u0120feder": 28062, "\u0120worthless": 28063, "\u0120pest": 28064, "Yesterday": 28065, "ankind": 28066, "\u0120gays": 28067, "\u0120borne": 28068, "\u0120POS": 28069, "Picture": 28070, "\u0120percentages": 28071, "251": 28072, "rame": 28073, "\u0120potions": 28074, "AMD": 28075, "\u0120Lebanese": 28076, "\u0120rang": 28077, "\u0120LSU": 28078, "ongs": 28079, "\u0120peninsula": 28080, "\u0120Clause": 28081, "ALK": 28082, "oha": 28083, "\u0120MacBook": 28084, "\u0120unanimous": 28085, "\u0120lenders": 28086, "\u0120hangs": 28087, "\u0120franchises": 28088, "orers": 28089, "\u0120Updates": 28090, "\u0120isolate": 28091, "andro": 28092, "Soon": 28093, "\u0120disruptive": 28094, "\u0120Surve": 28095, "\u0120stitches": 28096, "\u0120Scorp": 28097, "\u0120Dominion": 28098, "\u0120supplying": 28099, "Arg": 28100, "\u0120turret": 28101, "\u0120Luk": 28102, "\u0120brackets": 28103, "*)": 28104, "\u0120Revolutionary": 28105, "\u0120Honest": 28106, "\u0120noticing": 28107, "\u0120Shannon": 28108, "\u0120afforded": 28109, "\u0120tha": 28110, "\u0120Janet": 28111, "!--": 28112, "\u0120Narendra": 28113, "\u0120Plot": 28114, "Hol": 28115, "sever": 28116, "eenth": 28117, "\u0120obstruction": 28118, "\u01201024": 28119, "staff": 28120, "jas": 28121, "orget": 28122, "scenes": 28123, "laughs": 28124, "\u0120Fargo": 28125, "crime": 28126, "\u0120orchestr": 28127, "\u0120delet": 28128, "iliary": 28129, "rieved": 28130, "\u0120militar": 28131, "\u0120Greene": 28132, "\u00e2\u0139\u0131": 28133, "\u00e3\u0123\u00a6": 28134, "\u0120Guards": 28135, "\u0120unleashed": 28136, "\u0120Weber": 28137, "\u0120adjustable": 28138, "\u0120caliber": 28139, "\u0120motivations": 28140, "\u0120\u00c3\u0142": 28141, "mAh": 28142, "\u0120Lanka": 28143, "handle": 28144, "\u0120pent": 28145, "\u0120Rav": 28146, "\u0120Angular": 28147, "\u0120Kau": 28148, "umbing": 28149, "\u0120philanthrop": 28150, "\u0120dehyd": 28151, "\u0120toxicity": 28152, "eer": 28153, "\u0120YORK": 28154, "witz": 28155, "\u00e5\u00bc": 28156, "\u0120IE": 28157, "community": 28158, "\u0120AH": 28159, "\u0120retali": 28160, "\u0120massively": 28161, "\u0120Daniels": 28162, "\u0120DEL": 28163, "\u0120carcin": 28164, "Url": 28165, "\u0120routing": 28166, "\u0120NPCs": 28167, "\u0120RAF": 28168, "ryce": 28169, "\u0120waived": 28170, "\u0120Guatem": 28171, "Everybody": 28172, "\u0120covenant": 28173, "\u0120173": 28174, "\u0120relaxing": 28175, "\u0120quart": 28176, "almost": 28177, "\u0120guarded": 28178, "\u0120Soldiers": 28179, "\u0120PLAY": 28180, "\u0120outgoing": 28181, "LAND": 28182, "\u0120rewrite": 28183, "\u0120MOV": 28184, "\u0120Imper": 28185, "\u0120Solution": 28186, "\u0120phenomenal": 28187, "\u0120longevity": 28188, "\u0120impat": 28189, "\u0120Nissan": 28190, "irie": 28191, "\u0120odor": 28192, "\u0120Zar": 28193, "oks": 28194, "\u0120militias": 28195, "\u0120SPEC": 28196, "\u0120tolerated": 28197, "arser": 28198, "\u0120Bradford": 28199, "+,": 28200, "\u0120surreal": 28201, "sf": 28202, "Canadian": 28203, "\u0120resemblance": 28204, "\u0120carbohydrate": 28205, "VIEW": 28206, "\u0120accessory": 28207, "meal": 28208, "largest": 28209, "iegel": 28210, "Someone": 28211, "\u0120toughest": 28212, "oso": 28213, "\u0120funnel": 28214, "\u0120condemnation": 28215, "luent": 28216, "\u0120wired": 28217, "\u0120Sunset": 28218, "Jesus": 28219, "\u0120PST": 28220, "\u0120Pages": 28221, "\u0120Tycoon": 28222, "\u0120PF": 28223, "\u0120selections": 28224, "\u0120\u00e0\u00a4": 28225, "partisan": 28226, "\u0120highs": 28227, "\u0120Rune": 28228, "\u0120crafts": 28229, "lead": 28230, "\u0120Parents": 28231, "\u0120reclaim": 28232, "eker": 28233, "\u0120Allied": 28234, "aeper": 28235, "\u0120looming": 28236, "\u0120beneficiaries": 28237, "\u0120Hull": 28238, "Students": 28239, "Jewish": 28240, "dj": 28241, "\u0120pact": 28242, "template": 28243, "\u0120Officials": 28244, "\u0120Baylor": 28245, "\u0120hemp": 28246, "\u0120youths": 28247, "\u0120Levels": 28248, "\u0120Xiao": 28249, "\u0120Ches": 28250, "\u0120endeavor": 28251, "\u0120Removed": 28252, "\u0120hippocamp": 28253, "Hell": 28254, "\u00e3\u0124\u012c": 28255, "805": 28256, "\u0120dinosaur": 28257, "\u0120Wrath": 28258, "\u0120Indonesian": 28259, "\u0120calculator": 28260, "\u0120Dictionary": 28261, "\u0120420": 28262, "\u0120MAG": 28263, "(_": 28264, "!,": 28265, "tarians": 28266, "\u0120restricting": 28267, "racuse": 28268, "\u0120weekday": 28269, "OUNT": 28270, "\u0120shrugged": 28271, "leground": 28272, "\u0120bald": 28273, "\u0120Doctors": 28274, "\u0120touted": 28275, "\u0120Maxwell": 28276, "\u0120214": 28277, "\u0120diplomat": 28278, "\u0120repression": 28279, "\u0120constituency": 28280, "vice": 28281, "ranked": 28282, "\u0120Napoleon": 28283, "gang": 28284, "\u0120Forever": 28285, "tun": 28286, "\u0120bulb": 28287, "\u0120PDT": 28288, "\u0120Cisco": 28289, "VEN": 28290, "\u0120resumed": 28291, "Steven": 28292, "\u0120Manitoba": 28293, "\u0120fabulous": 28294, "\u0120Agents": 28295, "1984": 28296, "\u0120amusing": 28297, "\u0120Mysteries": 28298, "\u0120orthodox": 28299, "floor": 28300, "\u0120questionnaire": 28301, "\u0120penetrate": 28302, "\u0120filmmakers": 28303, "\u0120Unc": 28304, "\u0120stamped": 28305, "\u0120thirteen": 28306, "\u0120outfield": 28307, "\u0120forwarded": 28308, "\u0120appra": 28309, "\u0120aided": 28310, "try": 28311, "\u0120unfocused": 28312, "\u0120Liz": 28313, "\u0120Wendy": 28314, "\u0120Scene": 28315, "Charg": 28316, "\u0120rejects": 28317, "\u0120leftist": 28318, "\u0120Providence": 28319, "\u0120Brid": 28320, "regn": 28321, "\u0120prophecy": 28322, "\u0120LIVE": 28323, "499": 28324, "\u0120forge": 28325, "\u0120FML": 28326, "\u0120intrinsic": 28327, "\u0120Frog": 28328, "\u0120wont": 28329, "\u0120Holt": 28330, "\u0120famed": 28331, "CLUS": 28332, "aepernick": 28333, "\u0120Hate": 28334, "\u0120Cay": 28335, "\u0120registering": 28336, "ortality": 28337, "ropy": 28338, "ocalyptic": 28339, "aan": 28340, "nav": 28341, "\u0120fascist": 28342, "IFIED": 28343, "\u0120implicated": 28344, "\u0120Resort": 28345, "\u0120Chandler": 28346, "\u0120Brick": 28347, "Pin": 28348, "ysc": 28349, "Usage": 28350, "\u0120Helm": 28351, "usra": 28352, "\u00e2\u013a\u0127\u00e2\u013a\u0127": 28353, "\u0120Abbas": 28354, "\u0120unanimously": 28355, "\u0120keeper": 28356, "\u0120addicted": 28357, "???": 28358, "\u0120helmets": 28359, "\u0120antioxid": 28360, "apsed": 28361, "808": 28362, "giene": 28363, "\u0120waits": 28364, "\u0120minion": 28365, "raved": 28366, "\u0120Porsche": 28367, "\u0120dreaming": 28368, "\u0120171": 28369, "\u0120Cain": 28370, "\u0120unfor": 28371, "asso": 28372, "\u0120Configuration": 28373, "kun": 28374, "hardt": 28375, "\u0120nested": 28376, "\u0120LDS": 28377, "LES": 28378, "\u0120tying": 28379, "enos": 28380, "\u0120cue": 28381, "\u0120Marqu": 28382, "skirts": 28383, "\u0120clicked": 28384, "\u0120expiration": 28385, "\u0120Accordingly": 28386, "\u0120WC": 28387, "\u0120blessings": 28388, "\u0120addictive": 28389, "\u0120Narr": 28390, "yx": 28391, "\u0120Jaguars": 28392, "\u0120rents": 28393, "\u0120Siber": 28394, "\u0120tipped": 28395, "ousse": 28396, "\u0120Fitzgerald": 28397, "\u0120hierarch": 28398, "outine": 28399, "\u0120wavelength": 28400, ">.": 28401, "chid": 28402, "\u0120Processing": 28403, "/+": 28404, "ranking": 28405, "Easy": 28406, "\u0120Construct": 28407, "\u0120tet": 28408, "insured": 28409, "HUD": 28410, "\u0120quoting": 28411, "\u0120communicated": 28412, "inx": 28413, "\u0120inmate": 28414, "\u0120erected": 28415, "\u0120Absolutely": 28416, "\u0120Surely": 28417, "\u0120unim": 28418, "\u0120Throne": 28419, "heid": 28420, "\u0120claws": 28421, "\u0120superstar": 28422, "\u0120Lenn": 28423, "\u0120Whis": 28424, "Uk": 28425, "abol": 28426, "\u0120sket": 28427, "\u0120Niet": 28428, "\u0120perks": 28429, "\u0120affinity": 28430, "\u0120openings": 28431, "phasis": 28432, "\u0120discriminate": 28433, "Tip": 28434, "vc": 28435, "\u0120grinding": 28436, "\u0120Jenny": 28437, "\u0120asthma": 28438, "holes": 28439, "\u0120Homer": 28440, "\u0120registers": 28441, "\u0120Glad": 28442, "\u0120creations": 28443, "\u0120lithium": 28444, "\u0120applause": 28445, "until": 28446, "Justice": 28447, "\u0120Turks": 28448, "\u0120scandals": 28449, "\u0120bake": 28450, "tank": 28451, "Mech": 28452, "\u0120Means": 28453, "\u0120Maid": 28454, "Republicans": 28455, "isal": 28456, "windows": 28457, "\u0120Santos": 28458, "\u0120vegetation": 28459, "338": 28460, "tri": 28461, "\u0120flux": 28462, "insert": 28463, "\u0120clarified": 28464, "\u0120mortg": 28465, "\u0120Chim": 28466, "\u0120Tort": 28467, "\u0120disclaim": 28468, "metal": 28469, "\u0120Aside": 28470, "\u0120induction": 28471, "\u0120infl": 28472, "\u0120atheists": 28473, "amph": 28474, "\u0120ether": 28475, "\u0120Vital": 28476, "\u0120Built": 28477, "Mind": 28478, "\u0120weaponry": 28479, "SET": 28480, "\u0120186": 28481, "admin": 28482, "gam": 28483, "contract": 28484, "afa": 28485, "\u0120derivatives": 28486, "\u0120snacks": 28487, "\u0120churn": 28488, "Econom": 28489, "\u0120capped": 28490, "\u0120Understanding": 28491, "\u0120Hers": 28492, "\u0120Iz": 28493, "\u0120duct": 28494, "IENT": 28495, "aughty": 28496, "\u0120\u00e2\u013e\u0136": 28497, "\u0120NP": 28498, "\u0120sailing": 28499, "Initialized": 28500, "\u0120ted": 28501, "\u0120reactors": 28502, "\u0120Lomb": 28503, "\u0120choke": 28504, "\u0120Worm": 28505, "\u0120admiration": 28506, "\u0120swung": 28507, "ensibly": 28508, "\u0120rash": 28509, "\u0120Goals": 28510, "\u0120Important": 28511, "Shot": 28512, "\u0120Ras": 28513, "\u0120trainers": 28514, "\u0120Bun": 28515, "Working": 28516, "\u0120harmed": 28517, "\u0120Pandora": 28518, "\u0120LTE": 28519, "\u0120mushroom": 28520, "\u0120CHAR": 28521, "\u0120Fee": 28522, "\u0120Moy": 28523, "Born": 28524, "oliberal": 28525, "\u0120Martial": 28526, "\u0120gentlemen": 28527, "\u0120lingering": 28528, "Official": 28529, "\u0120graffiti": 28530, "\u0120Names": 28531, "Der": 28532, "\u0120quint": 28533, "istrate": 28534, "azeera": 28535, "\u0120NOTICE": 28536, "\u0120Florence": 28537, "\u0120payable": 28538, "\u0120depicts": 28539, "\u0120Species": 28540, "Heart": 28541, "\u00e2\u0136\u0122\u00e2\u0136\u0122\u00e2\u0136\u0122\u00e2\u0136\u0122\u00e2\u0136\u0122\u00e2\u0136\u0122\u00e2\u0136\u0122\u00e2\u0136\u0122": 28542, "\u0120enclosed": 28543, "Increases": 28544, "Daily": 28545, "\u0120Lis": 28546, "\u0120enactment": 28547, "\u0120Bacon": 28548, "\u0120Steele": 28549, "demand": 28550, "\u0120183": 28551, "\u0120mouths": 28552, "\u0120stranded": 28553, "\u0120enhancement": 28554, "011": 28555, "\u0120Whats": 28556, "\u0120healed": 28557, "eny": 28558, "\u0120Rab": 28559, "\u0120340": 28560, "\u0120Labyrinth": 28561, "roach": 28562, "\u0120Yosh": 28563, "\u0120Clippers": 28564, "\u0120concerts": 28565, "Internet": 28566, "355": 28567, "\u0120stickers": 28568, "\u0120termed": 28569, "\u0120Axe": 28570, "\u0120grandparents": 28571, "France": 28572, "\u0120Clim": 28573, "\u0120Uh": 28574, "ulic": 28575, "\u0120thrill": 28576, "centric": 28577, "\u0120Overview": 28578, "\u0120Conduct": 28579, "\u0120substantive": 28580, "\u0120182": 28581, "mur": 28582, "\u0120stray": 28583, "\u0120Coff": 28584, "\u0120repetitive": 28585, "\u0120Forgotten": 28586, "\u0120qualification": 28587, "ewitness": 28588, "\u0120Zimbabwe": 28589, "\u0120simulated": 28590, "\u0120JD": 28591, "253": 28592, "\u0120Ware": 28593, "\u0120unsc": 28594, "Times": 28595, "\u0120summons": 28596, "\u0120disconnected": 28597, "\u0120184": 28598, "cius": 28599, "\u0120Gujar": 28600, "odka": 28601, "\u0120erase": 28602, "\u0120Tobacco": 28603, "elected": 28604, "\u0120uncont": 28605, "\u0120Shepard": 28606, "\u0120Lamp": 28607, "\u0120alerted": 28608, "\u0120operative": 28609, "arna": 28610, "uint": 28611, "\u0120negligence": 28612, "acements": 28613, "\u0120supra": 28614, "\u0120prevail": 28615, "\u0120Shark": 28616, "\u0120belts": 28617, "\u00e3\u0123\u00ab": 28618, "\u0120tighter": 28619, "Engineers": 28620, "\u0120inactive": 28621, "\u0120exponent": 28622, "\u0120Willie": 28623, "aples": 28624, "\u0120heir": 28625, "\u0120Hits": 28626, "iann": 28627, "\u0120Says": 28628, "\u0120currents": 28629, "\u0120Bengal": 28630, "\u0120arist": 28631, "Buffer": 28632, "\u0120breeze": 28633, "\u0120Wesley": 28634, "Cola": 28635, "\u0120pronoun": 28636, "\u0120deed": 28637, "\u0120Kling": 28638, "\u0120oft": 28639, "\u0120inflict": 28640, "\u0120punishing": 28641, "\u0120nm": 28642, "iku": 28643, "ODUCT": 28644, "014": 28645, "\u0120subsidy": 28646, "\u0120DEA": 28647, "\u0120Herbert": 28648, "\u0120Jal": 28649, "Bank": 28650, "\u0120deferred": 28651, "\u0120shipment": 28652, "Bott": 28653, "\u0120alle": 28654, "bearing": 28655, "HTML": 28656, "Offline": 28657, "\u0120213": 28658, "\u0120scrolling": 28659, "\u0120scanned": 28660, "\u0120Libyan": 28661, "\u0120TOP": 28662, "chrom": 28663, "dt": 28664, "column": 28665, "PsyNetMessage": 28666, "Zero": 28667, "\u0120torso": 28668, "050": 28669, "\u00e2\u0137\u0132": 28670, "\u0120imperson": 28671, "\u0120Schwartz": 28672, "udic": 28673, "\u0120pissed": 28674, "\u0120Sapp": 28675, "257": 28676, "\u0120ISPs": 28677, "ogl": 28678, "\u0120supervised": 28679, "\u0120adolescent": 28680, "\u0120attained": 28681, "\u0120Delivery": 28682, "\u0120Bunny": 28683, "\u01201937": 28684, "\u0120miniature": 28685, "\u0120os": 28686, "\u0120370": 28687, "608": 28688, "\u0120Mourinho": 28689, "\u0120innate": 28690, "\u0120tempo": 28691, "\u0120NM": 28692, "\u0120Fallen": 28693, "009": 28694, "\u0120provocative": 28695, "Streamer": 28696, "\u0120Benedict": 28697, "\u0120Bolshe": 28698, "\u0120turtle": 28699, "\u0120PCB": 28700, "\u0120Equal": 28701, "Director": 28702, "\u0120Rend": 28703, "\u0120fluids": 28704, "Authorities": 28705, "\u0120cousins": 28706, "requency": 28707, "\u0120Neighbor": 28708, "sets": 28709, "shared": 28710, "Charles": 28711, "password": 28712, "\u0120gears": 28713, "\u0120211": 28714, "\u0120Hardware": 28715, "rika": 28716, "\u0120upstream": 28717, "Hom": 28718, "\u0120disproportionately": 28719, "ivities": 28720, "\u0120undefined": 28721, "\u0120electrons": 28722, "\u0120commemor": 28723, "Eventually": 28724, "\u0120><": 28725, "\u0120irresponsible": 28726, "218": 28727, "\u0120Released": 28728, "\u0120OVER": 28729, "\u0120IGN": 28730, "\u0120Bread": 28731, "stellar": 28732, "\u0120Sage": 28733, "tted": 28734, "damage": 28735, "edition": 28736, "\u0120Prec": 28737, "\u0120lime": 28738, "\u0120confinement": 28739, "\u0120calorie": 28740, "weapon": 28741, "\u0120differing": 28742, "\u0120Sina": 28743, "mys": 28744, "amd": 28745, "\u0120intricate": 28746, "kk": 28747, "\u0120PAT": 28748, "\u00c3\u00a3o": 28749, "stones": 28750, "links": 28751, "\u0120ranch": 28752, "Semitic": 28753, "\u0120differentiate": 28754, "\u0120Singer": 28755, "occupied": 28756, "\u0120fortress": 28757, "cmd": 28758, "\u0120interception": 28759, "\u0120Ankara": 28760, "\u0120rept": 28761, "\u0120Solitaire": 28762, "\u0120remake": 28763, "pred": 28764, "\u0120dared": 28765, "autions": 28766, "\u0120BACK": 28767, "Running": 28768, "\u0120debugging": 28769, "\u0120graphs": 28770, "399": 28771, "\u0120Nigel": 28772, "\u0120bun": 28773, "\u0120pillow": 28774, "\u0120progressed": 28775, "fashioned": 28776, "\u0120obedience": 28777, "ERN": 28778, "\u0120rehears": 28779, "Cell": 28780, "tl": 28781, "Sher": 28782, "\u0120herald": 28783, "\u0120Payment": 28784, "\u0120Cory": 28785, "\u0120Dept": 28786, "\u0120repent": 28787, "\u0120Weak": 28788, "uckland": 28789, "\u0120pleasing": 28790, "\u0120shortages": 28791, "\u0120jurors": 28792, "\u0120Kab": 28793, "qqa": 28794, "Anti": 28795, "\u0120wow": 28796, "\u0120RCMP": 28797, "\u0120tsun": 28798, "\u0120Sic": 28799, "\u0120comprises": 28800, "\u0120spies": 28801, "\u0120precinct": 28802, "nu": 28803, "\u0120urges": 28804, "\u0120timed": 28805, "\u0120stripes": 28806, "\u0120Boots": 28807, "\u0120yen": 28808, "Advanced": 28809, "\u0120discrete": 28810, "\u0120Archangel": 28811, "employment": 28812, "Diff": 28813, "\u0120monuments": 28814, "\u0120209": 28815, "worker": 28816, "\u0120196": 28817, "\u0120Ig": 28818, "utterstock": 28819, "TPS": 28820, "Jac": 28821, "\u0120homelessness": 28822, "\u0120commentator": 28823, "\u0120racially": 28824, "fing": 28825, "seed": 28826, "Ele": 28827, "ellation": 28828, "\u0120ethanol": 28829, "\u0120parish": 28830, "\u0120Dong": 28831, "\u0120Awakening": 28832, "\u0120deviation": 28833, "\u0120Bearing": 28834, "\u0120Tsuk": 28835, "\u0120recess": 28836, "\u0120lymph": 28837, "\u0120Cannabis": 28838, "\u00e5\u013e": 28839, "\u0120NEWS": 28840, "\u0120dra": 28841, "\u0120Stefan": 28842, "\u0120Wrong": 28843, "\u0120SAM": 28844, "\u0120loosely": 28845, "\u0120interpreter": 28846, "\u0120Plain": 28847, "Government": 28848, "\u0120bigotry": 28849, "\u0120grenades": 28850, "avez": 28851, "pictured": 28852, "\u0120mandated": 28853, "\u0120Monk": 28854, "\u0120Pedro": 28855, "\u0120lava": 28856, "274": 28857, "\u0120cynical": 28858, "\u0120Scrolls": 28859, "locks": 28860, "Mp": 28861, "\u0120congregation": 28862, "ornings": 28863, "phil": 28864, "\u0120Ibid": 28865, "\u0120ferv": 28866, "\u0120disappearing": 28867, "\u0120arrogant": 28868, "syn": 28869, "\u0120Maver": 28870, "\u0120Suit": 28871, "241": 28872, "\u0120abbre": 28873, "ackers": 28874, "Pa": 28875, "\u0120Yel": 28876, "Whenever": 28877, "\u0120235": 28878, "\u0120Vine": 28879, "\u0120Anat": 28880, "\u0120extinct": 28881, "LET": 28882, "\u0120executable": 28883, "VERS": 28884, "oxide": 28885, "DNA": 28886, "\u0120Prel": 28887, "\u0120resentment": 28888, "\u0120comprise": 28889, "\u0120Aviv": 28890, "\u0120interceptions": 28891, "\u0120prolific": 28892, "INA": 28893, "\u0120Erin": 28894, "thought": 28895, "219": 28896, "\u0120Psychiatry": 28897, "unky": 28898, "chemist": 28899, "Ho": 28900, "\u0120McCoy": 28901, "\u0120bricks": 28902, "Los": 28903, "rily": 28904, "\u0120USSR": 28905, "\u0120rud": 28906, "\u0120laud": 28907, "\u0120Wise": 28908, "\u0120Emerald": 28909, "\u0120revived": 28910, "\u0120damned": 28911, "\u0120Repair": 28912, "idem": 28913, "ctica": 28914, "\u0120patriarch": 28915, "\u0120Nurs": 28916, "meg": 28917, "\u0120cheapest": 28918, "reements": 28919, "empty": 28920, "\u0120Celebr": 28921, "\u0120deprivation": 28922, "chanted": 28923, "\u0120Thumbnails": 28924, "Energy": 28925, "\u0120Ethan": 28926, "\u0120Qing": 28927, "\u0120opposes": 28928, "WIND": 28929, "vik": 28930, "\u0120Mau": 28931, "\u0120SUB": 28932, "667": 28933, "GRE": 28934, "\u0120Volunte": 28935, "nton": 28936, "Cook": 28937, "\u00e5\u0132": 28938, "esque": 28939, "\u0120plummet": 28940, "\u0120suing": 28941, "\u0120pronounce": 28942, "\u0120resisting": 28943, "\u0120Fishing": 28944, "\u0120Trials": 28945, "\u0120yell": 28946, "\u0120310": 28947, "\u0120induct": 28948, "\u0120personalized": 28949, "often": 28950, "Reb": 28951, "EMBER": 28952, "\u0120viewpoint": 28953, "\u0120existential": 28954, "())": 28955, "remove": 28956, "MENTS": 28957, "lasses": 28958, "\u0120evapor": 28959, "\u0120aisle": 28960, "meta": 28961, "\u0120reflective": 28962, "\u0120entitlement": 28963, "\u0120devised": 28964, "music": 28965, "ascade": 28966, "\u0120winding": 28967, "offset": 28968, "\u0120accessibility": 28969, "kered": 28970, "Better": 28971, "\u0120Johnston": 28972, "thinking": 28973, "Snow": 28974, "\u0120Croatia": 28975, "\u0120Atomic": 28976, "271": 28977, "348": 28978, "\u0120textbook": 28979, "\u0120Sixth": 28980, "\u0120\u00d8\u00a7\u00d9\u0126": 28981, "\u0120slider": 28982, "\u0120Burger": 28983, "bol": 28984, "Sync": 28985, "\u0120grandchildren": 28986, "\u0120cerv": 28987, "+)": 28988, "\u0120eternity": 28989, "\u0120tweeting": 28990, "\u0120speculative": 28991, "\u0120pivotal": 28992, "\u0120WP": 28993, "\u0120TER": 28994, "ynamic": 28995, "\u0120upl": 28996, "\u0120Cats": 28997, "perhaps": 28998, "\u0120classmates": 28999, "\u0120blatant": 29000, "'-": 29001, "\u0120lakh": 29002, "antine": 29003, "\u0120Borg": 29004, "iom": 29005, "/(": 29006, "\u0120Athletic": 29007, "\u0120sar": 29008, "OTA": 29009, "\u0120Hoffman": 29010, "Nevertheless": 29011, "\u0120adorable": 29012, "\u0120spawned": 29013, "Associated": 29014, "\u0120Domestic": 29015, "\u0120implant": 29016, "\u0120Luxem": 29017, "\u0120Kens": 29018, "\u0120pumps": 29019, "\u0120SAT": 29020, "Attributes": 29021, "509": 29022, "avour": 29023, "\u0120centralized": 29024, "\u0120TN": 29025, "\u0120freshly": 29026, "\u0120Achieve": 29027, "\u0120outsiders": 29028, "herty": 29029, "\u0120Ree": 29030, "\u0120Towers": 29031, "\u0120Dart": 29032, "akable": 29033, "\u0120mp": 29034, "\u0120Heavenly": 29035, "\u0120ripe": 29036, "\u0120Caroline": 29037, "ryan": 29038, "\u0120classics": 29039, "\u0120retiring": 29040, "\u0120228": 29041, "\u0120ah": 29042, "\u0120dealings": 29043, "\u0120punching": 29044, "\u0120Chapman": 29045, "Options": 29046, "maxwell": 29047, "volume": 29048, "\u0120stal": 29049, "\u0120exported": 29050, "\u0120Quite": 29051, "\u0120numerical": 29052, "Burn": 29053, "Fact": 29054, "\u0120Keystone": 29055, "\u0120trending": 29056, "\u0120altering": 29057, "\u0120Africans": 29058, "478": 29059, "\u0120MN": 29060, "\u0120Knock": 29061, "\u0120temptation": 29062, "\u0120prestige": 29063, "Overview": 29064, "\u0120Traditional": 29065, "\u0120Bahrain": 29066, "Private": 29067, "\u0120HOU": 29068, "\u0120barr": 29069, "\u0120Tat": 29070, "Cube": 29071, "USD": 29072, "\u0120Grande": 29073, "\u0120Gat": 29074, "\u0120Flo": 29075, "\u0120resides": 29076, "\u0120indec": 29077, "volent": 29078, "\u0120perpetual": 29079, "ubes": 29080, "\u0120worldview": 29081, "\u0120Quantum": 29082, "\u0120filtered": 29083, "\u0120ensu": 29084, "orgetown": 29085, "ERSON": 29086, "\u0120Mild": 29087, "379": 29088, "OTT": 29089, "\u00c3\u00a5": 29090, "\u0120vitamins": 29091, "\u0120ribbon": 29092, "\u0120sincerely": 29093, "\u0120Hin": 29094, "\u0120eighteen": 29095, "\u0120contradictory": 29096, "\u0120glaring": 29097, "\u0120expectancy": 29098, "\u0120conspir": 29099, "\u0120monstrous": 29100, "\u0120380": 29101, "reci": 29102, "\u0120handic": 29103, "\u0120pumped": 29104, "\u0120indicative": 29105, "\u0120rapp": 29106, "\u0120avail": 29107, "\u0120LEGO": 29108, "\u0120Marijuana": 29109, "1985": 29110, "erton": 29111, "\u0120twentieth": 29112, "################################": 29113, "\u0120Swamp": 29114, "\u0120valuation": 29115, "\u0120affiliates": 29116, "adjusted": 29117, "\u0120Facility": 29118, "262": 29119, "\u0120enzymes": 29120, "itudinal": 29121, "\u0120imprint": 29122, "Site": 29123, "\u0120installer": 29124, "\u0120TRA": 29125, "mology": 29126, "linear": 29127, "\u0120Collective": 29128, "igating": 29129, "\u0120Token": 29130, "\u0120speculated": 29131, "KN": 29132, "\u0120Cly": 29133, "ority": 29134, "\u0120defer": 29135, "\u0120inspectors": 29136, "approved": 29137, "RM": 29138, "\u0120Suns": 29139, "\u0120informing": 29140, "\u0120Syracuse": 29141, "ibli": 29142, "765": 29143, "\u0120glove": 29144, "\u0120authorize": 29145, "\u00e2\u0122\u00a6\u00e2\u0122\u00a6\u00e2\u0122\u00a6\u00e2\u0122\u00a6\u00e2\u0122\u00a6\u00e2\u0122\u00a6\u00e2\u0122\u00a6\u00e2\u0122\u00a6": 29146, "\u0120Cruise": 29147, "\u0120contracting": 29148, "shell": 29149, "IFE": 29150, "\u0120Jewel": 29151, "pract": 29152, "\u0120Photoshop": 29153, "\u0120Knowing": 29154, "harm": 29155, "\u0120attractions": 29156, "adan": 29157, "etus": 29158, "018": 29159, "wagen": 29160, "Alt": 29161, "\u0120multiply": 29162, "\u0120equilibrium": 29163, ":{": 29164, "\u0120Fighters": 29165, "\u0120Edgar": 29166, "\u0120fourteen": 29167, "Govern": 29168, "\u0120misuse": 29169, "\u0120abusing": 29170, "\u0120ancestry": 29171, "ramer": 29172, "644": 29173, "\u0120worms": 29174, "\u0120thicker": 29175, "\u0120Combine": 29176, "\u0120peasants": 29177, "\u0120vind": 29178, "\u0120conquest": 29179, "\u0120mocked": 29180, "\u0120cinnamon": 29181, "\u0120Cald": 29182, "\u0120Gallup": 29183, "\u0120avoidance": 29184, "\u0120incarnation": 29185, "\u0120Strat": 29186, "\u0120tasted": 29187, "enta": 29188, "\u0120Neal": 29189, "pared": 29190, "\u0120terminology": 29191, "jection": 29192, "Scientists": 29193, "\u0120INS": 29194, "\u0120Dee": 29195, "\u0120directories": 29196, "Road": 29197, "\u0120Shap": 29198, "bright": 29199, "\u0120Directors": 29200, "\u0120Column": 29201, "\u0120bob": 29202, "\u0120preferably": 29203, "\u0120glitch": 29204, "furt": 29205, "\u0120eg": 29206, "idis": 29207, "CBC": 29208, "\u0120surrendered": 29209, "\u0120testament": 29210, "336": 29211, "uggest": 29212, "\u0120Nil": 29213, "another": 29214, "\u0120pathetic": 29215, "\u0120Donna": 29216, "\u0120218": 29217, "\u0120Avery": 29218, "\u0120whiskey": 29219, "\u0120fixture": 29220, "\u0120Conquest": 29221, "\u0120bets": 29222, "Occ": 29223, "\u0120Leicester": 29224, "].\"": 29225, "\u0120));": 29226, "\u0120flashes": 29227, "456": 29228, "\u0120masked": 29229, "gebra": 29230, "\u0120computed": 29231, "chel": 29232, "auder": 29233, "\u0120defeats": 29234, "\u0120Liberation": 29235, "\u0120Osama": 29236, "\u0120Vive": 29237, "Changes": 29238, "Channel": 29239, "\u0120tariffs": 29240, "\u0120mage": 29241, "\u0120Sax": 29242, "\u0120inadvertently": 29243, "\u0120CRE": 29244, "\u0120Reaper": 29245, "inky": 29246, "grading": 29247, "\u0120stereotyp": 29248, "\u0120curl": 29249, "\u0120FANT": 29250, "\u0120frameworks": 29251, "Mom": 29252, "\u0120Anch": 29253, "\u0120flavour": 29254, "carbon": 29255, "\u0120permitting": 29256, "letcher": 29257, "\u0120Mozilla": 29258, "\u0120Parking": 29259, "\u0120Champ": 29260, "Scroll": 29261, "\u0120murderer": 29262, "\u0120rested": 29263, "\u0120owes": 29264, "\u0120Poss": 29265, "ADD": 29266, "IFF": 29267, "resolution": 29268, "\u0120Mining": 29269, "\u0120comparative": 29270, "Dim": 29271, "\u0120neighbouring": 29272, "\u0120AST": 29273, "\u0120Toxic": 29274, "\u0120biases": 29275, "\u0120gunfire": 29276, "urous": 29277, "\u0120Moment": 29278, "1983": 29279, "\u0120pervasive": 29280, "ttp": 29281, "\u0120Normally": 29282, "rir": 29283, "Sarah": 29284, "\u0120Albany": 29285, "\u0120unsett": 29286, "\u0120SMS": 29287, "ipers": 29288, "layer": 29289, "\u0120Whites": 29290, "uple": 29291, "\u0120turbo": 29292, "\u0120Leeds": 29293, "\u0120thats": 29294, "\u0120Miner": 29295, "MER": 29296, "\u0120Reign": 29297, "\u0120perme": 29298, "\u0120Blitz": 29299, "\u01201934": 29300, "\u0120intimidating": 29301, "tube": 29302, "\u0120eccentric": 29303, "abolic": 29304, "boxes": 29305, "\u0120Associates": 29306, "votes": 29307, "\u0120simulate": 29308, "umbo": 29309, "astery": 29310, "\u0120shipments": 29311, "FFFF": 29312, "anth": 29313, "\u0120seasoned": 29314, "\u0120experimentation": 29315, "\u00e2\u0138\u0142": 29316, "laws": 29317, "Meet": 29318, "iddles": 29319, "antics": 29320, "Rating": 29321, "ISIS": 29322, "hift": 29323, "\u0120fronts": 29324, "buf": 29325, "017": 29326, "\u0120unatt": 29327, "\u0120Dil": 29328, "leases": 29329, "\u0120Gardens": 29330, "777": 29331, "touch": 29332, "vell": 29333, "458": 29334, "\u0120=====": 29335, "saving": 29336, "\u0120erosion": 29337, "\u0120Quin": 29338, "\u0120earns": 29339, "\u0120accomplishment": 29340, "\u0120Wei": 29341, "\u0120<[": 29342, "_____": 29343, "\u0120irrig": 29344, "\u0120Teddy": 29345, "\u0120conquered": 29346, "\u0120Armored": 29347, "\u0120asserts": 29348, "\u0120manipulating": 29349, "r\u00c3\u00a9": 29350, "\u0120transcripts": 29351, "Gallery": 29352, "\u0120plotting": 29353, "Neil": 29354, "\u0120betrayal": 29355, "loader": 29356, "\u0120Sul": 29357, "\u0120displacement": 29358, "\u0120royalty": 29359, "\u0120WI": 29360, "heit": 29361, "\u0120Devices": 29362, "allel": 29363, "\u0120municipalities": 29364, "\u0120canal": 29365, "Stars": 29366, "\u0120UAE": 29367, "\u0120\"\u00e2\u0122\u00a6": 29368, "\u0120CU": 29369, "above": 29370, "\u0120resonance": 29371, "\u0120guiActiveUn": 29372, "added": 29373, "\u0120Braves": 29374, "\u0120Ibn": 29375, "\u0120hereby": 29376, "\u0120BRE": 29377, "\u0120shareholder": 29378, "\u0120Hir": 29379, "\u0120Ji": 29380, "\u0120strangely": 29381, "\u0120admired": 29382, "\u0120plight": 29383, "\u0120bachelor": 29384, "\u0120Pole": 29385, "ciplinary": 29386, "Tony": 29387, "\u0120Armenian": 29388, "\u0120unman": 29389, "\u0120Zionist": 29390, "Stage": 29391, "iscover": 29392, "\u0120automotive": 29393, "\u0120sidelines": 29394, "\u0120slick": 29395, "\u0120Renaissance": 29396, "\u0120FUN": 29397, "Images": 29398, "\u0120Haj": 29399, "\u0120ping": 29400, "\u0120shortcut": 29401, "\u0120Blvd": 29402, "\u0120Looks": 29403, "\u0120bursts": 29404, "\u0120clamp": 29405, "\u0120mish": 29406, "\u0120sorting": 29407, "\u0120patriot": 29408, "\u0120correctness": 29409, "\u0120Scandinav": 29410, "\u0120Cavaliers": 29411, "python": 29412, "azar": 29413, "\u0120375": 29414, "\u0120Jaune": 29415, "409": 29416, "\u0120detrimental": 29417, "\u0120stabbing": 29418, "\u0120poisoned": 29419, "\u0120fountain": 29420, "ocent": 29421, "orst": 29422, "\u0120Mari": 29423, "\u0120rains": 29424, "\u0120Overs": 29425, "\u0120Institution": 29426, "udget": 29427, "AMY": 29428, "tale": 29429, "\u0120KR": 29430, "\u0120Prices": 29431, "\u0120headaches": 29432, "\u0120landsl": 29433, "\u0120Aura": 29434, "Bonus": 29435, "\u0120Zhao": 29436, "\u0120Hip": 29437, "\u0120hops": 29438, "\u0120Kurdistan": 29439, "\u0120exploiting": 29440, "ryn": 29441, "\u0120hypocrisy": 29442, "opening": 29443, "\u0120gunshot": 29444, "\u0120wed": 29445, "interstitial": 29446, "Interstitial": 29447, "\u0120amen": 29448, "Breaking": 29449, "\u0120marketed": 29450, "Wire": 29451, "\u0120Crowd": 29452, "Continue": 29453, "\u0120Known": 29454, "\u0120Effective": 29455, "orean": 29456, "izons": 29457, "Joseph": 29458, "\u0120escalation": 29459, "username": 29460, "\u0120curtain": 29461, "ATES": 29462, "\u0120PAR": 29463, "\u0120Miy": 29464, "\u0120counterfe": 29465, "lene": 29466, "\u0120contenders": 29467, "daily": 29468, "\u0120Asc": 29469, "\u0120Phillip": 29470, "mostly": 29471, "\u0120filename": 29472, "hene": 29473, "\u0120resembling": 29474, "\u0120staging": 29475, "\u0120Chloe": 29476, "\u0120wiring": 29477, "Hon": 29478, "\u0120Renew": 29479, "ottage": 29480, "\u0120Hybrid": 29481, "much": 29482, "\u0120strokes": 29483, "\u0120policymakers": 29484, "APTER": 29485, "\u0120Arkham": 29486, "plot": 29487, "\u0120assistants": 29488, "\u0120deport": 29489, "\u0120Sega": 29490, "\u0120influenza": 29491, "\u0120Cursed": 29492, "\u0120Kobe": 29493, "\u0120skinny": 29494, "Provider": 29495, "\u0120Rip": 29496, "\u0120incremental": 29497, "products": 29498, "BF": 29499, "\u0120dome": 29500, "\u0120Credits": 29501, "\u0120losers": 29502, "ints": 29503, "\u0120Betty": 29504, "\u0120Talent": 29505, "\u0120DAM": 29506, "Lv": 29507, "Ess": 29508, "\u0120dens": 29509, "temp": 29510, "Judge": 29511, "odic": 29512, "\u0120'(": 29513, "URES": 29514, "etsk": 29515, "VO": 29516, "\u0120retrieved": 29517, "\u0120architects": 29518, "\u00d9\u0129": 29519, "\u0120ethic": 29520, "\u0120Secondary": 29521, "stocks": 29522, "adia": 29523, "\u0120325": 29524, "\u0120Opinion": 29525, "\u0120simultaneous": 29526, "\u0120dizz": 29527, "ulp": 29528, "\u0120smuggling": 29529, "ippery": 29530, "Random": 29531, "facing": 29532, "\u0120Das": 29533, "\u0120stockp": 29534, "\u0120disclosures": 29535, "pointer": 29536, "\u0120coral": 29537, "\u0120Selection": 29538, "\u0120Pike": 29539, "ivalent": 29540, "\u0120ruthless": 29541, "\u0120Rim": 29542, "\u0120ensuing": 29543, "\u0120Experiment": 29544, "\u0120congressman": 29545, "\u0120believer": 29546, "\u0120unspecified": 29547, "\u0120Mord": 29548, "\u0120knowledgeable": 29549, "\u0120VERY": 29550, "TX": 29551, "\u0120straps": 29552, "\u0120turf": 29553, "apeshifter": 29554, "\u0120marital": 29555, "\u0120flock": 29556, "\u00e3\u0123\u0128": 29557, "263": 29558, "AMES": 29559, "\u0120Opposition": 29560, "\u0120treasures": 29561, "\u0120GOD": 29562, "\u0120modeled": 29563, "\u0120WORLD": 29564, "\u0120([": 29565, "\u0120Usage": 29566, "HF": 29567, "\u0120$(": 29568, "ussed": 29569, "\u0120pioneer": 29570, "Eight": 29571, "parse": 29572, "bread": 29573, "ritz": 29574, "\u0120Miranda": 29575, "\u0120Kant": 29576, "++)": 29577, "oren": 29578, "\u0120provoked": 29579, "\u0120breeds": 29580, "\u0120Includes": 29581, "\u0120Pastebin": 29582, "\u0120Flip": 29583, "Java": 29584, "\u0120brink": 29585, "\u0120rumored": 29586, "\u0120unseen": 29587, "\u0120garnered": 29588, "\u0120Defin": 29589, "alted": 29590, "\u0120tattoos": 29591, "\u0120hesitation": 29592, "isitions": 29593, "\u0120Weaver": 29594, "\u0120Reporting": 29595, "\u0120therapies": 29596, "\u0120consultants": 29597, "\u0120residual": 29598, "\u0120Mali": 29599, "\u0120Roma": 29600, "iago": 29601, "\u0120Residents": 29602, "ubi": 29603, "\u0120remedies": 29604, "\u0120adaptive": 29605, "\u0120Alive": 29606, "\u0120Barcl": 29607, "\u0120wallets": 29608, "crypt": 29609, "etermination": 29610, "\u0120Pelosi": 29611, "\u0120slipping": 29612, "otonin": 29613, "\u0120alliances": 29614, "patrick": 29615, "iris": 29616, "\u0120orth": 29617, "\u0120Perkins": 29618, "\u0120DeV": 29619, "\u0120Gets": 29620, "\u0120drying": 29621, "gee": 29622, "forest": 29623, "\u0120Forget": 29624, "orem": 29625, "339": 29626, "\u0120vaguely": 29627, "\u0120Dion": 29628, "\u0120Porn": 29629, "\u0120HOW": 29630, "\u0120pneum": 29631, "\u0120rubble": 29632, "\u0120Taste": 29633, "encia": 29634, "\u0120Gel": 29635, "\u0120dst": 29636, "\u0120245": 29637, "\u0120Morocco": 29638, "inflamm": 29639, "\u0120Twins": 29640, "\u0120bots": 29641, "daughter": 29642, "\u0120Balk": 29643, "\u0120brethren": 29644, "\u0120logos": 29645, "\u0120gobl": 29646, "fps": 29647, "\u0120subdivision": 29648, "\u0120pawn": 29649, "\u0120squeezed": 29650, "\u0120morale": 29651, "\u0120DW": 29652, "'\"": 29653, "\u0120knot": 29654, "ooky": 29655, "\u0120divisive": 29656, "\u0120boosted": 29657, "chy": 29658, "\u00e3\u0125\u0132": 29659, "ifact": 29660, "\u0120newcomers": 29661, "\u0120Wrestling": 29662, "\u0120scouts": 29663, "wolves": 29664, "Rat": 29665, "\u0120nineteenth": 29666, "\u0120Osborne": 29667, "Stats": 29668, "\u0120empowered": 29669, "\u0120psychopath": 29670, "\u0120OEM": 29671, "uggage": 29672, "\u0120PK": 29673, "\u0120Mohammad": 29674, "Pak": 29675, "\u0120anarchists": 29676, "\u0120Extract": 29677, "esthes": 29678, "\u0120Stockholm": 29679, "loo": 29680, "\u0120Graph": 29681, "\u0120deploying": 29682, "\u0120Stranger": 29683, "\u0120Mold": 29684, "\u0120staffer": 29685, "\u0120discounted": 29686, "uckle": 29687, "please": 29688, "\u0120Landing": 29689, "\u00c3\u0143a": 29690, "\u0120193": 29691, "\u0120ante": 29692, "\u0120repetition": 29693, "\u0120+/-": 29694, "\u0120parody": 29695, "\u0120lively": 29696, "AAA": 29697, "\u0120Horus": 29698, "\u0120pits": 29699, "inders": 29700, "LOC": 29701, "\u0120Venice": 29702, "406": 29703, "\u0120Discover": 29704, "\u00e2\u0128": 29705, "ellectual": 29706, "\u0120pens": 29707, "\u0120eyel": 29708, "iguous": 29709, "Impl": 29710, "\u0120joking": 29711, "\u0120inval": 29712, "\u0120Belfast": 29713, "\u0120creditors": 29714, "\u0120Skywalker": 29715, "ovsky": 29716, "\u0120ceasefire": 29717, "\u0120seals": 29718, "isoft": 29719, ")).": 29720, "\u0120Felix": 29721, "ITS": 29722, "\u0120tresp": 29723, "\u0120Blockchain": 29724, "eware": 29725, "\u0120Schwar": 29726, "enne": 29727, "mounted": 29728, "\u0120Beacon": 29729, "lesh": 29730, "\u0120immensely": 29731, "\u0120cheering": 29732, "Employ": 29733, "scene": 29734, "ishly": 29735, "atchewan": 29736, "\u0120Nicolas": 29737, "\u0120drained": 29738, "\u0120Exit": 29739, "\u0120Azerb": 29740, "jun": 29741, "\u0120floated": 29742, "uania": 29743, "Deep": 29744, "\u0120superv": 29745, "\u0120mystical": 29746, "\u0120Dollar": 29747, "\u0120Apostle": 29748, "\u0120REL": 29749, "\u0120Provided": 29750, "\u0120Bucks": 29751, "\u00e3\u0125\u00b4": 29752, "cutting": 29753, "\u0120enhancements": 29754, "\u0120Penguins": 29755, "\u0120Isaiah": 29756, "\u0120jerk": 29757, "\u0120Wyn": 29758, "\u0120stalled": 29759, "\u0120cryptocurrencies": 29760, "\u0120Roland": 29761, "single": 29762, "\u0120lumin": 29763, "\u0120Fellow": 29764, "\u0120Capacity": 29765, "\u0120Kazakh": 29766, "WN": 29767, "\u0120financed": 29768, "389": 29769, "\u0120tid": 29770, "\u0120collusion": 29771, "\u0120Myr": 29772, "\u00ee\u0122": 29773, "Senator": 29774, "\u0120pediatric": 29775, "\u0120neatly": 29776, "\u0120sandwiches": 29777, "\u0120Architecture": 29778, "\u0120tucked": 29779, "\u0120balcony": 29780, "\u0120earthquakes": 29781, "quire": 29782, "Future": 29783, "\u0120hefty": 29784, "\u00e9\u0139": 29785, "\u0120specializes": 29786, "\u0120stresses": 29787, "\u0120sender": 29788, "\u0120misunderstanding": 29789, "\u0120epile": 29790, "\u0120provoke": 29791, "\u0120Colors": 29792, "\u0120dismay": 29793, "uko": 29794, "[_": 29795, "586": 29796, "neutral": 29797, "\u0120donating": 29798, "\u0120Randall": 29799, "Multi": 29800, "\u0120conveniently": 29801, "\u0120Sung": 29802, "\u0120Coca": 29803, "\u0120tents": 29804, "\u0120Acceler": 29805, "\u0120partnered": 29806, "272": 29807, "irming": 29808, "\u0120BAS": 29809, "sometimes": 29810, "\u0120objected": 29811, "ubric": 29812, "posed": 29813, "LCS": 29814, "grass": 29815, "\u0120attributable": 29816, "VIS": 29817, "Israeli": 29818, "\u0120repeats": 29819, "\u0120RM": 29820, "vag": 29821, "uta": 29822, "inous": 29823, "\u0120inert": 29824, "\u0120Miguel": 29825, "\u00e6\u0143": 29826, "\u0120Hawaiian": 29827, "Board": 29828, "\u0120artific": 29829, "\u0120Azerbai": 29830, "asio": 29831, "\u0120Rent": 29832, "AIN": 29833, "\u0120appliances": 29834, "\u0120nationality": 29835, "\u0120asshole": 29836, "\u0120Neb": 29837, "\u0120notch": 29838, "hani": 29839, "\u0120Bride": 29840, "Availability": 29841, "\u0120intercepted": 29842, "\u0120continental": 29843, "\u0120swelling": 29844, "\u0120Perspect": 29845, "bies": 29846, ".<": 29847, "ithmetic": 29848, "\u0120Lara": 29849, "\u0120tempting": 29850, "addr": 29851, "\u0120overseeing": 29852, "clad": 29853, "\u0120DV": 29854, "\u0120Gingrich": 29855, "\u0120mun": 29856, "\u0120Appropri": 29857, "\u0120alterations": 29858, "\u0120Patreon": 29859, "\u0120havoc": 29860, "\u0120disciplines": 29861, "\u0120notoriously": 29862, "akuya": 29863, "ieri": 29864, "?).": 29865, "\u0120Went": 29866, "\u0120silicon": 29867, "\u0120tremb": 29868, "Container": 29869, "Known": 29870, "\u0120mortar": 29871, "este": 29872, "icka": 29873, "Arthur": 29874, "\u0120Previously": 29875, "\u0120Marty": 29876, "\u0120sparse": 29877, "gins": 29878, "\u0120inward": 29879, "\u0120Participant": 29880, "Copy": 29881, "\u0120Misc": 29882, "\u0120antibiotic": 29883, "\u0120Retro": 29884, "\u0120elusive": 29885, "\u0120assail": 29886, "\u0120Battalion": 29887, "\u0120Bought": 29888, "\u0120diminish": 29889, "\u0120Europa": 29890, "session": 29891, "\u0120Dangerous": 29892, "iesel": 29893, "\u0120disbelief": 29894, "\u0120blasts": 29895, "extreme": 29896, "\u0120Boyd": 29897, "\u0120Projects": 29898, "\u0120Guys": 29899, "\u0120undergone": 29900, "\u0120grill": 29901, "\u0120Dwight": 29902, "\u0120197": 29903, "USER": 29904, "\u0120filesystem": 29905, "\u0120clocks": 29906, "Taylor": 29907, "\u0120wrapper": 29908, "\u0120folding": 29909, "ousand": 29910, "\u0120Philippine": 29911, "ATIONAL": 29912, "\u0120Perth": 29913, "\u0120ashes": 29914, "\u0120accumulate": 29915, "\u0120Gateway": 29916, "Shop": 29917, "orkshire": 29918, "Han": 29919, "\u0120Barrel": 29920, "\u0120Leh": 29921, "\u0120XV": 29922, "\u0120whim": 29923, "\u0120repo": 29924, "\u0120CG": 29925, "\u0120Mam": 29926, "\u0120incorporating": 29927, "\u0120bailout": 29928, "\u0120linguistic": 29929, "\u0120disinteg": 29930, "CLE": 29931, "\u0120cinematic": 29932, "\u0120Fiber": 29933, "Syn": 29934, "ilion": 29935, "\u0120Compos": 29936, "chens": 29937, "\u0120neoc": 29938, "\u0120boiled": 29939, "FINE": 29940, "ono": 29941, "uncle": 29942, "iken": 29943, "\u0120BM": 29944, "\u00ce\u00b9": 29945, "\u0120receipts": 29946, "\u0120disposed": 29947, "\u0120Thirty": 29948, "\u0120Rough": 29949, "\u0120ABS": 29950, "\u0120notwithstanding": 29951, "ollen": 29952, "#$": 29953, "\u0120unreliable": 29954, "\u0120bloom": 29955, "\u0120mediocre": 29956, "\u0120tram": 29957, "\u0120Tasman": 29958, "\u0120shakes": 29959, "\u0120manifesto": 29960, "\u0120MW": 29961, "\u0120satisfactory": 29962, "\u0120shores": 29963, "\u0120computation": 29964, "\u0120assertions": 29965, "ormons": 29966, "arag": 29967, "abit": 29968, "Democrats": 29969, "\u0120Loot": 29970, "\u0120Volks": 29971, "haired": 29972, "\u0120gravitational": 29973, "Sing": 29974, "\u0120Miz": 29975, "\u0120throttle": 29976, "\u0120tyranny": 29977, "\u0120Views": 29978, "\u0120robber": 29979, "\u0120Minority": 29980, "\u0120shrine": 29981, "scope": 29982, "purpose": 29983, "\u0120nucleus": 29984, "ourcing": 29985, "\u0120USDA": 29986, "\u0120DHS": 29987, "wra": 29988, "\u0120Bowie": 29989, "Scale": 29990, "\u0120BEL": 29991, "xi": 29992, "Iter": 29993, "\u0120(),": 29994, "wright": 29995, "\u0120sailors": 29996, "oused": 29997, "NASA": 29998, "\u0120Proof": 29999, "\u0120Mineral": 30000, "token": 30001, "\u0120FD": 30002, "Rew": 30003, "\u0120ell": 30004, "630": 30005, "\u0120chancellor": 30006, "\u0120Gos": 30007, "\u0120amounted": 30008, "\u0120Recre": 30009, "omez": 30010, "\u0120Optim": 30011, "\u0120Olive": 30012, "\u0120tracker": 30013, "owler": 30014, "\u0120Unique": 30015, "Root": 30016, "\u0120maritime": 30017, "\u0120Quran": 30018, "\u0120Adapt": 30019, "\u0120ecosystems": 30020, "\u0120Repeat": 30021, "\u0120Soy": 30022, "\u0120IMP": 30023, "\u0120graduating": 30024, "andem": 30025, "Pur": 30026, "\u0120Reset": 30027, "\u0120Trick": 30028, "\u0120Philly": 30029, "\u0120Tue": 30030, "\u0120Malaysian": 30031, "\u0120climax": 30032, "\u0120bury": 30033, "\u0120conspic": 30034, "\u0120Southampton": 30035, "\u0120Flowers": 30036, "\u0120escorted": 30037, "\u0120Educational": 30038, "\u0120IRC": 30039, "\u0120brutally": 30040, "eating": 30041, "\u0120pillar": 30042, "\u0120Sang": 30043, "\u0120Jude": 30044, "arling": 30045, "\u0120Amnesty": 30046, "\u0120reminding": 30047, "\u0120Administrative": 30048, "hesda": 30049, "\u0120flashed": 30050, "\u0120PBS": 30051, "perate": 30052, "feature": 30053, "\u0120swipe": 30054, "\u0120graves": 30055, "oultry": 30056, "261": 30057, "breaks": 30058, "\u0120Guer": 30059, "\u0120shrimp": 30060, "\u0120Voting": 30061, "quist": 30062, "\u0120analytical": 30063, "\u0120tablespoons": 30064, "\u0120SOU": 30065, "\u0120researched": 30066, "\u0120disrupted": 30067, "\u0120jour": 30068, "\u0120replica": 30069, "\u0120cartoons": 30070, "bians": 30071, "})": 30072, "copy": 30073, "Got": 30074, "ouched": 30075, "PUT": 30076, "\u0120swarm": 30077, "notations": 30078, "said": 30079, "\u0120rebuilt": 30080, "\u0120collaborate": 30081, "\u0120raging": 30082, "\u0120nar": 30083, "\u0120demographics": 30084, "\u0120DDR": 30085, "\u0120distrust": 30086, "ossier": 30087, "\u0120Kro": 30088, "\u0120pumpkin": 30089, "\u0120regrets": 30090, "\u0120fatalities": 30091, "\u0120Lens": 30092, "\u0120Ole": 30093, "pd": 30094, "\u0120puppet": 30095, "\u0120Outlook": 30096, "\u0120Stam": 30097, "Ol": 30098, "Fair": 30099, "UU": 30100, "\u0120rewritten": 30101, "\u00c4\u00b1": 30102, "\u0120fascinated": 30103, "\u0120vectors": 30104, "\u0120tribunal": 30105, "uay": 30106, "\u0120Mats": 30107, "\u0120Coins": 30108, "[[": 30109, "\u0120181": 30110, "\u0120renders": 30111, "\u0120Kaepernick": 30112, "\u0120espionage": 30113, "\u0120summ": 30114, "\u0120ditch": 30115, "Account": 30116, "\u0120spreadsheet": 30117, "\u0120mutant": 30118, "past": 30119, "407": 30120, "\u0120dye": 30121, "\u0120initiation": 30122, "\u01204000": 30123, "\u0120punishable": 30124, "\u0120thinner": 30125, "\u0120Khal": 30126, "\u0120intermedi": 30127, "Dun": 30128, "\u0120Gotham": 30129, "\u0120eagerly": 30130, "\u0120vaginal": 30131, "powers": 30132, "VW": 30133, "\u0120WATCHED": 30134, "\u0120predator": 30135, "amsung": 30136, "\u0120disparity": 30137, "\u0120[*": 30138, "\u0120amph": 30139, "\u0120outskirts": 30140, "\u0120Spirits": 30141, "\u0120skeletal": 30142, "\u00d0\u00bb": 30143, "\u0120Rear": 30144, "\u0120issuance": 30145, "\u0120Logic": 30146, "released": 30147, "ZZ": 30148, "\u0120Bound": 30149, "Entry": 30150, "\u0120exits": 30151, "isol": 30152, "\u0120Founder": 30153, "\u0120wre": 30154, "\u0120Greenland": 30155, "\u0120MMO": 30156, "taker": 30157, "INC": 30158, "\u00e3\u0123\u00be": 30159, "\u0120hourly": 30160, "henko": 30161, "\u0120fantasies": 30162, "\u0120disob": 30163, "\u0120demolition": 30164, "\u00e3\u0125\u012d": 30165, "\u0120enlisted": 30166, "ratulations": 30167, "\u0120misguided": 30168, "\u0120ensured": 30169, "\u0120discouraged": 30170, "mort": 30171, "\u0120flank": 30172, "\u0120cess": 30173, "\u0120reacts": 30174, "\u0120Sere": 30175, "sensitive": 30176, "\u0120Serpent": 30177, "assad": 30178, "\u0120247": 30179, "\u0120calmly": 30180, "busters": 30181, "\u0120bleed": 30182, "\u0120Stro": 30183, "\u0120amusement": 30184, "\u0120Antarctica": 30185, "\u0120scept": 30186, "\u0120Gaw": 30187, "aq": 30188, "asonic": 30189, "\u0120sprawling": 30190, "native": 30191, "aturated": 30192, "\u0120Battlefield": 30193, "IVERS": 30194, "EB": 30195, "\u0120Gems": 30196, "\u0120Northwestern": 30197, "\u0120Films": 30198, "\u0120Automatic": 30199, "\u0120apprehend": 30200, "\u00e3\u0123\u00a8": 30201, "\u0120guiName": 30202, "\u0120backend": 30203, "\u0120evidenced": 30204, "geant": 30205, "012": 30206, "\u0120Siege": 30207, "\u0120externalTo": 30208, "\u0120unfocusedRange": 30209, "\u0120guiActiveUnfocused": 30210, "\u0120guiIcon": 30211, "\u0120externalToEVA": 30212, "\u0120externalToEVAOnly": 30213, "Fri": 30214, "chard": 30215, "enaries": 30216, "\u0120chiefs": 30217, "\u0120cf": 30218, "\u0120HUD": 30219, "\u0120corrobor": 30220, "\u0120dB": 30221, "\u0120Taken": 30222, "\u0120Patricia": 30223, "rail": 30224, "\u0120Charm": 30225, "\u0120Libertarian": 30226, "rieve": 30227, "Personal": 30228, "\u0120OUR": 30229, "geries": 30230, "\u0120dumping": 30231, "\u0120neurological": 30232, "itimate": 30233, "\u0120Clintons": 30234, "rafted": 30235, "\u0120Molly": 30236, "\u0120terminals": 30237, "register": 30238, "\u0120flare": 30239, "\u0120encoded": 30240, "\u0120autopsy": 30241, "pel": 30242, "machine": 30243, "\u0120exemptions": 30244, "\u0120Royals": 30245, "distance": 30246, "\u0120drafts": 30247, "\u0120lame": 30248, "\u0120Cunning": 30249, "\u0120spouses": 30250, "\u0120Markets": 30251, "\u0120Carrier": 30252, "\u0120implying": 30253, "\u0120Yak": 30254, "sid": 30255, "\u0120loser": 30256, "\u0120vigilant": 30257, "\u0120impeachment": 30258, "\u0120augmented": 30259, "\u0120Employees": 30260, "\u0120unintended": 30261, "ternally": 30262, "\u0120Watt": 30263, "\u0120recognizable": 30264, "essim": 30265, "\u00e6\u013f": 30266, "\u0120coated": 30267, "rha": 30268, "\u0120lieutenant": 30269, "\u0120Legislation": 30270, "published": 30271, "444": 30272, "013": 30273, "\u0120ideally": 30274, "\u0120Password": 30275, "\u0120simplify": 30276, "\u0120Meta": 30277, "\u0120MRI": 30278, "\u0120pleading": 30279, "organized": 30280, "handler": 30281, "\u0120unravel": 30282, "correct": 30283, "\u0120icy": 30284, "\u0120paranoid": 30285, "\u0120passer": 30286, "\u0120inspections": 30287, "ofer": 30288, "\u0120Healthcare": 30289, "283": 30290, "\u0120Brut": 30291, "iola": 30292, "forge": 30293, "\u0120Medieval": 30294, "MSN": 30295, "ievers": 30296, "\u0120Programming": 30297, "\u00e5\u012b": 30298, "\u0120223": 30299, "mu": 30300, "\u0120CLE": 30301, "uga": 30302, "\u0120shoppers": 30303, "\u0120informative": 30304, "\u0120Plans": 30305, "\u0120supplementation": 30306, "\u0120Tests": 30307, "tyard": 30308, "ocytes": 30309, "\u0120Vega": 30310, "\u0120Gujarat": 30311, "ermanent": 30312, "Except": 30313, "\u0120LOT": 30314, "alla": 30315, "\u0120Cumm": 30316, "\u0120Osw": 30317, "\u0120venom": 30318, "\u0120Debt": 30319, "\u0120DOWN": 30320, "\u0120reunion": 30321, "\u0120muc": 30322, "\u0120Relief": 30323, "\u0120geop": 30324, "\u0120\u00f0\u0141\u013a": 30325, "alogue": 30326, "Anth": 30327, "echo": 30328, "\u0120corros": 30329, "\u0120replication": 30330, "\u0120Blazing": 30331, "\u0120Daughter": 30332, "\u0120inflic": 30333, "\u0120Lindsey": 30334, "\u00d9\u012a": 30335, "284": 30336, "Exit": 30337, "\u0120gloom": 30338, "TAIN": 30339, "\u0120undermining": 30340, "\u0120advising": 30341, "hidden": 30342, "\u0120overflow": 30343, "\u0120gor": 30344, "urdue": 30345, "\u0120echoes": 30346, "enhagen": 30347, "\u0120impuls": 30348, "drug": 30349, "cash": 30350, "\u0120async": 30351, "\u0120mirac": 30352, "atts": 30353, "punk": 30354, "\u0120pivot": 30355, "\u0120Legislative": 30356, "\u0120bloggers": 30357, "\u0120Claw": 30358, "sburg": 30359, "dyl": 30360, "\u0120Recommend": 30361, "\u0120verte": 30362, "\u0120prohibiting": 30363, "\u0120Panther": 30364, "Jonathan": 30365, "\u0120omin": 30366, "\u0120hateful": 30367, "281": 30368, "\u0120Orche": 30369, "\u0120Murdoch": 30370, "downs": 30371, "\u0120asymm": 30372, "GER": 30373, "Always": 30374, "\u0120informs": 30375, "\u0120WM": 30376, "\u0120Pony": 30377, "\u0120Appendix": 30378, "\u0120Arlington": 30379, "Jam": 30380, "\u0120medicinal": 30381, "\u0120Slam": 30382, "ITIES": 30383, "\u0120reaff": 30384, "\u0120Ri": 30385, "FG": 30386, "Spring": 30387, "bool": 30388, "\u0120thighs": 30389, "\u0120markings": 30390, "\u0120Raqqa": 30391, "\u0120Lak": 30392, "poll": 30393, "tsky": 30394, "\u0120Morty": 30395, "\u0120Definition": 30396, "\u0120debunk": 30397, "endered": 30398, "\u0120Leone": 30399, "avers": 30400, "\u0120mortgages": 30401, "Apparently": 30402, "Nic": 30403, "haus": 30404, "\u0120Thousands": 30405, "auld": 30406, "\u0120mash": 30407, "shoot": 30408, "\u0120diarr": 30409, "\u0120consciously": 30410, "Hero": 30411, "eas": 30412, "\u0120Naturally": 30413, "\u0120Destroyer": 30414, "\u0120dashboard": 30415, "services": 30416, "Rog": 30417, "\u0120millennials": 30418, "\u0120invade": 30419, "-(": 30420, "\u0120commissions": 30421, "\u0120Auckland": 30422, "\u0120broadcasts": 30423, "\u0120frontal": 30424, "\u0120crank": 30425, "\u0120Historic": 30426, "\u0120rumours": 30427, "CTV": 30428, "\u0120steril": 30429, "\u0120booster": 30430, "rocket": 30431, "\u00e3\u0124\u00bc": 30432, "utsche": 30433, "\u0120PI": 30434, "\u0120233": 30435, "\u0120Producer": 30436, "\u0120Analytics": 30437, "\u0120invaluable": 30438, "\u0120unintention": 30439, "\u0120CY": 30440, "\u0120scrutin": 30441, "\u0120gigg": 30442, "\u0120engulf": 30443, "\u0120proletariat": 30444, "\u0120hacks": 30445, "\u0120Hew": 30446, "arak": 30447, "\u0120Slime": 30448, "ielding": 30449, "agher": 30450, "\u0120Elliot": 30451, "\u0120telecom": 30452, "\u0120219": 30453, "ultan": 30454, "\u0120Arbor": 30455, "\u0120Scouts": 30456, "Ban": 30457, "\u0120lifespan": 30458, "\u0120blasp": 30459, "388": 30460, "\u0120judiciary": 30461, "\u0120Continental": 30462, "asking": 30463, "McC": 30464, "LED": 30465, "\u0120baggage": 30466, "\u0120Sorcerer": 30467, "\u0120remnants": 30468, "\u0120Griffith": 30469, "etsu": 30470, "\u0120Subaru": 30471, "\u0120Personality": 30472, "designed": 30473, "ushima": 30474, "agnar": 30475, "\u0120recoil": 30476, "\u0120passions": 30477, "\\\":": 30478, "\u0120tee": 30479, "\u0120abolition": 30480, "\u0120Creating": 30481, "jac": 30482, "\u0120194": 30483, "019": 30484, "\u0120pillars": 30485, "riched": 30486, "/\"": 30487, "tk": 30488, "\u0120livelihood": 30489, "\u0120roasted": 30490, "ahon": 30491, "\u0120Hutch": 30492, "assert": 30493, "\u0120dividend": 30494, "\u0120knit": 30495, "\u0120daunting": 30496, "\u0120disturbance": 30497, "\u0120shale": 30498, "\u0120cultivated": 30499, "\u0120refrigerator": 30500, "LB": 30501, "\u0120NET": 30502, "\u0120commercials": 30503, "\u0120thinkers": 30504, "455": 30505, "\u0120chop": 30506, "Broad": 30507, "\u0120suspicions": 30508, "\u0120tagged": 30509, "lifting": 30510, "\u0120stylish": 30511, "\u0120Shields": 30512, "Shortly": 30513, "\u0120tails": 30514, "Auth": 30515, "STE": 30516, "\u0120GAME": 30517, "\u0120seism": 30518, "\u0120Kis": 30519, "ologne": 30520, "\u0120cowork": 30521, "\u0120forcibly": 30522, "\u0120thyroid": 30523, "\u0120PB": 30524, "ANE": 30525, "married": 30526, "horse": 30527, "\u0120polymer": 30528, "\u0120Chal": 30529, "odor": 30530, "DEBUG": 30531, "\u0120Context": 30532, "\u0120bliss": 30533, "\u0120pinpoint": 30534, "\u0120Mathemat": 30535, "legram": 30536, "\u0120Weekend": 30537, "\u0120labelled": 30538, "\u0120bart": 30539, "itles": 30540, "\u0120estrogen": 30541, "\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136\u00e2\u0122\u0136": 30542, "\"'": 30543, "\u0120visibly": 30544, "\u0120outsider": 30545, "aida": 30546, "Area": 30547, "\u0120dissemin": 30548, "\u0120dishonest": 30549, "\u0120Closed": 30550, "\u0120Bulletin": 30551, "\u0120Ramsey": 30552, "sword": 30553, "\u0120XI": 30554, "ourced": 30555, "Same": 30556, "346": 30557, "\u0120Repe": 30558, "\u0120Kou": 30559, "cake": 30560, "emis": 30561, "Cache": 30562, "\u0120Meaning": 30563, "\u0120Enlight": 30564, "onomy": 30565, "\u0120manifestation": 30566, "sworth": 30567, "Jay": 30568, "\u0120chore": 30569, "\u00c3\u00b6r": 30570, "Dream": 30571, "\u0120sanctioned": 30572, "\u0120culturally": 30573, "\u0120Ara": 30574, "Nav": 30575, "\u0120theological": 30576, "\u0120strut": 30577, "\u0120VO": 30578, "\u0120Handbook": 30579, "\u0120constructing": 30580, "\u0120\u00c2\u00b6": 30581, "\u0120Benefits": 30582, "\u0120Psychological": 30583, "sac": 30584, "\u00e5\u00b8": 30585, "policy": 30586, "\u0120Matters": 30587, "\u0120Reported": 30588, "\u0120Byte": 30589, "\u0120vitro": 30590, "\u0120Maiden": 30591, "\u0120lam": 30592, "\u0120Jennings": 30593, "\u0120garment": 30594, "\u0120Rutgers": 30595, "\u0120Stafford": 30596, "\u0120Wellington": 30597, "\u0120intermitt": 30598, "\u0120npm": 30599, "\u0120ordeal": 30600, "\u0120plugged": 30601, "ooming": 30602, "inished": 30603, "framework": 30604, "\u0120timber": 30605, "\u0120cass": 30606, "\u0120850": 30607, "iless": 30608, "\u0120Redux": 30609, "768": 30610, "Stre": 30611, "\u0120surpassed": 30612, "whel": 30613, "\u0120parallels": 30614, "\u0120veil": 30615, "\u0120GI": 30616, "\u0120REST": 30617, "\u0120readiness": 30618, "sort": 30619, "\u0120modifying": 30620, "\u0120Slate": 30621, "ruff": 30622, "\u0120marble": 30623, "\u0120infrared": 30624, "\u0120auditor": 30625, "\u0120FANTASY": 30626, "\u0120Poverty": 30627, "\u0120SPD": 30628, "\u0120\"(": 30629, "Ky": 30630, "RAY": 30631, "\u0120executions": 30632, "\u0120Beverly": 30633, "\u0120Marxism": 30634, "\u0120Burst": 30635, "\u0120Kali": 30636, "estones": 30637, "Clearly": 30638, "Ell": 30639, "\u00e3\u0123\u00a7": 30640, "\u0120Proceedings": 30641, "Token": 30642, "IFIC": 30643, "\u00c3\u00b1a": 30644, "Central": 30645, "\u0120Haley": 30646, "\u0120Drama": 30647, "\u0120formations": 30648, "ORN": 30649, "Books": 30650, "\u0120dominating": 30651, "\u0120Flyers": 30652, "\u0120Companion": 30653, "\u0120disciplined": 30654, "\u0120Yugoslav": 30655, "\u0120Spells": 30656, "\u0120vengeance": 30657, "\u0120landlords": 30658, "Len": 30659, "\u0120Ogre": 30660, "anoia": 30661, "\u0120piercing": 30662, "\u0120congreg": 30663, "\u0120scorer": 30664, "obia": 30665, "\u0120nickel": 30666, "\u0120Learns": 30667, "\u0120rejo": 30668, "\u0120masterpiece": 30669, "Flash": 30670, "\u0120inhabited": 30671, "\u0120OpenGL": 30672, "\u0120Dud": 30673, "\u0120ICO": 30674, "\u0120arter": 30675, "\u0120plur": 30676, "\u0120mastery": 30677, "\u0120longstanding": 30678, "sted": 30679, "\u0120wines": 30680, "\u0120televised": 30681, "\u0120Shrine": 30682, "\u0120Bayern": 30683, "\u0120\u00e2\u0135\u013a": 30684, "\u0120enclosure": 30685, "john": 30686, "\u0120prophets": 30687, "\u0120Resurrection": 30688, "\u0120Orders": 30689, "\u0120uneven": 30690, "rals": 30691, "\u0120dwind": 30692, "\u0120Lah": 30693, "\u0120Sloven": 30694, "378": 30695, "\u0120insistence": 30696, "affle": 30697, "\u0120Clone": 30698, "\u0120hardship": 30699, "\u0120Congressman": 30700, "\u0120plead": 30701, "\u0120reviewers": 30702, "\u0120cured": 30703, "\u01201935": 30704, "asley": 30705, "fake": 30706, "\u0120Thinking": 30707, "ydia": 30708, "PART": 30709, "\u0120Dota": 30710, "oit": 30711, "\u0120whipped": 30712, "\u0120bouncing": 30713, "\u0120Hispanics": 30714, "comings": 30715, "\u0120cannabin": 30716, "\u0120Chambers": 30717, "\u0120Zack": 30718, "Optional": 30719, "\u0120coats": 30720, "\u0120prowess": 30721, "\u0120Norton": 30722, "\u0120plainly": 30723, "\u0120freight": 30724, "\u0120inhibition": 30725, "\u0120clam": 30726, "\u0120303": 30727, "kef": 30728, "aleigh": 30729, "Luke": 30730, "\u0120psycho": 30731, "atorium": 30732, "MED": 30733, "\u0120treaties": 30734, "\u0120indisc": 30735, "\u0120dc": 30736, "OPS": 30737, "\u0120resilient": 30738, "\u0120Interstate": 30739, "\u0120slack": 30740, "\u0120mundane": 30741, "\u0120establishes": 30742, "359": 30743, "\u0120strained": 30744, "\u0120nond": 30745, "Sus": 30746, "\u0120caste": 30747, "arate": 30748, "ieving": 30749, "\u0120unfairly": 30750, "\u0120parser": 30751, "onial": 30752, "ursive": 30753, "Via": 30754, "\u0120Otto": 30755, "\u0120Authorities": 30756, "stroke": 30757, "KR": 30758, "\u0120Mercy": 30759, "\u0120furnished": 30760, "\u0120outset": 30761, "\u0120metic": 30762, "1982": 30763, "olithic": 30764, "\u0120Tent": 30765, "ogical": 30766, "\u0120Aircraft": 30767, "\u0120hides": 30768, "\u0120Became": 30769, "\u0120educators": 30770, "reaching": 30771, "\u0120volatility": 30772, "\u0120toddler": 30773, "\u0120NASCAR": 30774, "\u0120Twelve": 30775, "\u0120Highlights": 30776, "\u0120grape": 30777, "\u0120splits": 30778, "\u0120peasant": 30779, "\u0120reneg": 30780, "\u0120MSI": 30781, "Temp": 30782, "stars": 30783, "\u0120trek": 30784, "\u0120Hyde": 30785, "binding": 30786, "\u0120realism": 30787, "\u0120oxide": 30788, "\u0120Hos": 30789, "\u0120mounts": 30790, "\u0120biting": 30791, "\u0120collapsing": 30792, "\u0120postal": 30793, "\u0120museums": 30794, "\u0120detached": 30795, "\u0120respecting": 30796, "\u0120monopol": 30797, "\u0120workflow": 30798, "\u0120Cake": 30799, "Template": 30800, "\u0120Organisation": 30801, "\u0120persistence": 30802, "369": 30803, "Coming": 30804, "Brad": 30805, "\u0120redundant": 30806, "\u0120GTA": 30807, "\u0120bending": 30808, "\u0120revoked": 30809, "\u0120offending": 30810, "\u0120framing": 30811, "\u0120printf": 30812, "Commun": 30813, "members": 30814, "Outside": 30815, "\u0120construed": 30816, "\u0120coded": 30817, "FORE": 30818, "\u0120chast": 30819, "Chat": 30820, "Indian": 30821, "\u0120Yard": 30822, "?!\"": 30823, "\u0120Ports": 30824, "\u0120Xavier": 30825, "\u0120RET": 30826, "'.\"": 30827, "\u0120Boat": 30828, "ivated": 30829, "icht": 30830, "umerable": 30831, "Ds": 30832, "\u0120Dunn": 30833, "\u0120coffin": 30834, "\u0120securely": 30835, "\u0120Raptors": 30836, "\u0120Bes": 30837, "Installation": 30838, "\u0120inception": 30839, "\u0120Healthy": 30840, "endants": 30841, "\u0120psychologists": 30842, "\u0120Sheikh": 30843, "cultural": 30844, "\u0120BlackBerry": 30845, "shift": 30846, "Fred": 30847, "oche": 30848, "\u0120cakes": 30849, "\u0120SEO": 30850, "\u0120Gian": 30851, "\u0120Asians": 30852, "ogging": 30853, "element": 30854, "\u0120pundits": 30855, "\u0120Vaugh": 30856, "\u0120Gavin": 30857, "\u0120hitter": 30858, "\u0120drowned": 30859, "\u0120chalk": 30860, "\u0120Zika": 30861, "\u0120measles": 30862, "802": 30863, "\u00e2\u0122\u00a6..": 30864, "\u0120AWS": 30865, "]\"": 30866, "\u0120distort": 30867, "\u0120Mast": 30868, "\u0120antibodies": 30869, "\u0120Mash": 30870, "Memory": 30871, "\u0120Uganda": 30872, "\u0120Prob": 30873, "\u0120vomiting": 30874, "\u0120Turns": 30875, "\u0120occupying": 30876, "\u0120evasion": 30877, "\u0120Therapy": 30878, "\u0120promo": 30879, "\u0120electr": 30880, "\u0120blueprint": 30881, "\u0120Dre": 30882, "priced": 30883, "\u0120Depot": 30884, "\u0120alleviate": 30885, "\u0120Somali": 30886, "marg": 30887, "nine": 30888, "\u0120nostalgia": 30889, "\u0120Shepherd": 30890, "\u0120cavalry": 30891, "\u0120torped": 30892, "\u0120Bloody": 30893, "xb": 30894, "\u0120sank": 30895, "\u0120goalt": 30896, "reportprint": 30897, "embedreportprint": 30898, "cloneembedreportprint": 30899, "\u0120Initially": 30900, "\u0120Fischer": 30901, "\u0120noteworthy": 30902, "cern": 30903, "\u0120inefficient": 30904, "rawdownload": 30905, "rawdownloadcloneembedreportprint": 30906, "cation": 30907, "\u0120Dynasty": 30908, "lag": 30909, "DES": 30910, "\u0120distinctly": 30911, "\u0120Estonia": 30912, "\u0120openness": 30913, "\u0120gossip": 30914, "ruck": 30915, "Width": 30916, "\u0120Ibrahim": 30917, "\u0120petroleum": 30918, "\u0120avatar": 30919, "\u0120Hed": 30920, "atha": 30921, "\u0120Hogwarts": 30922, "\u0120caves": 30923, "678": 30924, "\u0120safeguard": 30925, "\u0120Mog": 30926, "isson": 30927, "\u0120Durham": 30928, "slaught": 30929, "\u0120Graduate": 30930, "\u0120subconscious": 30931, "\u0120Excellent": 30932, "\u0120Dum": 30933, "-----": 30934, "\u0120piles": 30935, "\u0120WORK": 30936, "\u0120Garn": 30937, "\u0120Fol": 30938, "\u0120ATM": 30939, "\u0120avoids": 30940, "\u0120Tul": 30941, "\u0120bleak": 30942, "ELY": 30943, "ivist": 30944, "lightly": 30945, "Pers": 30946, "\u0120Dob": 30947, "\u0120LS": 30948, "\u0120insanity": 30949, "\u00ce\u00b5": 30950, "atalie": 30951, "Enlarge": 30952, "\u0120twists": 30953, "\u0120faulty": 30954, "\u0120piracy": 30955, "\u0120impover": 30956, "\u0120rugged": 30957, "\u0120Fashion": 30958, "\u0120sands": 30959, "'?": 30960, "swick": 30961, "\u0120natives": 30962, "\u0120hen": 30963, "\u0120Noise": 30964, "\u00e3\u0125\u0139": 30965, "\u0120greens": 30966, "\u0120freezer": 30967, "\u0120dynasty": 30968, "\u0120Fathers": 30969, "\u0120Newark": 30970, "\u0120archaeological": 30971, "\u0120ot": 30972, "obar": 30973, "\u0120blockade": 30974, "\u0120allerg": 30975, "LV": 30976, "\u0120debit": 30977, "\u0120RFC": 30978, "\u0120Milton": 30979, "\u0120Pressure": 30980, "\u0120willingly": 30981, "\u0120disproportionate": 30982, "\u0120oppressive": 30983, "\u0120diamonds": 30984, "\u0120belongings": 30985, "1970": 30986, "\u0120bells": 30987, "\u0120imperialism": 30988, "\u0120227": 30989, "\u0120exploding": 30990, "\u0120Eclipse": 30991, "\u01201919": 30992, "\u0120rant": 30993, "\u0120nominations": 30994, "347": 30995, "\u0120peacefully": 30996, "rica": 30997, "\u0120FUCK": 30998, "\u0120vibration": 30999, "malink": 31000, "\u0120ropes": 31001, "\u0120Ivanka": 31002, "\u0120Brewery": 31003, "\u0120Booker": 31004, "\u0120Owens": 31005, "goers": 31006, "Services": 31007, "\u0120Snape": 31008, "\u0120191": 31009, "395": 31010, "\u0120299": 31011, "justice": 31012, "\u0120bri": 31013, "\u0120discs": 31014, "\u0120prominently": 31015, "\u0120vulgar": 31016, "\u0120skipping": 31017, "lves": 31018, "\u0120tsunami": 31019, "374": 31020, "\u0120Urug": 31021, "\u0120Eid": 31022, "recated": 31023, "phen": 31024, "\u0120faults": 31025, "\u0120Started": 31026, "950": 31027, "\u0120pi": 31028, "\u0120detector": 31029, "\u0120bastard": 31030, "\u0120validated": 31031, "SpaceEngineers": 31032, "OURCE": 31033, "\u0120(~": 31034, "\u0120unsur": 31035, "\u0120affirmed": 31036, "\u0120fascism": 31037, "\u0120resolving": 31038, "\u0120Chavez": 31039, "\u0120Cyn": 31040, "\u0120detract": 31041, "Lost": 31042, "\u0120rigged": 31043, "\u0120homage": 31044, "\u0120Bruno": 31045, "555": 31046, "eca": 31047, "\u0120presses": 31048, "\u0120humour": 31049, "\u0120spacing": 31050, "\u0120'/": 31051, "olkien": 31052, "Coun": 31053, "OPER": 31054, "Tre": 31055, "Son": 31056, "\u0120Cambodia": 31057, "ierre": 31058, "mong": 31059, "ozy": 31060, "\u0120liquidity": 31061, "\u0120Soviets": 31062, "\u0120Fernando": 31063, "\u0120229": 31064, "\u0120slug": 31065, "\u0120Catalan": 31066, "electric": 31067, "\u0120scenery": 31068, "\u0120Hearth": 31069, "\u0120constrained": 31070, "\u0120goalie": 31071, "\u0120Guidelines": 31072, "\u0120Ammo": 31073, "\u0120Pearson": 31074, "\u0120taxed": 31075, "\u0120fetus": 31076, "Response": 31077, "\u0120Alexis": 31078, "thia": 31079, "Guy": 31080, "\u0120reconstruct": 31081, "\u0120extremes": 31082, "\u0120concluding": 31083, "\u0120Peg": 31084, "ooks": 31085, "\u0120deductions": 31086, "Rose": 31087, "\u0120groundbreaking": 31088, "\u0120Targ": 31089, "\u00e3\u0125\u0123": 31090, "\u0120Reve": 31091, "resource": 31092, "\u0120moons": 31093, "\u0120electromagnetic": 31094, "\u0120amidst": 31095, "\u0120Viktor": 31096, "NESS": 31097, "BACK": 31098, "\u0120commute": 31099, "\u0120Anaheim": 31100, "\u0120fluctuations": 31101, "640": 31102, "\u0120noodles": 31103, "\u0120Copenhagen": 31104, "\u0120Tide": 31105, "\u0120Grizz": 31106, "\u0120SEE": 31107, "\u0120pipelines": 31108, "\u0120scars": 31109, "endo": 31110, "agus": 31111, "\u0120ETF": 31112, "/#": 31113, "\u0120Become": 31114, "448": 31115, "\u0120visc": 31116, "\u0120Recommended": 31117, "\u0120jumper": 31118, "\u0120cognition": 31119, "\u0120assassin": 31120, "\u0120witnessing": 31121, "\u0120Setup": 31122, "\u0120lac": 31123, "vim": 31124, "ISM": 31125, "pages": 31126, "SSL": 31127, "358": 31128, "\u0120adject": 31129, "industrial": 31130, "lore": 31131, "chery": 31132, "\u0120glitter": 31133, "\u0120calf": 31134, "Florida": 31135, "\u0120spoilers": 31136, "\u0120succeeds": 31137, "\u0120chanting": 31138, "\u0120slogans": 31139, "\u0120Tracy": 31140, "Visit": 31141, "rology": 31142, "\u0120mornings": 31143, "\u0120lineage": 31144, "\u0120sip": 31145, "\u0120intensely": 31146, "\u0120flourish": 31147, "\u0120Sleeping": 31148, "\u0120Fem": 31149, "orpor": 31150, "\u0120Klan": 31151, "\u0120Darth": 31152, "hack": 31153, "\u0120Nielsen": 31154, "\u0120tumors": 31155, "\u0120procurement": 31156, "\u0120Yorkshire": 31157, "\u0120raided": 31158, "KY": 31159, "Anna": 31160, "\u0120//[": 31161, "\u0120Disorder": 31162, "\u0120Mustang": 31163, "\u0120Wen": 31164, "\u0120Trying": 31165, "sq": 31166, "\u0120deliveries": 31167, "\u0120shutter": 31168, "\u0120cerebral": 31169, "\u0120bipolar": 31170, "\u0120CN": 31171, "lass": 31172, "jet": 31173, "\u0120debating": 31174, ">:": 31175, "\u0120eagle": 31176, "grades": 31177, "\u0120Dixon": 31178, "UGC": 31179, "MAS": 31180, "\u0120Draco": 31181, "\u0120Machines": 31182, "affer": 31183, "\u0120eman": 31184, "\u00c2\u00b2": 31185, "pron": 31186, "\u0120Gym": 31187, "\u0120comparatively": 31188, "\u0120Tribunal": 31189, "PRO": 31190, "\u0120lex": 31191, "\u0120fertile": 31192, "\u0120depressing": 31193, "\u0120superficial": 31194, "essential": 31195, "\u0120Hunters": 31196, "gp": 31197, "\u0120prominence": 31198, "Liber": 31199, "\u0120Ancest": 31200, "otechnology": 31201, "\u0120mocking": 31202, "\u0120Traff": 31203, "\u0138\u013c": 31204, "Medium": 31205, "Iraq": 31206, "\u0120psychiatrist": 31207, "Quantity": 31208, "\u0120Lect": 31209, "\u0120noisy": 31210, "520": 31211, "GY": 31212, "\u0120slapped": 31213, "\u0120MTV": 31214, "\u0120para": 31215, "pull": 31216, "Multiple": 31217, "asher": 31218, "\u0120nour": 31219, "\u0120Seg": 31220, "Spell": 31221, "vous": 31222, "ordial": 31223, "Senior": 31224, "\u0120Goldberg": 31225, "\u0120Plasma": 31226, "need": 31227, "\u0120messenger": 31228, "eret": 31229, "\u0120teamed": 31230, "\u0120literacy": 31231, "\u0120Leah": 31232, "\u0120Doyle": 31233, "\u0120emitted": 31234, "UX": 31235, "\u0120evade": 31236, "\u0120maze": 31237, "\u0120wrongly": 31238, "\u0120Lars": 31239, "\u0120stereotype": 31240, "\u0120pledges": 31241, "\u0120aroma": 31242, "\u0120MET": 31243, "\u0120acre": 31244, "\u0120OD": 31245, "\u0120ff": 31246, "\u0120breweries": 31247, "\u0120Hilton": 31248, "undle": 31249, "\u0120Kak": 31250, "\u0120Thankfully": 31251, "\u0120Canucks": 31252, "inctions": 31253, "\u0120Appears": 31254, "\u0120coer": 31255, "\u0120undermined": 31256, "rovers": 31257, "Andre": 31258, "\u0120blaze": 31259, "umers": 31260, "\u0120famine": 31261, "amphetamine": 31262, "ulkan": 31263, "Amount": 31264, "\u0120desperation": 31265, "wikipedia": 31266, "development": 31267, "\u0120Corinth": 31268, "ussia": 31269, "Jackson": 31270, "LI": 31271, "Native": 31272, "Rs": 31273, "Ohio": 31274, "\u0120Kathleen": 31275, "Fortunately": 31276, "\u0120attendant": 31277, "\u0120Preferred": 31278, "\u0120Didn": 31279, "\u0120Vs": 31280, "Mis": 31281, "\u0120respondent": 31282, "\u0120boun": 31283, "stable": 31284, "\u0120paved": 31285, "\u0120unexpl": 31286, "\u0120Cheney": 31287, "LM": 31288, "\u0120Cull": 31289, "blown": 31290, "\u0120confronting": 31291, "ocese": 31292, "serving": 31293, "Wi": 31294, "\u0120Lithuania": 31295, "anni": 31296, "\u0120stalk": 31297, "hd": 31298, "\u0120vener": 31299, "APH": 31300, "ynchronous": 31301, "URR": 31302, "umably": 31303, "historic": 31304, "Half": 31305, "Hay": 31306, "\u0120resilience": 31307, "spection": 31308, "\u0120abandoning": 31309, "Obs": 31310, "\u0120Debbie": 31311, "\u0120gradient": 31312, "\u0120Plaint": 31313, "\u0120Canal": 31314, "ARCH": 31315, "\u0120expansive": 31316, "\u0120fung": 31317, "\u0120bounced": 31318, "Und": 31319, "\u0120precautions": 31320, "\u0120clarification": 31321, "\u0120dagger": 31322, "\u0120grips": 31323, "\u0120\u00c2\u00b5": 31324, "\u0120Rivera": 31325, "\u0120Undead": 31326, "isites": 31327, "\u0120FIRST": 31328, "\u00c3\u00b1o": 31329, "audi": 31330, "\u0120hostages": 31331, "\u0120compliant": 31332, "\u0120alumni": 31333, "Seven": 31334, "\u0120cybersecurity": 31335, "either": 31336, "Collect": 31337, "\u0120invariably": 31338, "\u0120Soci": 31339, "\u0120lawmaker": 31340, "\u0120ale": 31341, "\u0120Personally": 31342, "Nazi": 31343, "\u0120customization": 31344, "\u0120Proc": 31345, "\u0120Saskatchewan": 31346, "eaturing": 31347, "\u0120spared": 31348, "\u0120discontinued": 31349, "\u0120computational": 31350, "\u0120Motorola": 31351, "\u0120supremacist": 31352, "governmental": 31353, "\u0120paradise": 31354, "\u0120Downing": 31355, "\u0120Nikon": 31356, "\u0120catalyst": 31357, "berra": 31358, "Toronto": 31359, "875": 31360, "beta": 31361, "\u0120Macron": 31362, "\u0120unrealistic": 31363, "vector": 31364, "\u0120Vehicles": 31365, "itiveness": 31366, "\u0120RV": 31367, "\u0120Colbert": 31368, "sin": 31369, "oji": 31370, "entin": 31371, "\u0120Krish": 31372, "hello": 31373, "ffield": 31374, "oky": 31375, "\u0120Tate": 31376, "\u0120maple": 31377, "\u0120aids": 31378, "chemical": 31379, "334": 31380, "nuts": 31381, "\u0120Warp": 31382, "\u0120xx": 31383, "\u0120Robb": 31384, "umerous": 31385, "_-_": 31386, "ftime": 31387, "\u0120VW": 31388, "\u0120winger": 31389, "\u0120Dome": 31390, "tools": 31391, "\u0120PV": 31392, "\u0120Georgetown": 31393, "\u0120geared": 31394, "\u0120jihadists": 31395, "\u0120cp": 31396, "\u0120steroids": 31397, "Mother": 31398, "clerosis": 31399, "\u0120DRM": 31400, "nesia": 31401, "\u0120linger": 31402, "\u0120immersive": 31403, "\u0120COUN": 31404, "\u0120outweigh": 31405, "ensual": 31406, "Band": 31407, "\u0120transforms": 31408, "matched": 31409, "psons": 31410, "\u0120Judicial": 31411, "factor": 31412, "\u0120referral": 31413, "\u0120oddly": 31414, "\u0120Wenger": 31415, "Bring": 31416, "\u0120Bows": 31417, "602": 31418, "ICLE": 31419, "\u0120lions": 31420, "\u0120Academic": 31421, "\u0120Thorn": 31422, "\u0120Raider": 31423, "kefeller": 31424, "Storage": 31425, "Lower": 31426, "\u0120Ort": 31427, "\u0120Equality": 31428, "ALT": 31429, "\u0120SOC": 31430, "Types": 31431, "\u0120lyn": 31432, "\u0120Asset": 31433, "coat": 31434, "TPP": 31435, "CVE": 31436, "\u0120Pioneer": 31437, "application": 31438, "Modern": 31439, "\u0120HK": 31440, "Environment": 31441, "Alright": 31442, "Rain": 31443, "IPP": 31444, "\u0120Shiite": 31445, "\u0120mound": 31446, "\u0120Abilities": 31447, "condition": 31448, "Staff": 31449, "\u0120competence": 31450, "\u0120Moor": 31451, "\u0120Diablo": 31452, "\u0120withheld": 31453, "\u0120ostensibly": 31454, "\u0120Brom": 31455, "\u0120msg": 31456, "\u0120denomin": 31457, "\u0120References": 31458, "\u0120FP": 31459, "\u0120plunged": 31460, "\u0120pamph": 31461, "moving": 31462, "central": 31463, "\u0120downright": 31464, "\u0120fading": 31465, "Tal": 31466, "Typ": 31467, "\u0120Thy": 31468, "ukes": 31469, "ithe": 31470, "\u0120ove": 31471, "\u0120battled": 31472, "\u0120seafood": 31473, "\u0120figur": 31474, "\u0120RD": 31475, "crop": 31476, "\u0120squads": 31477, "{\\": 31478, "\u00e0\u00b9": 31479, "\u0120Eh": 31480, "\u0120interviewing": 31481, "\u0120Qin": 31482, "\u0120aspiring": 31483, "PLIC": 31484, "\u0120clauses": 31485, "\u0120Gast": 31486, "\u0120Nir": 31487, "\u0120luggage": 31488, "\u0120hose": 31489, "\u0120systemd": 31490, "\u0120descending": 31491, "\u0120Revised": 31492, "\u0120Rails": 31493, "align": 31494, "709": 31495, "337": 31496, "\u0120fug": 31497, "charging": 31498, "tags": 31499, "\u0120uter": 31500, "kish": 31501, "WARNING": 31502, "490": 31503, "profits": 31504, "\u0120voyage": 31505, "\u0120ace": 31506, "\u0120Vanguard": 31507, "\u0120Tanks": 31508, "\u0120Muk": 31509, "\u0120226": 31510, "Safe": 31511, "Armor": 31512, "\u0120volcanic": 31513, "\u0120womb": 31514, "\u0120MIL": 31515, "\u0120beginner": 31516, "\u0120Recogn": 31517, "\u0120AAP": 31518, "PLAY": 31519, ")!": 31520, "\u0120detecting": 31521, "cn": 31522, "\u0120breaches": 31523, "Basically": 31524, "\u0120Pag": 31525, "\u0120Municipal": 31526, "\u0120Indie": 31527, "\u0120Laf": 31528, "\u0120Disable": 31529, "\u0120Olson": 31530, "\u0120restrained": 31531, "\u0120rulings": 31532, "\u0120humane": 31533, "events": 31534, "\u0120Cinema": 31535, "displayText": 31536, "\u0120Hatch": 31537, "actionDate": 31538, "onnaissance": 31539, "\u0120assaulting": 31540, "\u0120Lug": 31541, "CHAT": 31542, "\u0120vigorous": 31543, "\u0120Perse": 31544, "\u0120intolerance": 31545, "\u0120Snapchat": 31546, "\u0120Sharks": 31547, "\u0120dummy": 31548, "\u0120Diagn": 31549, "\u0120Guitar": 31550, "imeters": 31551, "403": 31552, "REG": 31553, "Ax": 31554, "\u0120separates": 31555, "\u0120Mahm": 31556, "\u0120tv": 31557, "jah": 31558, "OOL": 31559, "Circ": 31560, "\u0120Windsor": 31561, "ussian": 31562, "\u0120intuition": 31563, "\u0120disdain": 31564, "\u0120Donovan": 31565, "\u0120221": 31566, "Emb": 31567, "\u0120condemning": 31568, "\u0120generosity": 31569, "zzy": 31570, "\u0120panties": 31571, "\u0120Prevent": 31572, "ActionCode": 31573, "ANA": 31574, "342": 31575, "externalActionCode": 31576, "\u0120specifying": 31577, "\u0120crystall": 31578, "Jere": 31579, "\u0120rupt": 31580, "\u0120Apprentice": 31581, "\u0120profiling": 31582, "\u00d0\u00ba": 31583, "Strike": 31584, "\u0120sideline": 31585, "\u0120obligated": 31586, "\u0120occult": 31587, "\u0120bureaucratic": 31588, "antically": 31589, "rupted": 31590, "negative": 31591, "\u0120Ethiopia": 31592, "\u0120Civic": 31593, "\u0120insiders": 31594, "eligible": 31595, "\u0120TVs": 31596, "\u0120BAR": 31597, "\u0120TI": 31598, "iologist": 31599, "\u0120AIR": 31600, "\u0120substituted": 31601, "Arab": 31602, "\u0120Saul": 31603, "\u0120Yog": 31604, "prem": 31605, "\u0120builders": 31606, "\u0120stationary": 31607, "\u0120doubtful": 31608, "\u0120vigorously": 31609, "\u0120thrilling": 31610, "Physical": 31611, "\u0120Carey": 31612, "\u0120Hydra": 31613, "geoning": 31614, "\u0120Sly": 31615, "yton": 31616, "\u0120borrowers": 31617, "\u0120Parkinson": 31618, "\u0120\u00eb": 31619, "\u0120Jamaica": 31620, "\u0120satir": 31621, "\u0120insurgents": 31622, "\u0120Firm": 31623, "\u0120isot": 31624, "\u0120Karn": 31625, "ourning": 31626, "akens": 31627, "docs": 31628, "little": 31629, "\u0120Monaco": 31630, "CLASS": 31631, "Turkey": 31632, "Ly": 31633, "\u0120Conan": 31634, "assic": 31635, "\u0120starred": 31636, "\u0120Pacers": 31637, "eties": 31638, "\u0120tipping": 31639, "Moon": 31640, "\u0120Rw": 31641, "same": 31642, "\u0120cavity": 31643, "\u0120goof": 31644, "\u0120Zo": 31645, "Shock": 31646, "ummer": 31647, "\u0120emphasizes": 31648, "\u0120regrett": 31649, "\u0120novelty": 31650, "\u0120envy": 31651, "\u0120Passive": 31652, "rw": 31653, "505": 31654, "\u0120indifferent": 31655, "\u0120Rica": 31656, "\u0120Himself": 31657, "\u0120Freddie": 31658, "\u0120adip": 31659, "\u00e4\u00b8\u0122": 31660, "\u0120breakout": 31661, "\u0120hurried": 31662, "\u0120Huang": 31663, "\u0120Disk": 31664, "\u0120roaming": 31665, "?????-?????-": 31666, "UV": 31667, "\u0120Ricky": 31668, "\u0120Sigma": 31669, "\u0120marginalized": 31670, "\u0120edits": 31671, "\u0120304": 31672, "memory": 31673, "\u0120specimen": 31674, "293": 31675, "\u00e3\u0123\u00af": 31676, "\u0120vertically": 31677, "\u0120audition": 31678, "\u0120Heck": 31679, "\u0120caster": 31680, "\u0120Holdings": 31681, "adal": 31682, "\u0120Cron": 31683, "\u0120Liam": 31684, "\u0120deflect": 31685, "Pick": 31686, "\u0120Debug": 31687, "REF": 31688, "\u0120versatility": 31689, "othes": 31690, "classified": 31691, "\u0120Mahar": 31692, "\u0120Hort": 31693, "Counter": 31694, "stasy": 31695, "noticed": 31696, "331": 31697, "\u0120Shim": 31698, "fuck": 31699, "\u0120Bie": 31700, "\u0120airing": 31701, "\u0120Protein": 31702, "\u0120Holding": 31703, "\u0120spectators": 31704, "iliated": 31705, "\u0120Thatcher": 31706, "nosis": 31707, "\u00e3\u0125\u00bc\u00e3\u0125\u00b3": 31708, "Tele": 31709, "Boston": 31710, "\u0120Templ": 31711, "stay": 31712, "\u0120declarations": 31713, "479": 31714, "Volume": 31715, "\u0120Designer": 31716, "\u0120Overwatch": 31717, "idae": 31718, "\u0120onwards": 31719, "\u0120nets": 31720, "\u0120Manila": 31721, "particularly": 31722, "\u0120politic": 31723, "oother": 31724, "\u0120portraits": 31725, "\u0120pavement": 31726, "cffff": 31727, "\u0120saints": 31728, "\u0120beginners": 31729, "ESPN": 31730, "\u0120shortcomings": 31731, "\u00e2\u0137\u0132\u00e2\u0137\u0132": 31732, "\u0120comet": 31733, "\u0120Organic": 31734, "quel": 31735, "\u0120hospitalized": 31736, "Break": 31737, "\u0120peel": 31738, "dylib": 31739, "aspx": 31740, "urances": 31741, "\u0120TIM": 31742, "Pg": 31743, "\u0120readable": 31744, "\u0120Malik": 31745, "\u0120muzzle": 31746, "\u0120benchmarks": 31747, "dal": 31748, "\u0120Vacc": 31749, "\u0120Hicks": 31750, "609": 31751, "\u0120Biblical": 31752, "heng": 31753, "\u0120overload": 31754, "\u0120Civilization": 31755, "\u0120immoral": 31756, "\u0120fries": 31757, "\u00e3\u0124\u0134": 31758, "\u0120reproduced": 31759, "\u0120formulation": 31760, "jug": 31761, "irez": 31762, "gear": 31763, "\u0120coached": 31764, "MpServer": 31765, "\u0120SJ": 31766, "\u0120Kw": 31767, "Init": 31768, "deal": 31769, "\u0120Oro": 31770, "\u0120Loki": 31771, "\u0120Songs": 31772, "\u0120232": 31773, "\u0120Louise": 31774, "asionally": 31775, "\u0120uncond": 31776, "ollywood": 31777, "\u0120progressives": 31778, "\u0120Enough": 31779, "\u0120Doe": 31780, "\u0120wreckage": 31781, "\u0120brushed": 31782, "\u0120BaseType": 31783, "\u0120zoning": 31784, "ishable": 31785, "hetically": 31786, "\u0120Caucus": 31787, "\u0120Hue": 31788, "\u0120karma": 31789, "\u0120Sporting": 31790, "\u0120trader": 31791, "\u0120seeming": 31792, "\u0120Capture": 31793, "430": 31794, "bish": 31795, "\u0120tunes": 31796, "\u0120indoors": 31797, "\u0120Sphere": 31798, "\u0120Dancing": 31799, "TERN": 31800, "\u0120nob": 31801, "\u0120GST": 31802, "maps": 31803, "\u0120peppers": 31804, "Fit": 31805, "\u0120oversees": 31806, "\u0120Rabbi": 31807, "\u0120Ruler": 31808, "vertising": 31809, "office": 31810, "xxx": 31811, "\u0120raft": 31812, "Changed": 31813, "\u0120textbooks": 31814, "Links": 31815, "\u0120Omn": 31816, "\u00e3\u0122\u0133": 31817, "\u0120inconvenience": 31818, "\u0120Donetsk": 31819, "=~": 31820, "\u0120implicitly": 31821, "\u0120boosts": 31822, "\u0120Bones": 31823, "\u0120Boom": 31824, "Courtesy": 31825, "\u0120sensational": 31826, "ANY": 31827, "\u0120greedy": 31828, "eden": 31829, "\u0120inexper": 31830, "\u0120Ler": 31831, "\u0120Vale": 31832, "\u0120tighten": 31833, "\u0120EAR": 31834, "\u0120Num": 31835, "\u0120ancestor": 31836, "Sent": 31837, "\u0120Horde": 31838, "urgical": 31839, "allah": 31840, "\u0120sap": 31841, "amba": 31842, "\u0120Spread": 31843, "twitch": 31844, "\u0120grandson": 31845, "\u0120fracture": 31846, "\u0120moderator": 31847, "\u0120Seventh": 31848, "\u0120Reverse": 31849, "\u0120estimation": 31850, "Choose": 31851, "\u0120parach": 31852, "\u0120barric": 31853, "\u00e3\u0122\u0132": 31854, "\u0120compass": 31855, "\u0120allergic": 31856, "\u00e2\u0122\u0137": 31857, "OTHER": 31858, "errilla": 31859, "\u0120wagon": 31860, "\u0120zinc": 31861, "\u0120rubbed": 31862, "\u0120Fuller": 31863, "\u0120Luxembourg": 31864, "\u0120Hoover": 31865, "\u0120liar": 31866, "\u0120Evening": 31867, "\u0120Cobb": 31868, "esteem": 31869, "\u0120selector": 31870, "\u0120Brawl": 31871, "isance": 31872, "\u0120Ek": 31873, "\u0120troop": 31874, "\u0120guts": 31875, "\u0120Appeal": 31876, "\u0120Tibetan": 31877, "\u0120routines": 31878, "\u0120Ment": 31879, "\u0120summarized": 31880, "steamapps": 31881, "\u0120tranqu": 31882, "\u01201929": 31883, "oran": 31884, "\u0120Authent": 31885, "\u0120gmaxwell": 31886, "\u0120apprehens": 31887, "\u0120poems": 31888, "\u0120sausage": 31889, "\u0120Webster": 31890, "urus": 31891, "\u0120themed": 31892, "\u0120lounge": 31893, "\u0120charger": 31894, "Spoiler": 31895, "\u0120spilled": 31896, "hog": 31897, "\u0120Sunder": 31898, "\u0120Ain": 31899, "\u0120Angry": 31900, "\u0120disqual": 31901, "\u0120Frequency": 31902, "\u0120Ethernet": 31903, "\u0120helper": 31904, "Percent": 31905, "\u0120horrifying": 31906, "\u0120ail": 31907, "\u0120Allan": 31908, "EEE": 31909, "\u0120Crossing": 31910, "449": 31911, "\u0120holog": 31912, "\u0120Puzzles": 31913, "\u0120Goes": 31914, "erenn": 31915, "604": 31916, "\u00e3\u0123\u0131": 31917, "\u0120Rafael": 31918, "\u0120atten": 31919, "\u0120Emanuel": 31920, "\u0120upro": 31921, "\u0120Susp": 31922, "Psych": 31923, "\u0120Trainer": 31924, "\u0120NES": 31925, "\u0120Hunts": 31926, "becue": 31927, "\u0120counselor": 31928, "Rule": 31929, "\u0120toxins": 31930, "\u0120banners": 31931, "rifice": 31932, "\u0120greeting": 31933, "\u0120frenzy": 31934, "\u0120allocate": 31935, "\u0120*)": 31936, "expr": 31937, "503": 31938, "\u0120Chick": 31939, "\u0120Torn": 31940, "\u0120consolidation": 31941, "\u0120Fletcher": 31942, "switch": 31943, "frac": 31944, "clips": 31945, "\u0120McKin": 31946, "\u0120Lunar": 31947, "Month": 31948, "ITCH": 31949, "\u0120scholarly": 31950, "raped": 31951, "398": 31952, "\u01201910": 31953, "\u0120egreg": 31954, "\u0120insecure": 31955, "\u0120victorious": 31956, "cffffcc": 31957, "\u0120singled": 31958, "\u0120elves": 31959, "\u0120Wond": 31960, "burst": 31961, "\u0120camoufl": 31962, "\u0120BLACK": 31963, "\u0120conditioned": 31964, "\u00e7\u012b": 31965, "answered": 31966, "\u0120compulsory": 31967, "ascist": 31968, "\u0120podcasts": 31969, "\u0120Frankfurt": 31970, "bnb": 31971, "\u0120neoliberal": 31972, "\u0120Keyboard": 31973, "\u0120Belle": 31974, "warm": 31975, "\u0120trusts": 31976, "\u0120insured": 31977, "\u0120Bucc": 31978, "usable": 31979, "607": 31980, "\u0120Plains": 31981, "\u01201890": 31982, "\u0120sabotage": 31983, "\u0120lodged": 31984, "felt": 31985, "\u0120ga": 31986, "\u0120Narc": 31987, "\u0120Salem": 31988, "\u0120seventy": 31989, "\u0120Blank": 31990, "pocket": 31991, "\u0120whisper": 31992, "\u0120mating": 31993, "omics": 31994, "\u0120Salman": 31995, "\u0120Kad": 31996, "\u0120angered": 31997, "\u0120collisions": 31998, "\u0120extraordinarily": 31999, "\u0120coercion": 32000, "Ghost": 32001, "birds": 32002, "\u00e8\u0122": 32003, "kok": 32004, "\u0120permissible": 32005, "avorable": 32006, "\u0120pointers": 32007, "\u0120dissip": 32008, "aci": 32009, "\u0120theatrical": 32010, "\u0120Cosmic": 32011, "\u0120forgetting": 32012, "\u0120finalized": 32013, "\u00e5\u00a4\u00a7": 32014, "yout": 32015, "library": 32016, "\u0120booming": 32017, "\u0120Believe": 32018, "\u0120Teacher": 32019, "\u0120Liv": 32020, "\u0120GOODMAN": 32021, "\u0120Dominican": 32022, "ORED": 32023, "\u0120Parties": 32024, "\u0120precipitation": 32025, "\u0120Slot": 32026, "Roy": 32027, "\u0120Combined": 32028, "\u0120integrating": 32029, "\u0120chrome": 32030, "\u0120intestinal": 32031, "\u0120Rebell": 32032, "\u0120matchups": 32033, "\u0120blockbuster": 32034, "\u0120Loren": 32035, "\u0120Levy": 32036, "\u0120preaching": 32037, "\u0120Sending": 32038, "\u0120Purpose": 32039, "rax": 32040, "fif": 32041, "\u0120authoritative": 32042, "\u0120PET": 32043, "astical": 32044, "\u0120dishon": 32045, "\u0120chatting": 32046, "\u0120\"$:/": 32047, "Connection": 32048, "\u0120recreate": 32049, "\u0120delinqu": 32050, "\u0120broth": 32051, "\u0120Dirty": 32052, "\u0120Admin": 32053, "zman": 32054, "\u0120scholarships": 32055, "\u0120253": 32056, "contact": 32057, "alsa": 32058, "767": 32059, "creen": 32060, "abbage": 32061, "\u01201915": 32062, "\u0120blended": 32063, "\u0120alarmed": 32064, "Language": 32065, "356": 32066, "\u0120blends": 32067, "\u0120Changed": 32068, "Wolf": 32069, "\u0120hepat": 32070, "Creating": 32071, "\u0120persecut": 32072, "\u0120sweetness": 32073, "arte": 32074, "\u0120forfeiture": 32075, "\u0120Roberto": 32076, "impro": 32077, "NFL": 32078, "\u0120Magnet": 32079, "Detailed": 32080, "\u0120insignificant": 32081, "\u0120POLIT": 32082, "\u0120BBQ": 32083, "\u0120CPS": 32084, "\u0120seaw": 32085, "aminer": 32086, "mL": 32087, "endif": 32088, "finals": 32089, "\u0120265": 32090, "uish": 32091, "\u0120})": 32092, "\u0120Problems": 32093, "\u0120emblem": 32094, "\u0120seriousness": 32095, "\u0120parsing": 32096, "\u0120substitution": 32097, "\u0120pressured": 32098, "\u0120recycled": 32099, "aleb": 32100, "Ruby": 32101, "\u0120proficiency": 32102, "Driver": 32103, "\u0120Wester": 32104, ":'": 32105, "AFTA": 32106, "\u0120mantle": 32107, "\u0120Clayton": 32108, "flag": 32109, "\u0120practitioner": 32110, "covered": 32111, "\u0120Struct": 32112, "addafi": 32113, "425": 32114, "\u0120Township": 32115, "\u0120Hydro": 32116, "Louis": 32117, "343": 32118, "\u0120condo": 32119, "\u0120Tao": 32120, "\u0120utilization": 32121, "\u0120nausea": 32122, "\u0120Dems": 32123, "ridges": 32124, "pause": 32125, "\u0120formulas": 32126, "\u0120challenger": 32127, "376": 32128, "\u0120defective": 32129, "\u0120Railway": 32130, "\u0120PubMed": 32131, "\u0120yogurt": 32132, "lbs": 32133, "\u0120Norfolk": 32134, "OPE": 32135, "\u0120Moody": 32136, "\u0120distributor": 32137, "\u0120scrolls": 32138, "\u0120extracts": 32139, "Stan": 32140, "\u0120viability": 32141, "\u0120exposes": 32142, "\u0120starvation": 32143, "\u0120Steps": 32144, "\u0120Dodd": 32145, "few": 32146, "STD": 32147, "332": 32148, "\u0120closures": 32149, "\u0120complementary": 32150, "\u0120Sasha": 32151, "umpy": 32152, "\u0120monet": 32153, "\u0120articulate": 32154, "\u0120Doct": 32155, "killer": 32156, "\u0120scrim": 32157, "\u0120264": 32158, "\u0120prostitutes": 32159, "\u0120severed": 32160, "\u0120attachments": 32161, "\u0120cooled": 32162, "Lev": 32163, "\u0120Falk": 32164, "fail": 32165, "\u0120policeman": 32166, "\u0120Dag": 32167, "\u0120prayed": 32168, "\u0120Kernel": 32169, "\u0120clut": 32170, "\u0120cath": 32171, "\u0120anomaly": 32172, "Storm": 32173, "emaker": 32174, "\u0120Breakfast": 32175, "uli": 32176, "oire": 32177, "JJ": 32178, "hz": 32179, "Operation": 32180, "\u0120Sick": 32181, "354": 32182, "\u0120Guatemala": 32183, "Rate": 32184, "\u0120exposures": 32185, "faces": 32186, "\u0120Archae": 32187, "raf": 32188, "\u0120Mia": 32189, "\u01202025": 32190, "\u0120opaque": 32191, "\u0120disguised": 32192, "\u0120Headquarters": 32193, "Sah": 32194, "\u0120pots": 32195, "978": 32196, "\u0120Malf": 32197, "\u0120frowned": 32198, "\u0120poisonous": 32199, "\u0120Convers": 32200, "eeks": 32201, "\u0120crab": 32202, ".\"\"": 32203, "\u0120treason": 32204, "\u0120ranc": 32205, "\u0120escalating": 32206, "\u0120warr": 32207, "\u0120mobs": 32208, "\u0120lamps": 32209, "\u0120Sunshine": 32210, "\u0120Brunswick": 32211, "Phones": 32212, "\u0120spelled": 32213, "\u0120Skip": 32214, "\u01202050": 32215, "\u01201911": 32216, "\u0120Pluto": 32217, "\u0120Amend": 32218, "\u0120meats": 32219, "387": 32220, "\u0120stomp": 32221, "\u0120Zhou": 32222, "\u0120Leviathan": 32223, "\u0120Hazard": 32224, "adv": 32225, "\u0120Orwell": 32226, "\u0120aloud": 32227, "\u0120bumper": 32228, "\u0120Anarch": 32229, "ubuntu": 32230, "\u0120Serious": 32231, "fitting": 32232, "\u0120Optional": 32233, "\u0120Cecil": 32234, "REAM": 32235, "\u0120serotonin": 32236, "\u0120cultivate": 32237, "agogue": 32238, "}\\": 32239, "\u0120mosques": 32240, "\u0120Sunny": 32241, "\u0120reactive": 32242, "revolution": 32243, "\u0120Lup": 32244, "\u0120Fedora": 32245, "\u0120defenseman": 32246, "\u0120VID": 32247, "istine": 32248, "\u0120drowning": 32249, "\u0120Broadcasting": 32250, "\u0120thriller": 32251, "\u0120Scy": 32252, "\u0120accelerating": 32253, "\u0120directs": 32254, "odied": 32255, "bike": 32256, "duration": 32257, "\u0120painfully": 32258, "Redd": 32259, "\u0120productions": 32260, "\u0120gag": 32261, "\u0120whist": 32262, "\u0120sock": 32263, "\u0120infinitely": 32264, "\u0120Concern": 32265, "\u0120Citadel": 32266, "\u0120lieu": 32267, "\u0120candles": 32268, "ogeneous": 32269, "arger": 32270, "\u0120heavenly": 32271, "inflammatory": 32272, "Performance": 32273, "Cs": 32274, "ructose": 32275, "azaki": 32276, "\u0120pessim": 32277, "\u0120inference": 32278, "\u0120powd": 32279, "\u0120Zoe": 32280, "\u0120paints": 32281, "\u0120dazz": 32282, "pta": 32283, "-----------": 32284, "\u0120inspir": 32285, "\u0120Experimental": 32286, "\u0120Knife": 32287, "regor": 32288, "bors": 32289, "\u0120showers": 32290, "romeda": 32291, "\u0120saint": 32292, "\u0120benign": 32293, "\u0120Jiang": 32294, "\u0120envisioned": 32295, "\u0120shroud": 32296, "IFT": 32297, "HO": 32298, "\u0120shuff": 32299, "\u0120ICC": 32300, "\u0120segreg": 32301, "\u0120revisit": 32302, "ighthouse": 32303, "Li": 32304, "\u0120substrate": 32305, "\u0120Seas": 32306, "\u0120Reward": 32307, "\u0120Hep": 32308, "\u0120Brass": 32309, "sbm": 32310, "\u0120eliminates": 32311, "\u0120stamina": 32312, "\u0120VAT": 32313, "\u0120Loan": 32314, "\u0120constraint": 32315, "\u0120appropriated": 32316, "\u0120pes": 32317, "\u0120ALE": 32318, "ranging": 32319, "\u0120404": 32320, "392": 32321, "\u0120intellectuals": 32322, "achu": 32323, "\u0120restructuring": 32324, "\u0120Levin": 32325, "\u0120runes": 32326, "\u0120delightful": 32327, "\u0120carbohydrates": 32328, "\u0120Models": 32329, "\u0120Expo": 32330, "\u0120transporting": 32331, "alloc": 32332, "\u0120ringing": 32333, "Samsung": 32334, "\u0120scarcely": 32335, "\u0120URLs": 32336, "\u0120MAS": 32337, "\u0120prototypes": 32338, "\u0120narrator": 32339, "\u0120CPUs": 32340, "cdn": 32341, "\u0120Barton": 32342, "\u0120decidedly": 32343, "\u0120Shu": 32344, "ixir": 32345, "ocious": 32346, "\u0120Myst": 32347, "Nintendo": 32348, "\u0120reuse": 32349, "\u0120forgiven": 32350, "Few": 32351, "inical": 32352, "nat": 32353, "\u0120seamless": 32354, "\u0120Eva": 32355, "\u0120EVE": 32356, "\u0120JO": 32357, "landers": 32358, "\u0120softer": 32359, "negie": 32360, "\u0120transient": 32361, "\u0120orbital": 32362, "\u0120fulfil": 32363, "\u0120Kom": 32364, "Hopefully": 32365, "\u0120dynamically": 32366, "\u0120Hunger": 32367, "\u00e5\u013d": 32368, "\u0120Armenia": 32369, "elman": 32370, "berto": 32371, "\u0120pige": 32372, "\u0120IDs": 32373, "limit": 32374, "\u0120veins": 32375, "\u0120soaring": 32376, "packs": 32377, "Golden": 32378, "\u0120Crab": 32379, "istor": 32380, "\u0120RPM": 32381, "\u0120$$": 32382, "gression": 32383, "\u0120jihadist": 32384, "\u0120gamble": 32385, "\u0120careg": 32386, "\u0120inflated": 32387, "Face": 32388, "\u0120Firearms": 32389, "\u0120Emmanuel": 32390, "\u00e2\u013f": 32391, "\u0120shocks": 32392, "grab": 32393, "\u0120splend": 32394, "\u0120HPV": 32395, "abortion": 32396, "Above": 32397, "Entity": 32398, "players": 32399, "\u0120commenced": 32400, "ulence": 32401, "\u0120fulfillment": 32402, "\u0120embodiments": 32403, "\u0120Welfare": 32404, "\u0120hail": 32405, "\u0120<@": 32406, "tten": 32407, "\u0120catcher": 32408, "\u0120Jazeera": 32409, "\u0120volcano": 32410, "\u0120stabilize": 32411, "\u0120Handler": 32412, "\u0120intensified": 32413, "\u0120Abrams": 32414, "\u0120humiliation": 32415, "paced": 32416, "605": 32417, "\u0120CentOS": 32418, "Specific": 32419, "\u0120heed": 32420, "\u0120CAM": 32421, "\u0120Galile": 32422, "Die": 32423, "\u0120abolished": 32424, "\u0120Thomson": 32425, "\u0120Teachers": 32426, "\u0120Wass": 32427, "jong": 32428, "\u0120ISBN": 32429, "\u0120Allies": 32430, "shake": 32431, "\u00e5\u00b7": 32432, "vict": 32433, "Howard": 32434, "\u0120deem": 32435, "\u0120exceedingly": 32436, "\u0120Smartstocks": 32437, "ibe": 32438, "\u0120doorway": 32439, "\u0120competed": 32440, "igmat": 32441, "\u0120nationalists": 32442, "\u0120groom": 32443, "\u0120Keen": 32444, "\u0120disposable": 32445, "decl": 32446, "\u0120Tolkien": 32447, "\u0120Scheme": 32448, "\u0120biod": 32449, "\u0120avid": 32450, "\u0120Elon": 32451, "agar": 32452, "\u0120TSA": 32453, "Roman": 32454, "\u0120artificially": 32455, "\u0120advisors": 32456, "XL": 32457, "\u0120Inferno": 32458, "366": 32459, "\u0120tedious": 32460, "\u0120Photography": 32461, "\u0120Carrie": 32462, "\u0120trope": 32463, "\u0120Sandra": 32464, "\u0120decimal": 32465, "Queen": 32466, "\u0120Gundam": 32467, "\u0120OM": 32468, "otech": 32469, "NBA": 32470, "\u01201932": 32471, "\u0120entrenched": 32472, "\u0120Marion": 32473, "\u0120fraternity": 32474, "Labour": 32475, "Henry": 32476, "\u0120latitude": 32477, "Either": 32478, "\u0120enhances": 32479, "\u0120Potential": 32480, "\u0120shines": 32481, "idad": 32482, "\u0120breadth": 32483, "\u0120capacities": 32484, "\u0120\u00f0\u0141\u013b\u0124": 32485, "\u0120Bronx": 32486, "\u0120sexes": 32487, "\u0120differentiation": 32488, "\u0120heavyweight": 32489, "\u0120Taj": 32490, "dra": 32491, "\u0120migrate": 32492, "\u0120exhaustion": 32493, "\u0120RUN": 32494, "elsius": 32495, "\u0120Cuomo": 32496, "\u0120guitars": 32497, "\u0120clones": 32498, "\u0120Somew": 32499, "\u0120Pry": 32500, "-------------": 32501, "\u0120warranted": 32502, "cycles": 32503, "\u0120salvage": 32504, "\u0120disks": 32505, "RANT": 32506, "\u0120NGOs": 32507, "\u0120Martian": 32508, "\":[{\"": 32509, "\u0120addicts": 32510, "ojure": 32511, "illet": 32512, "\u0120amazingly": 32513, "artments": 32514, "pixel": 32515, "\u0120GPUs": 32516, "Layout": 32517, "\u00e8\u00a3": 32518, "\u0120Tamil": 32519, "\u0120Basil": 32520, "\u0120impartial": 32521, "\u0120Structure": 32522, "fork": 32523, "bryce": 32524, "\u0120ridge": 32525, "\u0120Hamburg": 32526, "rious": 32527, "\u0120blitz": 32528, "cigarettes": 32529, "\u0120canned": 32530, "402": 32531, "\u0120ironically": 32532, "\u0120compassionate": 32533, "\u0120Hawkins": 32534, ".#": 32535, "\u0120Cathedral": 32536, "\u0120rallied": 32537, "internal": 32538, "\u0120quota": 32539, "stakes": 32540, "TEXT": 32541, "mom": 32542, "\u0120completes": 32543, "\u0120238": 32544, "\u0120shrug": 32545, "\u00e3\u0125\u0133": 32546, "\u0120Ninth": 32547, "\u0120revise": 32548, "\u0120Provider": 32549, "\u0120treacher": 32550, "\u0120quasi": 32551, "\u0120PRES": 32552, "\u0120deposition": 32553, "\u0120confidentiality": 32554, "issors": 32555, "\u0120imbalance": 32556, "\u0120spanning": 32557, "\u0120angular": 32558, "\u0120Cul": 32559, "communication": 32560, "\u0120Nora": 32561, "\u0120Genius": 32562, "opter": 32563, "\u0120sacked": 32564, "Spot": 32565, "\u0120finely": 32566, "\u0120CHR": 32567, "282": 32568, "waves": 32569, "Palest": 32570, "\u0120Rohing": 32571, "NL": 32572, "\u00e8\u00bf": 32573, "\u0120shitty": 32574, "\u0120Scalia": 32575, "475": 32576, "Progress": 32577, "\u0120referencing": 32578, "\u0120classrooms": 32579, "abee": 32580, "\u0120sod": 32581, "hesion": 32582, "708": 32583, "\u0120Zuckerberg": 32584, "\u0120Finish": 32585, "\u0120Scotia": 32586, "\u0120Savior": 32587, "\u0120Installation": 32588, "antha": 32589, "(-": 32590, "\u0120302": 32591, "\u0120Punk": 32592, "\u0120crater": 32593, "youtu": 32594, "\u0120roast": 32595, "\u0120influencing": 32596, "\u0120dup": 32597, "\u0120JR": 32598, "\u0120Grav": 32599, "\u0120stature": 32600, "\u0120bathrooms": 32601, "Aside": 32602, "Wiki": 32603, "mean": 32604, "\u0120Zak": 32605, "\u0120Ones": 32606, "\u0120Nath": 32607, "\u0120hypert": 32608, "\u0120commencement": 32609, "Civil": 32610, "\u0120moderately": 32611, "\u0120distributors": 32612, "\u0120breastfeeding": 32613, "\u0120980": 32614, "\u0120Sik": 32615, "\u0120Cig": 32616, "\u0120AMER": 32617, "RIP": 32618, "\u0120Career": 32619, "usting": 32620, "\u0120messed": 32621, "\u0120eh": 32622, "\u0120Jensen": 32623, "/$": 32624, "\u0120blackmail": 32625, "\u0120conversions": 32626, "\u0120scientifically": 32627, "\u0120mantra": 32628, "paying": 32629, "\u0120ivory": 32630, "\u0120Courts": 32631, "OUGH": 32632, "auntlet": 32633, "Serial": 32634, "Brow": 32635, "\u0120Hundreds": 32636, "323": 32637, "\u0120pee": 32638, "\u0120linux": 32639, "\u0120submer": 32640, "\u0120Principal": 32641, "485": 32642, "\u0120DSL": 32643, "\u0120Cousins": 32644, "\u0120doctrines": 32645, "\u0120Athletics": 32646, "\u0120315": 32647, "\u0120Karma": 32648, "\u0120attent": 32649, "urger": 32650, "\u0120prescribe": 32651, "\u0120encaps": 32652, "\u0120Came": 32653, "\u0120secretive": 32654, "\u0120Crimes": 32655, "dn": 32656, "Clean": 32657, "\u0120Egyptians": 32658, "\u0120Carpenter": 32659, "\u0120ll": 32660, "Hum": 32661, "\u0120Milo": 32662, "\u0120capitalists": 32663, "\u0120briefed": 32664, "Twe": 32665, "\u0120Basin": 32666, "elvet": 32667, "Mos": 32668, "\u0120plunge": 32669, "\u0120Kaiser": 32670, "\u0120Fuj": 32671, "illin": 32672, "\u0120safeguards": 32673, "\u0120oste": 32674, "\u0120Opportunity": 32675, "\u0120Mafia": 32676, "\u0120Calling": 32677, "apa": 32678, "urban": 32679, "brush": 32680, "illard": 32681, "c\u00c3\u00a9": 32682, "intelligence": 32683, "\u0120Lob": 32684, "\u0120Druid": 32685, "\u0120smoother": 32686, "\u0120footing": 32687, "\u0120motorists": 32688, "arcity": 32689, "\u0120masculinity": 32690, "\u0120mism": 32691, "\u0120abdominal": 32692, "\u0120Tavern": 32693, "\u0120Roh": 32694, "\u0120escapes": 32695, "signed": 32696, "Anthony": 32697, "\u0120sacrificing": 32698, "\u0120intimacy": 32699, "\u0120anterior": 32700, "\u0120Kod": 32701, "\u0120motif": 32702, "\u0120graz": 32703, "\u0120visualization": 32704, "\u0120guitarist": 32705, "\u0120Trotsky": 32706, "magic": 32707, "Dar": 32708, "\u0120Mori": 32709, "\u0120wards": 32710, "\u0120toilets": 32711, "lest": 32712, "\u0120teleport": 32713, "\u0120Sundays": 32714, "\u0120Plat": 32715, "ETS": 32716, "\u0120eSports": 32717, "Patrick": 32718, "\u0120Katherine": 32719, "enko": 32720, "\u0120hassle": 32721, "\u0120Mick": 32722, "ggles": 32723, "\u0120hob": 32724, "aintain": 32725, "\u0120airborne": 32726, "\u0120spans": 32727, "\u0120chili": 32728, "\u0120aperture": 32729, "\u0120volunteered": 32730, "\u0120Incident": 32731, "\u0120Fres": 32732, "\u0120Veteran": 32733, "aughtered": 32734, "ingo": 32735, "\u0120uninsured": 32736, "CLOSE": 32737, "\u0120fuse": 32738, "\u0120erotic": 32739, "\u0120advertise": 32740, "raising": 32741, "Texture": 32742, "\u0120attends": 32743, "\u0120REAL": 32744, "uddled": 32745, "\u0120smoot": 32746, "\u0120305": 32747, "\u0120Willis": 32748, "\u0120blond": 32749, "Analysis": 32750, "\u0120VT": 32751, "onica": 32752, "\u0120stronghold": 32753, "RF": 32754, "NM": 32755, ".>>": 32756, "\u0120prosperous": 32757, "\u0120boasted": 32758, "292": 32759, "\u0120Manufacturing": 32760, "PRESS": 32761, "gren": 32762, "\u0120pharmacy": 32763, "\u0120Rockefeller": 32764, "kai": 32765, "\u0120thumbs": 32766, "\u0120Hut": 32767, "\u0120motherboard": 32768, "\u0120guardians": 32769, "\u0120Alter": 32770, "llular": 32771, "\u0120shack": 32772, "\u0120wisely": 32773, "\u0120backbone": 32774, "erva": 32775, "\u0120suicides": 32776, "\u0120McGregor": 32777, "ijah": 32778, "Emer": 32779, "\u0120Brav": 32780, "\u0120designate": 32781, "POST": 32782, "produced": 32783, "\u0120cleansing": 32784, "irlwind": 32785, "existent": 32786, "\u0120Humph": 32787, "\u0120Payne": 32788, "\u0120vested": 32789, "\u00c5\u00a1": 32790, "\u0120stringent": 32791, "iona": 32792, "\u0120unsub": 32793, "\u0120summed": 32794, "\u0120Hercules": 32795, "subject": 32796, "\u0120Ragnar": 32797, "\u0120Nos": 32798, "\u0120characterization": 32799, "\u0120savvy": 32800, "\u0120Dawson": 32801, "\u0120Casino": 32802, "\u0120fri": 32803, "\u0120Barrier": 32804, "\u0120misinformation": 32805, "\u0120insulation": 32806, "\u0120corridors": 32807, "\u0120airplanes": 32808, "\u0120Noct": 32809, "ahi": 32810, "\u01201916": 32811, "kb": 32812, "armac": 32813, "\u0120shun": 32814, "\u0120schema": 32815, "\u0120horrified": 32816, "\u0120239": 32817, "aunders": 32818, "NB": 32819, "iates": 32820, "erity": 32821, "\u0120Shard": 32822, "\u0120rarity": 32823, "\u0120grouped": 32824, "\u0120Ghana": 32825, "against": 32826, "\u0120Biological": 32827, "\u0120Aware": 32828, "owell": 32829, "\u00cf\u0126": 32830, "\u0120Beau": 32831, "shaw": 32832, "Hack": 32833, "\u0120Julius": 32834, "USS": 32835, "olson": 32836, "auna": 32837, "cru": 32838, "\u0120Maurice": 32839, "\u0120Ik": 32840, "\u0120sequencing": 32841, "\u0120radicals": 32842, "\u0120(?,": 32843, "virtual": 32844, "\u0120anyways": 32845, "\u0120reperc": 32846, "\u0120handlers": 32847, "\u0120hesitant": 32848, "\u00e9\u0125": 32849, "\u0120MF": 32850, "plementation": 32851, "associated": 32852, "\u0120campaigned": 32853, "\u0120Yue": 32854, "utations": 32855, "\u0120Yoga": 32856, "\u0120simmer": 32857, "\u0120rods": 32858, "\u0120melody": 32859, "\u0120convoy": 32860, "videos": 32861, "\u0120screened": 32862, "Neg": 32863, "ochemical": 32864, "\u0120())": 32865, "\u0120ultras": 32866, "\u0120antip": 32867, "\u0120Islanders": 32868, "704": 32869, "\u0120fetish": 32870, "\u0120ridiculously": 32871, "\u0120Kart": 32872, "\u0120mitochondrial": 32873, "\u0120interfering": 32874, "Builder": 32875, "\u0120overfl": 32876, "\u0120acne": 32877, "\u0120Mud": 32878, "\u0120Kerr": 32879, "flex": 32880, "\u0120Postal": 32881, "\u0120Baltic": 32882, "477": 32883, "\u0120Persons": 32884, "ourage": 32885, "HB": 32886, "\u0120Muse": 32887, "\u0120Immortal": 32888, "\u0120Driving": 32889, "\u0120petitions": 32890, "\u0120subscript": 32891, "\u0120sorce": 32892, "\u0120Processor": 32893, "uton": 32894, "Sony": 32895, "\u0120phon": 32896, "\u0120raced": 32897, "\u0120Anthrop": 32898, "\u0120daytime": 32899, "\u0120Exercise": 32900, "Adding": 32901, "\u0120engages": 32902, "\u0120Qualcomm": 32903, "\u0120miracles": 32904, "\u0120memes": 32905, "\u0120Drink": 32906, "\u0120Orioles": 32907, "\u0120hairs": 32908, "\u0120Polar": 32909, "athom": 32910, "\u0120slippery": 32911, "\u0120Remy": 32912, "\u0120caramel": 32913, "\u0120YEAR": 32914, "\u0120alk": 32915, "Ign": 32916, "aution": 32917, "\u0120Merlin": 32918, "\u0120Cran": 32919, "\u0120apologies": 32920, "\u0120410": 32921, "\u0120outing": 32922, "\u0120Memories": 32923, "appointed": 32924, "\u0120countered": 32925, "uld": 32926, "posing": 32927, "\u0120firewall": 32928, "\u0120Wast": 32929, "\u0120Wet": 32930, "worked": 32931, "seller": 32932, "\u0120repealed": 32933, "ereo": 32934, "assuming": 32935, "BLIC": 32936, "mite": 32937, "\u0120CEOs": 32938, "\u0120Chapel": 32939, "elligent": 32940, "________________________": 32941, "Dog": 32942, "\u0120wart": 32943, "\u0120subscriber": 32944, "sports": 32945, "\u0120begged": 32946, "\u0120MV": 32947, "\u0120semif": 32948, "ethical": 32949, "\u0120preach": 32950, "\u0120revital": 32951, "\u0120punitive": 32952, "\u0120shortcuts": 32953, "\u0120instituted": 32954, "\u0120Warsaw": 32955, "\u0120abdomen": 32956, "\u0120KING": 32957, "\u0120superintendent": 32958, "\u0120fry": 32959, "\u0120Geo": 32960, "TOR": 32961, "\u0120contradictions": 32962, "aptic": 32963, "\u0120landscapes": 32964, "bugs": 32965, "\u0120clust": 32966, "\u0120volley": 32967, "cribed": 32968, "\u0120tandem": 32969, "\u0120robes": 32970, "WHAT": 32971, "\u0120promoter": 32972, "\u0120eloqu": 32973, "reviewed": 32974, "\u0120DK": 32975, "\u0120Plato": 32976, "\u0120fps": 32977, "Tank": 32978, "\u0120Derrick": 32979, "\u0120prioritize": 32980, "asper": 32981, "\u0120Honduras": 32982, "\u0120Completed": 32983, "nec": 32984, "\u0120mog": 32985, "nir": 32986, "\u0120Mayo": 32987, "DEF": 32988, "stall": 32989, "inness": 32990, "\u0120Volkswagen": 32991, "\u0120precaution": 32992, "\u0120Mell": 32993, "iak": 32994, "istries": 32995, "\u0120248": 32996, "\u0120overlapping": 32997, "Senate": 32998, "\u0120Enhance": 32999, "resy": 33000, "racial": 33001, "ORTS": 33002, "\u0120Mormons": 33003, "Strong": 33004, "\u0120Coch": 33005, "Mexico": 33006, "\u0120Maduro": 33007, "\u0120jars": 33008, "\u0120cane": 33009, "Wik": 33010, "olla": 33011, "ifference": 33012, "\u0120physicist": 33013, "\u0120Maggie": 33014, "\u0120285": 33015, "\u0120depiction": 33016, "\u0120McLaren": 33017, "Ju": 33018, "\u0120slows": 33019, "\u0120commissioners": 33020, "\u0120Willow": 33021, "\u0120Explos": 33022, "hovah": 33023, "\u0120technician": 33024, "\u0120homicides": 33025, "\u0120Flav": 33026, "\u0120Truman": 33027, "\u012010000": 33028, "uctor": 33029, "\u0120shader": 33030, "Newsletter": 33031, "457": 33032, "\u0120rever": 33033, "\u0120hardened": 33034, "\u0120whereabouts": 33035, "\u0120redevelop": 33036, "\u0120carbs": 33037, "\u0120travers": 33038, "\u0120squirrel": 33039, "\u0120follower": 33040, "\u0120sings": 33041, "508": 33042, "\u0120rabbits": 33043, "emonium": 33044, "\u0120documenting": 33045, "\u0120misunderstood": 33046, ")'": 33047, "Rick": 33048, "ggies": 33049, "\u0120premie": 33050, "\u0120skating": 33051, "\u0120passports": 33052, "\u0120fists": 33053, "ageddon": 33054, "Haw": 33055, "ACP": 33056, "080": 33057, "\u0120Thoughts": 33058, "\u0120Carlson": 33059, "\u0120priesthood": 33060, "hua": 33061, "\u0120dungeons": 33062, "\u0120Loans": 33063, "\u0120antis": 33064, "\u0120familiarity": 33065, "\u0120Sabb": 33066, "opal": 33067, "\u0120Ink": 33068, "strike": 33069, "\u0120cram": 33070, "\u0120legalized": 33071, "\u0120cuisine": 33072, "\u0120fibre": 33073, "Travel": 33074, "\u0120Monument": 33075, "ODY": 33076, "ethy": 33077, "\u0120interstate": 33078, "\u0120PUR": 33079, "emporary": 33080, "\u0120Arabian": 33081, "developed": 33082, "\u0120saddle": 33083, "\u0120github": 33084, "\u0120Offer": 33085, "\u0120ISP": 33086, "rolet": 33087, "\u0120SUPER": 33088, "\u0120Denis": 33089, "\u0120multiplier": 33090, "\u0120stirred": 33091, "Interestingly": 33092, "\u0120customary": 33093, "\u0120billed": 33094, "hex": 33095, "\u0120multiplied": 33096, "\u0120flipping": 33097, "\u0120Crosby": 33098, "\u0120fundamentals": 33099, "iae": 33100, "\u0120Played": 33101, "\u0120Atom": 33102, "amazon": 33103, "\u0120Flam": 33104, "eez": 33105, "activated": 33106, "\u0120tablespoon": 33107, "\u0120liberalism": 33108, "\u0120Palin": 33109, "\u0120Patel": 33110, "Num": 33111, "\u0120TAM": 33112, "\u0120surn": 33113, "\u0120Reloaded": 33114, "\u0120coined": 33115, "\"],": 33116, "\u0120Clash": 33117, "\u0120Agu": 33118, "\u0120pragmatic": 33119, "\u0120Activate": 33120, "\u0120802": 33121, "\u0120trailers": 33122, "\u0120silhou": 33123, "\u0120probes": 33124, "\u0120circus": 33125, "\u0120Bain": 33126, "\u0120Lindsay": 33127, "\u0120Abbey": 33128, "Delivery": 33129, "\u0120concession": 33130, "\u0120gastro": 33131, "\u0120Sprite": 33132, "\u00c4\u0141": 33133, "andel": 33134, "\u0120gimm": 33135, "\u0120autobi": 33136, "\u0120Turtle": 33137, "\u0120wonderfully": 33138, "\u0120Haram": 33139, "\u0120Worldwide": 33140, "\u0120Handle": 33141, "\u0120theorists": 33142, "\u0120sleek": 33143, "\u0120Zhu": 33144, "ographically": 33145, "EGA": 33146, "\u0120Owners": 33147, "aths": 33148, "\u0120Antarctic": 33149, "natal": 33150, "=\"\"": 33151, "flags": 33152, "````": 33153, "\u0120sul": 33154, "Kh": 33155, "\u0120potassium": 33156, "\u0120lineman": 33157, "\u0120cereal": 33158, "\u0120Seasons": 33159, "\u01202022": 33160, "\u0120mathematic": 33161, "\u0120astronomers": 33162, "professional": 33163, "\u0120fares": 33164, "cknowled": 33165, "\u0120chi": 33166, "\u0120youngsters": 33167, "\u0120mistakenly": 33168, "\u0120hemisphere": 33169, "\u0120Divinity": 33170, "rone": 33171, "\u0120\",": 33172, "rings": 33173, "\u0120attracts": 33174, "vana": 33175, "\u00e5\u00b9": 33176, "CAP": 33177, "\u0120playlist": 33178, "\u0120porch": 33179, "\u00e3\u0123\u00a3": 33180, "\u0120incorporates": 33181, "\u0120soak": 33182, "\u0120asserting": 33183, "\u0120Terrorism": 33184, "\u0120Pablo": 33185, "Ja": 33186, "cester": 33187, "\u0120fearing": 33188, "\u0120Prayer": 33189, "\u0120escalated": 33190, "GW": 33191, "\u0120robe": 33192, "\u0120Brighton": 33193, "acists": 33194, "\u0120Symphony": 33195, "\u0120Dwarf": 33196, "\u0120Parade": 33197, "\u0120Lego": 33198, "\u0120inexpl": 33199, "\u0120lords": 33200, "leaf": 33201, "RAG": 33202, "liber": 33203, "\u0120cigars": 33204, "\u0120Jehovah": 33205, "606": 33206, "WINDOWS": 33207, "\u0120Liberia": 33208, "ebus": 33209, "Heavy": 33210, "\u0120lubric": 33211, "\u0120RW": 33212, "anguages": 33213, "\u0120narrowed": 33214, "computer": 33215, "\u0120Ember": 33216, "\u0120murdering": 33217, "\u0120downstream": 33218, "\u0120Tuls": 33219, "\u0120Tables": 33220, "Topic": 33221, "\u0120Accuracy": 33222, "=/": 33223, "lost": 33224, "\u0120Rei": 33225, "\u0120progresses": 33226, "bear": 33227, "\u0120establishments": 33228, "Justin": 33229, "\u0120Peach": 33230, "\u0120Gomez": 33231, "\u00e5\u00bf": 33232, "\u0120Triangle": 33233, "Ident": 33234, "\u0120Hive": 33235, "Resources": 33236, "\u0120mixes": 33237, "\u0120Assuming": 33238, "Mu": 33239, "\u0120hypoc": 33240, "\u0120sane": 33241, "\u0120Wan": 33242, "idious": 33243, "Success": 33244, "\u0120io": 33245, "Angel": 33246, "\u0120dangerously": 33247, "\u0120Creature": 33248, "WORK": 33249, ":[": 33250, "\u0120Katrina": 33251, "Listener": 33252, "Miller": 33253, "\u0120Idlib": 33254, "hang": 33255, "\u0120circumvent": 33256, "href": 33257, "\u0120celestial": 33258, "\u0120Weeks": 33259, "\u0120Pug": 33260, "\u0120Dalton": 33261, "\u0120subpoena": 33262, "uku": 33263, "\u0120persisted": 33264, "pei": 33265, "olding": 33266, "\u0120Documents": 33267, "\u0120Hast": 33268, "\u0120CENT": 33269, "\u0120primer": 33270, "\u0120synonymous": 33271, "\u0120nib": 33272, "ombs": 33273, "\u0120notation": 33274, "\u0120Dish": 33275, "\u0120Atmosp": 33276, "\u0120forbid": 33277, "\u0120ANG": 33278, "pattern": 33279, "los": 33280, "\u0120projectiles": 33281, "brown": 33282, ".\",": 33283, "\u0120Venom": 33284, "\u0120fiercely": 33285, "ublished": 33286, "\u0120Uran": 33287, "\u0120Nicarag": 33288, "410": 33289, "\u0120CAL": 33290, "OTOS": 33291, "\u0120Miracle": 33292, "\u0120Enchant": 33293, "\u0120guarding": 33294, "append": 33295, "Attach": 33296, "\u0120leveled": 33297, "\u0120condoms": 33298, "ihilation": 33299, "649": 33300, "\u0120nightmares": 33301, "\u0120THEY": 33302, "\u0120START": 33303, "\u0120Kinn": 33304, "\u0120roommate": 33305, "\u0120hygiene": 33306, "opping": 33307, "Job": 33308, "\u0120lvl": 33309, "\u0120VER": 33310, "\u0120Keeping": 33311, "abetic": 33312, "\u0120formatting": 33313, "erala": 33314, "\u0120revisions": 33315, "\u0120resurg": 33316, "Tel": 33317, "\u0120Goodman": 33318, "353": 33319, "pod": 33320, "\u0120indisp": 33321, "\u0120Translation": 33322, "\u0120gown": 33323, "\u0120Mund": 33324, "\u0120cis": 33325, "\u0120bystand": 33326, "collect": 33327, "\u0120Punjab": 33328, "actively": 33329, "\u0120Gamb": 33330, "tell": 33331, "\u0120importing": 33332, "gencies": 33333, "\u0120locom": 33334, "\u0120Brill": 33335, "Holy": 33336, "\u0120Berger": 33337, "\u0120showdown": 33338, "\u0120responders": 33339, "ILY": 33340, "\u0120takedown": 33341, "leted": 33342, "\u0120mattered": 33343, "\u0120predictive": 33344, "\u0120overlay": 33345, "GPU": 33346, "\u0120Vick": 33347, "\u0120conveyed": 33348, "Tab": 33349, "peer": 33350, "Scan": 33351, "\u0120defensively": 33352, "vae": 33353, "\u0120approving": 33354, "\u0120tiers": 33355, "\u0120Via": 33356, "querade": 33357, "\u0120Saudis": 33358, "\u0120demolished": 33359, "\u0120Prophe": 33360, "\u0120mono": 33361, "\u0120hospitality": 33362, "HAM": 33363, "\u0120Ariel": 33364, "MOD": 33365, "\u0120Torah": 33366, "\u0120blah": 33367, "\u0120Belarus": 33368, "erential": 33369, "\u0120Tuc": 33370, "\u0120banker": 33371, "397": 33372, "\u0120mosquit": 33373, "\u0120Scientist": 33374, "\u0120Musical": 33375, "\u0120hust": 33376, "Shift": 33377, "\u0120torment": 33378, "\u0120standoff": 33379, "Educ": 33380, "\u0120Fog": 33381, "\u0120amplifier": 33382, "Shape": 33383, "Instance": 33384, "\u0120Critics": 33385, "\u0120daemon": 33386, "Houston": 33387, "\u0120mattress": 33388, "\u0120IDF": 33389, "\u0120obscene": 33390, "\u0120Amer": 33391, "hetti": 33392, "\u0120compiling": 33393, "352": 33394, "verett": 33395, "\u0120Reduction": 33396, "istration": 33397, "\u0120Blessed": 33398, "\u0120Bachelor": 33399, "316": 33400, "\u0120prank": 33401, "\u0120Vulcan": 33402, "dding": 33403, "\u0120mourning": 33404, "\u0120Quint": 33405, "\u0120Blaster": 33406, "testing": 33407, "\u0120sediment": 33408, ">>>": 33409, "\u0120Eternity": 33410, "\u0120WHERE": 33411, "\u0120Maze": 33412, "\u0120reacting": 33413, "\u0120Alv": 33414, "omsday": 33415, "\u0120CRA": 33416, "\u0120translator": 33417, "\u0120bogus": 33418, "atu": 33419, "Website": 33420, "olls": 33421, "\u0120baptism": 33422, "\u0120sibling": 33423, "\u0120Autumn": 33424, "vez": 33425, "\u00e3\u0123\u00ae\u00e9": 33426, "guards": 33427, "Georg": 33428, "assadors": 33429, "\u0120Freud": 33430, "\u0120continents": 33431, "\u0120Registry": 33432, "Bernie": 33433, "\u0138\u013c\u00e5\u00a3\u00ab": 33434, "\u0120tolerant": 33435, "\u0120UW": 33436, "\u0120horribly": 33437, "995": 33438, "\u0120MIDI": 33439, "\u0120impatient": 33440, "ocado": 33441, "eri": 33442, "\u0120Worst": 33443, "\u0120Norris": 33444, "\u0120Talking": 33445, "\u0120defends": 33446, "ensable": 33447, "\u01202021": 33448, "\u0120anatomy": 33449, "Lew": 33450, "\u0120drawer": 33451, "\u0120Canberra": 33452, "\u0120patriotic": 33453, "\u00e9\u00be\u012f\u00e5\u0138\u013c\u00e5\u00a3\u00ab": 33454, "\u0120Avg": 33455, "ARM": 33456, "\u0120undisclosed": 33457, "\u0120farewell": 33458, "459": 33459, "bable": 33460, "\u0120Allison": 33461, "OLOG": 33462, "\u0120conco": 33463, "tight": 33464, "\u0120ACPI": 33465, "\u0120Mines": 33466, "lich": 33467, "\u0120\u00e2\u0136\u013e": 33468, "represented": 33469, "200000": 33470, "\u0120enthusiast": 33471, "OTS": 33472, "bil": 33473, "\u0120Ingredients": 33474, "\u0120inventor": 33475, "\u0120MySQL": 33476, "\u00c2\u0142\u00c2\u0142\u00c2\u0142": 33477, "\u0120ABOUT": 33478, "within": 33479, "\u0120mk": 33480, "Bul": 33481, "\u0120Fake": 33482, "\u0120draconian": 33483, "Wa": 33484, "helm": 33485, "\u0120Terran": 33486, "erville": 33487, "\u0120commonplace": 33488, "SIZE": 33489, "\u0120\"<": 33490, "replace": 33491, "ographs": 33492, "\u0120SELECT": 33493, "incible": 33494, "\u0120Mostly": 33495, "\u0120Sheffield": 33496, "\u0120IDE": 33497, "uggle": 33498, "\u0120citations": 33499, "hurst": 33500, "\u0120Unix": 33501, "\u0120unleash": 33502, "\u0120Piper": 33503, "\u0120Nano": 33504, "\u0120succumb": 33505, "\u0120reluctance": 33506, "\u01202500": 33507, "\u0120Merchant": 33508, "\u0120wiret": 33509, "\u0120combos": 33510, "\u0120Birthday": 33511, "\u0120charcoal": 33512, "\u0120UPS": 33513, "\u0120Fairfax": 33514, "\u0120driveway": 33515, "\u0120Tek": 33516, "\u0120Pitch": 33517, "overe": 33518, "\u0120technicians": 33519, "\u0120Actual": 33520, "flation": 33521, "\u0120Fiscal": 33522, "\u0120Empty": 33523, "anamo": 33524, "\u0120magnesium": 33525, "\u0120slut": 33526, "\u0120growers": 33527, "Investigators": 33528, "():": 33529, "\u0120Satellite": 33530, "\u0120Keynes": 33531, "missive": 33532, "lane": 33533, "\u0120borough": 33534, "344": 33535, "\u0120TEAM": 33536, "\u0120Bethesda": 33537, "CV": 33538, "hower": 33539, "\u0120RAD": 33540, "\u0120chant": 33541, "\u0120Riy": 33542, "\u0120compositions": 33543, "\u0120mildly": 33544, "\u0120meddling": 33545, "\u0120agility": 33546, "aneers": 33547, "501": 33548, "\u0120synth": 33549, "linger": 33550, "291": 33551, "\u0120exclaimed": 33552, "Party": 33553, "\u0120contamin": 33554, "\u0120Manor": 33555, "\u0120Respond": 33556, "\u0120praising": 33557, "\u0120manners": 33558, "fleet": 33559, "Summer": 33560, "\u0120Lynd": 33561, "\u0120Definitely": 33562, "grim": 33563, "\u0120bowling": 33564, "stri": 33565, "\u00e7\u013d": 33566, "ynt": 33567, "\u0120mandates": 33568, "DIV": 33569, "\u0120reconcile": 33570, "views": 33571, "\u0120Damon": 33572, "vette": 33573, "Flo": 33574, "\u0120Greatest": 33575, "ilon": 33576, "icia": 33577, "\u0120portrayal": 33578, "\u0120cushion": 33579, "504": 33580, "1979": 33581, "ossal": 33582, "Applic": 33583, "scription": 33584, "\u0120mitigation": 33585, "ATS": 33586, "pac": 33587, "\u0120erased": 33588, "\u0120deficiencies": 33589, "\u0120Hollande": 33590, "\u0120Xu": 33591, "\u0120bred": 33592, "\u0120pregnancies": 33593, "femin": 33594, "\u0120emph": 33595, "\u0120planners": 33596, "\u0120outper": 33597, "uttering": 33598, "\u0120perpetrator": 33599, "\u0120motto": 33600, "\u0120Ellison": 33601, "\u0120NEVER": 33602, "\u0120admittedly": 33603, "ARI": 33604, "\u0120Azerbaijan": 33605, "\u0120millisec": 33606, "\u0120combustion": 33607, "\u0120Bottle": 33608, "\u0120Lund": 33609, "\u0120Ps": 33610, "\u0120Dress": 33611, "\u0120fabricated": 33612, "\u0120battered": 33613, "\u0120sidel": 33614, "\u0120Notting": 33615, "Foreign": 33616, "\u0120Jerome": 33617, "020": 33618, "\u0120Arbit": 33619, "\u0120knots": 33620, "\u0120RIGHT": 33621, "Moving": 33622, "\u00e3\u0123\u013b": 33623, "\u0120surgeries": 33624, "\u0120courthouse": 33625, "\u0120mastered": 33626, "\u0120hovering": 33627, "\u0120Bran": 33628, "\u0120Alison": 33629, "\u0120safest": 33630, "military": 33631, "\u0120bullied": 33632, "\u0120barrage": 33633, "Reader": 33634, "ESE": 33635, "\u0120Geographic": 33636, "Tools": 33637, "314": 33638, "\u0120Geek": 33639, "roth": 33640, "glers": 33641, "\u0120FIN": 33642, "\u00cf\u0123": 33643, "\u0120Aston": 33644, "altern": 33645, "488": 33646, "\u0120veterin": 33647, "Gamer": 33648, "\u0120intel": 33649, "renches": 33650, "Shield": 33651, "\u0120amnesty": 33652, "\u0120Bhar": 33653, "\u0120piled": 33654, "\u0120honorable": 33655, "\u0120Institutes": 33656, "\u0120soaked": 33657, "\u0120coma": 33658, "\u0120EFF": 33659, "341": 33660, "bytes": 33661, "\u0120Gmail": 33662, "lein": 33663, "\u0120Canadiens": 33664, "material": 33665, "Il": 33666, "\u0120instructors": 33667, "\u0120KY": 33668, "\u0120conceive": 33669, "ubb": 33670, "\u0120Possible": 33671, "\u0120easing": 33672, "\u0120Christina": 33673, "\u0120caric": 33674, "\u0120HDR": 33675, "ROM": 33676, "\u0120shovel": 33677, "delete": 33678, "\u0120puff": 33679, "\u0120Changing": 33680, "\u0120seamlessly": 33681, "Attribute": 33682, "\u0120acquisitions": 33683, "akery": 33684, "\u0120EF": 33685, "\u0120autistic": 33686, "\u0120Takes": 33687, "\u0120Powder": 33688, "\u0120Stir": 33689, "510": 33690, "\u0120Bubble": 33691, "settings": 33692, "\u0120Fowler": 33693, "\u0120mustard": 33694, "\u0120moreover": 33695, "\u0120copyrighted": 33696, "\u0120LEDs": 33697, "1500": 33698, "\u00e6\u012b": 33699, "\u0120HIS": 33700, "enf": 33701, "\u0120custod": 33702, "\u0120Huck": 33703, "Gi": 33704, "\u0120img": 33705, "Answer": 33706, "Ct": 33707, "jay": 33708, "\u0120Infrastructure": 33709, "\u0120federally": 33710, "Loc": 33711, "\u0120microbes": 33712, "\u0120overrun": 33713, "dds": 33714, "otent": 33715, "adiator": 33716, ">>>>>>>>": 33717, "\u0120tornado": 33718, "\u0120adjud": 33719, "\u0120intrigued": 33720, "\u0120si": 33721, "\u0120Revelation": 33722, "progress": 33723, "\u0120burglary": 33724, "\u0120Saiyan": 33725, "\u0120Kathy": 33726, "\u0120serpent": 33727, "\u0120Andreas": 33728, "\u0120compel": 33729, "essler": 33730, "\u0120Plastic": 33731, "\u0120Advent": 33732, "\u0120Positive": 33733, "\u0120Qt": 33734, "\u0120Hindus": 33735, "registered": 33736, "ularity": 33737, "\u0120righteousness": 33738, "\u0120demonic": 33739, "uitive": 33740, "\u0120BDS": 33741, "\u0120Gregg": 33742, "cia": 33743, "\u0120Crusade": 33744, "\u0120Sinai": 33745, "WARE": 33746, "+(": 33747, "\u0120mell": 33748, "\u0120derail": 33749, "yards": 33750, "Ast": 33751, "\u0120noticeably": 33752, "\u0120Ober": 33753, "Ram": 33754, "\u0120unnoticed": 33755, "\u0120seq": 33756, "avage": 33757, "Ts": 33758, "\u0120640": 33759, "\u0120concede": 33760, "\u0120])": 33761, "Fill": 33762, "\u0120captivity": 33763, "\u0120Improvement": 33764, "\u0120Crusader": 33765, "araoh": 33766, "MAP": 33767, "\u00e6\u0139": 33768, "\u0120stride": 33769, "always": 33770, "Fly": 33771, "Nit": 33772, "\u0120algae": 33773, "\u0120Cooking": 33774, "\u0120Doors": 33775, "Malley": 33776, "\u0120policemen": 33777, "\u00e3\u0123\u012f": 33778, "\u0120astronaut": 33779, "accessible": 33780, "495": 33781, "\u0120RAW": 33782, "cliffe": 33783, "udicrous": 33784, "\u0120depended": 33785, "alach": 33786, "\u0120ventures": 33787, "rake": 33788, "\u0120tits": 33789, "\u0120Hou": 33790, "\u0120condom": 33791, "ormonal": 33792, "\u0120indent": 33793, "\u0120uploading": 33794, "Footnote": 33795, "Important": 33796, "\u0120271": 33797, "\u0120mindful": 33798, "\u0120contends": 33799, "Cra": 33800, "\u0120calibr": 33801, "\u0120OECD": 33802, "plugin": 33803, "Fat": 33804, "\u0120ISS": 33805, "\u0120Dynamics": 33806, "ansen": 33807, "686": 33808, "'),": 33809, "\u0120sprite": 33810, "\u0120handheld": 33811, "\u0120Hipp": 33812, "=~=~": 33813, "Trust": 33814, "\u0120semantics": 33815, "\u0120Bundes": 33816, "\u0120Reno": 33817, "\u0120Literature": 33818, "sense": 33819, "Gary": 33820, "\u0120Aeg": 33821, "\u0120Trin": 33822, "EEK": 33823, "\u0120cleric": 33824, "\u0120SSH": 33825, "\u0120christ": 33826, "\u0120invading": 33827, "ibu": 33828, "\u0120enum": 33829, "aura": 33830, "\u0120allege": 33831, "\u0120Incredible": 33832, "BBC": 33833, "\u0120thru": 33834, "\u0120sailed": 33835, "\u0120emulate": 33836, "\u0120insecurity": 33837, "\u0120crou": 33838, "\u0120accommodations": 33839, "\u0120incompetent": 33840, "\u0120slips": 33841, "\u0120Earthqu": 33842, "sama": 33843, "ILLE": 33844, "\u0120iPhones": 33845, "asaki": 33846, "\u0120bye": 33847, "\u0120ard": 33848, "\u0120extras": 33849, "\u0120slaughtered": 33850, "\u0120crowdfunding": 33851, "resso": 33852, "\u0120filib": 33853, "\u0120ERROR": 33854, "\u0120TLS": 33855, "egg": 33856, "\u0120Ital": 33857, "\u0120enlist": 33858, "\u0120Catalonia": 33859, "\u0120Scots": 33860, "\u0120sergeant": 33861, "\u0120dissolve": 33862, "NH": 33863, "\u0120standings": 33864, "rique": 33865, "IQ": 33866, "\u0120beneficiary": 33867, "\u0120aquarium": 33868, "YouTube": 33869, "\u0120PowerShell": 33870, "\u0120brightest": 33871, "\u0120Warrant": 33872, "Sold": 33873, "Writing": 33874, "\u0120beginnings": 33875, "\u0120Reserved": 33876, "\u0120Latinos": 33877, "heading": 33878, "\u0120440": 33879, "\u0120rooftop": 33880, "ATING": 33881, "\u0120390": 33882, "VPN": 33883, "Gs": 33884, "kernel": 33885, "turned": 33886, "\u0120preferable": 33887, "\u0120turnovers": 33888, "\u0120Hels": 33889, "Sa": 33890, "\u0120Shinji": 33891, "veh": 33892, "\u0120MODULE": 33893, "Viol": 33894, "\u0120exiting": 33895, "\u0120jab": 33896, "\u0120Vanilla": 33897, "\u0120acron": 33898, "\u0120Gap": 33899, "bern": 33900, "Ak": 33901, "\u0120McGu": 33902, "\u0120endlessly": 33903, "\u0120Farage": 33904, "\u0120Noel": 33905, "Va": 33906, "MK": 33907, "\u0120brute": 33908, "\u0120Kru": 33909, "\u0120ESV": 33910, "\u0120Olivia": 33911, "\u00e2\u0122\u0142": 33912, "\u0120Kaf": 33913, "\u0120trusting": 33914, "\u0120hots": 33915, "324": 33916, "\u0120malaria": 33917, "\u0120json": 33918, "\u0120pounding": 33919, "ortment": 33920, "Country": 33921, "\u0120postponed": 33922, "\u0120unequiv": 33923, "?),": 33924, "\u0120Rooney": 33925, "udding": 33926, "\u0120Leap": 33927, "urrence": 33928, "shapeshifter": 33929, "\u0120HAS": 33930, "osate": 33931, "\u0120cavern": 33932, "\u0120conservatism": 33933, "\u0120BAD": 33934, "\u0120mileage": 33935, "\u0120arresting": 33936, "Vaults": 33937, "\u0120mixer": 33938, "Democratic": 33939, "\u0120Benson": 33940, "\u0120authored": 33941, "8000": 33942, "\u0120proactive": 33943, "\u0120Spiritual": 33944, "tre": 33945, "\u0120incarcerated": 33946, "\u0120Sort": 33947, "\u0120peaked": 33948, "\u0120wielding": 33949, "reciation": 33950, "\u00d7\u013b\u00d7": 33951, "Patch": 33952, "\u0120Emmy": 33953, "\u0120exqu": 33954, "tto": 33955, "\u0120Ratio": 33956, "\u0120Picks": 33957, "\u0120Gry": 33958, "phant": 33959, "\u0120fret": 33960, "\u0120ethn": 33961, "\u0120archived": 33962, "%-": 33963, "cases": 33964, "\u0120Blaze": 33965, "\u0120imb": 33966, "cv": 33967, "yss": 33968, "imony": 33969, "\u0120countdown": 33970, "\u0120awakening": 33971, "\u0120Tunisia": 33972, "\u0120Refer": 33973, "\u0120MJ": 33974, "\u0120unnatural": 33975, "\u0120Carnegie": 33976, "izen": 33977, "\u0120Nuggets": 33978, "hess": 33979, "\u0120evils": 33980, "647": 33981, "\u0120introductory": 33982, "loving": 33983, "\u0120McMahon": 33984, "\u0120ambiguity": 33985, "Label": 33986, "\u0120Almighty": 33987, "\u0120coloring": 33988, "\u0120Claus": 33989, "setting": 33990, "NULL": 33991, "\u0120Favorite": 33992, "\u0120SIG": 33993, ">(": 33994, "\u0120Shiva": 33995, "\u0120Mayer": 33996, "\u0120stormed": 33997, "\u0120Coverage": 33998, "weapons": 33999, "igham": 34000, "\u0120unanswered": 34001, "\u0120leve": 34002, "\u0120coy": 34003, "cas": 34004, "bags": 34005, "asured": 34006, "Seattle": 34007, "\u0120Santorum": 34008, "serious": 34009, "\u0120courageous": 34010, "\u0120Soup": 34011, "\u0120confiscated": 34012, "\u0120///": 34013, "\u0120unconventional": 34014, "\u0120moms": 34015, "\u0120Rohingya": 34016, "\u0120Orchestra": 34017, "\u0120Potion": 34018, "\u0120discredit": 34019, "\u0120FIL": 34020, "fixed": 34021, "\u0120Deer": 34022, "doi": 34023, "\u0120Dimension": 34024, "\u0120bureaucrats": 34025, "eteen": 34026, "\u0120actionGroup": 34027, "ohm": 34028, "\u0120bumps": 34029, "\u0120Utility": 34030, "\u0120submarines": 34031, "renheit": 34032, "research": 34033, "\u0120Shapiro": 34034, "\u0120sketches": 34035, "\u0120deceptive": 34036, "\u0120Vil": 34037, "esame": 34038, "\u0120Essentially": 34039, "\u0120rampage": 34040, "isky": 34041, "\u0120muttered": 34042, "thritis": 34043, "\u0120236": 34044, "fet": 34045, "bars": 34046, "\u0120pupil": 34047, "\u0120Thou": 34048, "oS": 34049, "song": 34050, "\u0120fractured": 34051, "\u0120revert": 34052, "picture": 34053, "\u0120criterion": 34054, "usher": 34055, "\u0120repercussions": 34056, "\u0120Vintage": 34057, "\u0120Superintendent": 34058, "Officers": 34059, "\u0120flagged": 34060, "\u0120blames": 34061, "\u0120inverse": 34062, "ographers": 34063, "\u0120makeshift": 34064, "\u0120devoid": 34065, "\u0120fossils": 34066, "\u0120Aristotle": 34067, "\u0120Funds": 34068, "\u0120depleted": 34069, "\u0120Flu": 34070, "\u0120Yuan": 34071, "\u0120woes": 34072, "\u0120lipid": 34073, "\u0120situ": 34074, "requisites": 34075, "\u0120furnish": 34076, "\u0120Samar": 34077, "\u0120shameful": 34078, "\u0120adversely": 34079, "\u0120adept": 34080, "\u0120remorse": 34081, "\u0120murderous": 34082, "uckles": 34083, "\u0120ESL": 34084, "\u0120314": 34085, "sent": 34086, "\u0120redef": 34087, "\u0120Cache": 34088, "\u0120Purs": 34089, "igans": 34090, "\u0120460": 34091, "\u0120prescriptions": 34092, "\u0120fres": 34093, "Fuck": 34094, "ocrates": 34095, "Twenty": 34096, "\u0120Weird": 34097, "\u0120Toggle": 34098, "\u0120Called": 34099, "itizens": 34100, "\u0120poultry": 34101, "\u0120harvesting": 34102, "\u00e3\u0124\u00a6\u00e3\u0124\u00b9": 34103, "Bottom": 34104, "\u0120cautioned": 34105, "tn": 34106, "396": 34107, "\u0120Nikki": 34108, "\u0120evaluations": 34109, "\u0120harassing": 34110, "\u0120bindings": 34111, "\u0120Monetary": 34112, "\u0120hitters": 34113, "\u0120adversary": 34114, "unts": 34115, "\u0120setback": 34116, "\u0120encrypt": 34117, "\u0120Cait": 34118, "\u0120lows": 34119, "enges": 34120, "\u0120Norn": 34121, "\u0120bulbs": 34122, "\u0120bottled": 34123, "\u0120Voyager": 34124, "317": 34125, "\u0120spheres": 34126, "politics": 34127, "\u0120subtract": 34128, "\u0120sensations": 34129, "\u0120appalling": 34130, "\u0120316": 34131, "\u0120environmentally": 34132, "\u0120STEM": 34133, "\u0120publishes": 34134, "560": 34135, "\u0120diligence": 34136, "484": 34137, "\u0120advises": 34138, "\u0120petrol": 34139, "\u0120imagining": 34140, "\u0120patrols": 34141, "\u0120Integer": 34142, "\u0120Ashes": 34143, "actus": 34144, "\u0120Radiant": 34145, "\u0120LT": 34146, "itability": 34147, "htaking": 34148, "Setting": 34149, "\u0120nuanced": 34150, "\u0120Reef": 34151, "\u0120Developers": 34152, "Ni": 34153, "pieces": 34154, "990": 34155, "License": 34156, "\u0120lowers": 34157, "\u0120Ottoman": 34158, "327": 34159, "ooo": 34160, "\u0120quitting": 34161, "markets": 34162, "Behind": 34163, "\u0120basin": 34164, "\u0120docs": 34165, "anie": 34166, "flash": 34167, "ctl": 34168, "\u0120civilized": 34169, "\u0120Fukushima": 34170, "\"],\"": 34171, "\u0120KS": 34172, "\u0120Honestly": 34173, "arat": 34174, "\u0120constructs": 34175, "\u0120Lans": 34176, "\u0120Dire": 34177, "\u0120LIKE": 34178, "\u0120Trouble": 34179, "\u0120withholding": 34180, "\u0120Oblivion": 34181, "\u0120sanity": 34182, "anya": 34183, "Const": 34184, "\u0120grocer": 34185, "\u0120Celsius": 34186, "\u0120recounted": 34187, "\u0120Wife": 34188, "Border": 34189, "atered": 34190, "happy": 34191, "\u0120spoiler": 34192, "\u0120logically": 34193, "Hall": 34194, "\u0120succeeding": 34195, "\u0120polymorph": 34196, "\u0120axes": 34197, "\u0120Shotgun": 34198, "\u0120Slim": 34199, "\u0120Principles": 34200, "\u0120Leth": 34201, "arta": 34202, "\u0120scor": 34203, "Screenshot": 34204, "\u0120relaxation": 34205, "#$#$": 34206, "\u0120deterrent": 34207, "iddy": 34208, "\u0120powerless": 34209, "\u0120lesbians": 34210, "\u0120chords": 34211, "\u0120Edited": 34212, "selected": 34213, "\u0120separatists": 34214, "0002": 34215, "\u0120airspace": 34216, "\u0120turnaround": 34217, "\u0120cunning": 34218, "PATH": 34219, "Poly": 34220, "\u0120bombed": 34221, "\u0120tion": 34222, "xs": 34223, "\u0120withhold": 34224, "\u0120waged": 34225, "\u0120Liberties": 34226, "Flag": 34227, "\u0120comforting": 34228, "454": 34229, "\u0120Iris": 34230, "arers": 34231, "\u0120rag": 34232, "\u0120relocated": 34233, "\u0120Guarant": 34234, "\u0120strategically": 34235, "\u0120gamma": 34236, "uberty": 34237, "\u0120Lockheed": 34238, "gres": 34239, "\u0120grilled": 34240, "\u0120Lowe": 34241, "stats": 34242, "\u0120Rocks": 34243, "\u0120sensing": 34244, "\u0120renting": 34245, "\u0120Geological": 34246, "\u00d8\u00a7\u00d8": 34247, "otrop": 34248, "\u0120sew": 34249, "\u0120improperly": 34250, "486": 34251, "\u0120\u00e2\u0138\u0142": 34252, "\u0120starving": 34253, "\u0120Bj": 34254, "Discussion": 34255, "328": 34256, "\u0120Combo": 34257, "\u0120Fixes": 34258, "NAT": 34259, "\u0120striving": 34260, "thora": 34261, "\u0120harvested": 34262, "\u0120Ping": 34263, "\u0120playful": 34264, "\u0120avenues": 34265, "\u0120occupational": 34266, "\u0120wakes": 34267, "\u0120Courier": 34268, "\u0120drummer": 34269, "\u0120Browser": 34270, "\u0120Houth": 34271, "itu": 34272, "\u0120apparel": 34273, "paste": 34274, "\u0120hunted": 34275, "\u0120Secondly": 34276, "lain": 34277, "XY": 34278, "\u0120PIN": 34279, "icons": 34280, "\u0120cocktails": 34281, "\u0120sizable": 34282, "\u0120hurdles": 34283, "estinal": 34284, "\u0120Recreation": 34285, "\u0120eco": 34286, "648": 34287, "\u0120Died": 34288, "mint": 34289, "\u0120fingerprints": 34290, "\u0120dispose": 34291, "\u0120Bosnia": 34292, "tsy": 34293, "2200": 34294, "\u0120inspected": 34295, "\u0120Fou": 34296, "\u0120fuss": 34297, "\u0120ambush": 34298, "\u0120Rak": 34299, "\u0120manifested": 34300, "Prosecut": 34301, "\u0120suffice": 34302, "rences": 34303, "\u0120compensated": 34304, "\u0120Cyrus": 34305, "\u0120genus": 34306, "\u0120Wolverine": 34307, "\u0120Trends": 34308, "\u0120hikes": 34309, "\u0120Seen": 34310, "\u0120enrol": 34311, "Cold": 34312, "\u0120politely": 34313, "\u0120Slav": 34314, "\u0120Rupert": 34315, "\u0120eyewitness": 34316, "\u0120Alto": 34317, "\u0120uncomp": 34318, "\u0120posterior": 34319, "Must": 34320, "\u0120Herz": 34321, "\u0120progressively": 34322, "\u0120234": 34323, "\u0120indifference": 34324, "\u0120Cunningham": 34325, "\u0120academia": 34326, "\u0120sewer": 34327, "\u0120astounding": 34328, "\u0120AES": 34329, "rather": 34330, "\u0120eldest": 34331, "\u0120climbs": 34332, "\u0120Adds": 34333, "\u0120outcry": 34334, "\u0120contag": 34335, "\u0120Houses": 34336, "\u0120pept": 34337, "\u0120Melania": 34338, "interested": 34339, "\u0120UCH": 34340, "\u0120Roots": 34341, "\u0120Hubbard": 34342, "\u0120TBD": 34343, "\u0120Romanian": 34344, "filename": 34345, "Stone": 34346, "\u0120Impl": 34347, "\u0120chromosome": 34348, "Cle": 34349, "dx": 34350, "\u0120scrambled": 34351, "\u0120Pt": 34352, "\u0120242": 34353, "OPLE": 34354, "\u0120tremendously": 34355, "Street": 34356, "\u0120craving": 34357, "\u0120bundled": 34358, "\u0120RG": 34359, "pipe": 34360, "\u0120injuring": 34361, "\u0120arcane": 34362, "Particip": 34363, "\u0120Heroic": 34364, "sty": 34365, "\u0120topping": 34366, "\u0120Tempest": 34367, "rentices": 34368, "bh": 34369, "\u0120paranoia": 34370, "\u0120Unicode": 34371, "\u0120egregious": 34372, "\u0120\\'": 34373, "\u0120Oswald": 34374, "\u0120gravel": 34375, "\u0120Simpsons": 34376, "\u0120bland": 34377, "\u0120Guantanamo": 34378, "Writer": 34379, "liners": 34380, "\u0120Dice": 34381, "JC": 34382, "\u0120parity": 34383, "\u0120sided": 34384, "\u0120237": 34385, "\u0120Pyrrha": 34386, "atters": 34387, "dk": 34388, "Fine": 34389, "compan": 34390, "\u0120formulated": 34391, "\u0120Idol": 34392, "ilers": 34393, "hemoth": 34394, "\u0120Fav": 34395, "\u0120intrusion": 34396, "\u0120carrots": 34397, "\u0120Layer": 34398, "\u0120Hacker": 34399, "\u0120----------------": 34400, "\u0120moderation": 34401, "\u00e9\u0123": 34402, "ococ": 34403, "\u0120characterize": 34404, "\u0120Teresa": 34405, "\u0120socioeconomic": 34406, "\u0120perk": 34407, "\u0120Participation": 34408, "training": 34409, "\u0120Paulo": 34410, "phys": 34411, "\u0120trustworthy": 34412, "\u0120embodied": 34413, "\u0120Merch": 34414, "currency": 34415, "\u0120Priority": 34416, "\u0120teasing": 34417, "\u0120absorbing": 34418, "\u0120unfinished": 34419, "\u0120Comparison": 34420, "\u0120disple": 34421, "writers": 34422, "\u0120professions": 34423, "\u0120Penguin": 34424, "\u0120angrily": 34425, "\u0120LINK": 34426, "688": 34427, "\u0120Correspond": 34428, "\u0120prevailed": 34429, "\u0120cartel": 34430, "lp": 34431, "asms": 34432, "\u0120Redemption": 34433, "\u0120Islamists": 34434, "effects": 34435, "dose": 34436, "\u0120Latter": 34437, "\u0120Halifax": 34438, "\u0120vas": 34439, "\u0120Topics": 34440, "\u0120Named": 34441, "advertising": 34442, "zza": 34443, "ICES": 34444, "\u0120retarded": 34445, "achable": 34446, "\u0120Puppet": 34447, "\u0120ItemLevel": 34448, "\u0120retract": 34449, "\u0120identifiable": 34450, "Aaron": 34451, "\u0120Buster": 34452, "sol": 34453, "helle": 34454, "assemb": 34455, "Hope": 34456, "ranged": 34457, "Ba": 34458, "\u0120Purch": 34459, "\u00e9\u0122": 34460, "\u0120Siri": 34461, "\u0120arrivals": 34462, "\u01201912": 34463, "\u0120shortened": 34464, "\u0120312": 34465, "\u0120discrepancy": 34466, "\u0120Temperature": 34467, "\u0120Walton": 34468, "\u0120kinderg": 34469, "polit": 34470, "\u0120remix": 34471, "\u0120connectors": 34472, "\u00e3\u0125\u013a\u00e3\u0125\u00a9": 34473, "\u0120Kazakhstan": 34474, "dominated": 34475, "\u0120sugars": 34476, "imble": 34477, "\u0120Panic": 34478, "\u0120Demand": 34479, "\u0120Colony": 34480, "onen": 34481, "\u0120MER": 34482, "775": 34483, "uria": 34484, "azaar": 34485, "\u0120Degree": 34486, "Pri": 34487, "\u0120sunshine": 34488, "\u0120251": 34489, "\u0120psychedelic": 34490, "\u0120digitally": 34491, "\u0120Braun": 34492, "\u0120shimmer": 34493, "\u0120shave": 34494, "\u0120Telesc": 34495, "\u0120Astral": 34496, "\u0120Venezuelan": 34497, "\u0120OG": 34498, "\u0120crawling": 34499, "Integ": 34500, "\u0120Feather": 34501, "\u0120unfolding": 34502, "\u0120appropriation": 34503, "\u0120\u00e8\u00a3\u0131\u00e8": 34504, "\u0120Mobility": 34505, "\u0120Ney": 34506, "-.": 34507, "bilt": 34508, "LIN": 34509, "\u0120Tube": 34510, "\u0120Conversely": 34511, "\u0120keyboards": 34512, "\u0120Cao": 34513, "\u0120overth": 34514, "\u0120laure": 34515, ">>\\": 34516, "\u0120Viper": 34517, "acha": 34518, "Offset": 34519, "\u0120Raleigh": 34520, "\u0120Jae": 34521, "Jordan": 34522, "jp": 34523, "\u0120totalitarian": 34524, "Connector": 34525, "\u0120observes": 34526, "\u0120Spartan": 34527, "\u0120Immediately": 34528, "\u0120Scal": 34529, "Cool": 34530, "\u0120taps": 34531, "\u0120roar": 34532, "Past": 34533, "\u0120chars": 34534, "\u0120Bender": 34535, "\u0120Sheldon": 34536, "\u0120painter": 34537, "\u0120beacon": 34538, "\u0120Creatures": 34539, "\u0120downturn": 34540, "\u0120hinder": 34541, "\u0120Andromeda": 34542, "\u00c3\u013d": 34543, "ccoli": 34544, "\u0120Fitness": 34545, "etrical": 34546, "\u0120utilizes": 34547, "\u0120senate": 34548, "\u0120ensemble": 34549, "\u0120cheers": 34550, "TW": 34551, "\u0120affluent": 34552, "kil": 34553, "rylic": 34554, "ordering": 34555, "Computer": 34556, "\u0120gruesome": 34557, "ostics": 34558, "\u0120Ubisoft": 34559, "\u0120Kelley": 34560, "\u0120wrench": 34561, "\u0120bourgeoisie": 34562, "IBLE": 34563, "\u0120Preston": 34564, "worn": 34565, "arist": 34566, "reating": 34567, "\u0120stained": 34568, "arine": 34569, "\u0120slime": 34570, "ENN": 34571, "\u0120chests": 34572, "\u0120groundwater": 34573, "annot": 34574, "\u0120Tray": 34575, "\u0120Locke": 34576, "\u0120CTR": 34577, "\u0120dudes": 34578, "\u0120External": 34579, "\u0120Decoder": 34580, "\u0120paramed": 34581, "\u0120Medline": 34582, "809": 34583, "\u0120Dinner": 34584, "rupal": 34585, "gz": 34586, "\u0120Gum": 34587, "\u0120Demo": 34588, "jee": 34589, "\u0120dh": 34590, "berman": 34591, "archs": 34592, "\u0120enqu": 34593, "\u0120Epstein": 34594, "\u0120devastation": 34595, "\u0120friendships": 34596, "\u0120Ard": 34597, "\u0120231": 34598, "\u0120Rubin": 34599, "\u0120Distance": 34600, "\u0120spurred": 34601, "\u0120dossier": 34602, "\u0120overlooking": 34603, "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\": 34604, "Forest": 34605, "\u0120Comes": 34606, "\\\",": 34607, "\u0120Iranians": 34608, "\u0120fixtures": 34609, "Laughs": 34610, "\u0120curry": 34611, "\u0120Kingston": 34612, "\u0120squash": 34613, "\u0120catalogue": 34614, "\u0120abnormalities": 34615, "\u0120digestive": 34616, ".........": 34617, "\u0120subordinate": 34618, "ogly": 34619, "\u0120249": 34620, "Middle": 34621, "\u0120massac": 34622, "\u0120burgers": 34623, "\u0120downstairs": 34624, "\u01201931": 34625, "394": 34626, "\u0120VG": 34627, "\u0120lasers": 34628, "\u0120Sikh": 34629, "\u0120Alexa": 34630, "derived": 34631, "\u0120cyclist": 34632, "\u00e3\u0123\u00ae\u00e9\u0143\u0136": 34633, "oneliness": 34634, "!!!!!!!!": 34635, "\u0120buffs": 34636, "legate": 34637, "\u0120raping": 34638, "\u0120recommending": 34639, "rored": 34640, "\u0120multicultural": 34641, "unique": 34642, "\u0120businessmen": 34643, "\u0120uneasy": 34644, "\u0120MAP": 34645, "\u0120dispersed": 34646, "cipline": 34647, "Jess": 34648, "\u0120Kerala": 34649, "\u00e5\u00a7": 34650, "\u0120abstraction": 34651, "Surv": 34652, "Uh": 34653, "\u0120printers": 34654, "ija": 34655, "owder": 34656, "\u0120analogous": 34657, "\u0120ASP": 34658, "afer": 34659, "\u0120unfolded": 34660, "\u0120leveling": 34661, "\u0120breached": 34662, "\u0120Hearing": 34663, "\u0120nat": 34664, "\u0120translating": 34665, "critical": 34666, "\u0120antagonist": 34667, "\u0120Yesterday": 34668, "\u0120fuzzy": 34669, "wash": 34670, "mere": 34671, "\u0120bewild": 34672, "\u0120Mae": 34673, "Virgin": 34674, "phrase": 34675, "\u0120signaled": 34676, "\u0120HIGH": 34677, "\u0120protester": 34678, "\u0120garner": 34679, "unknown": 34680, "\u0120kay": 34681, "\u0120abducted": 34682, "\u0120stalking": 34683, "amn": 34684, "\u0120deserving": 34685, "\u0120Riv": 34686, "\u0120Jorge": 34687, "\u0120scratching": 34688, "\u0120Saving": 34689, "iping": 34690, "\u0120tease": 34691, "\u0120missionary": 34692, "\u0120Morrow": 34693, "TIME": 34694, "Present": 34695, "\u0120chemotherapy": 34696, "terness": 34697, "\u0120Homes": 34698, "\u0120Purdue": 34699, "\u0120staunch": 34700, "\u0120Whitney": 34701, "\u0120THERE": 34702, "\u00ce\u00bc": 34703, "iatus": 34704, "\u0120Ernest": 34705, "\u0120Deploy": 34706, "\u0120coveted": 34707, "FML": 34708, "\u0120Dialogue": 34709, "\u0120exited": 34710, "fruit": 34711, "\u0120nerd": 34712, "\":\"\",\"": 34713, "\u0120vivo": 34714, "ruly": 34715, "460": 34716, "\u0120Amen": 34717, "rehensible": 34718, "\u0120\u00e2\u013a": 34719, "DIR": 34720, "\u0120adherence": 34721, "\u0120chew": 34722, "\u0120Coke": 34723, "\u0120Sergei": 34724, "digital": 34725, "\u0120Neck": 34726, "gently": 34727, "enthal": 34728, "/)": 34729, "\u0120weary": 34730, "\u0120guise": 34731, "\u0120Concord": 34732, "\u0120Onion": 34733, "atcher": 34734, "\u0120binge": 34735, "\u0120Directive": 34736, "\u0120manned": 34737, "ansk": 34738, "\u0120illusions": 34739, "\u0120billionaires": 34740, "383": 34741, "olyn": 34742, "odynamic": 34743, "\u0120Wheat": 34744, "\u0120Alic": 34745, "\u0120coloured": 34746, "\u0120NAFTA": 34747, "abo": 34748, "\u0120macros": 34749, "independent": 34750, "sweet": 34751, "\u0120spac": 34752, "\u0120Kabul": 34753, "\u0120\u00c4": 34754, "eme": 34755, "\u0120dictated": 34756, "\u0120shouts": 34757, "={": 34758, "\u0120ripping": 34759, "\u0120Shay": 34760, "\u0120Cricket": 34761, "directed": 34762, "\u0120analysed": 34763, "\u0120WARRANT": 34764, "agons": 34765, "\u0120Blazers": 34766, "\u0120cheered": 34767, "\u0120arithmetic": 34768, "\u0120Tanz": 34769, "373": 34770, "\u0120Flags": 34771, "\u0120295": 34772, "\u0120witches": 34773, "\u0120Included": 34774, "\u0120Gained": 34775, "\u0120Blades": 34776, "Gam": 34777, "\u0120Samantha": 34778, "\u0120Atlantis": 34779, "\u0120Pratt": 34780, "\u0120spoiled": 34781, "\u0120IB": 34782, "\u0120Ramirez": 34783, "Probably": 34784, "rero": 34785, "\u0120Ng": 34786, "\u0120Warlock": 34787, "tp": 34788, "\u0120overhe": 34789, "\u0120administrations": 34790, "\u0120tint": 34791, "\u0120regiment": 34792, "\u0120pistols": 34793, "\u0120blankets": 34794, "\u0120epist": 34795, "\u0120bowls": 34796, "\u0120hydraulic": 34797, "\u0120dean": 34798, "\u0120jung": 34799, "\u0120ascend": 34800, "705": 34801, "\u0120Santiago": 34802, "\u00c3\u00ae": 34803, "\u0120unavoid": 34804, "\u0120Shaman": 34805, "reb": 34806, "\u0120stemming": 34807, "998": 34808, "\u0120MG": 34809, "sticks": 34810, "esthesia": 34811, "ERO": 34812, "\u0120morbid": 34813, "\u0120Grill": 34814, "\u0120Poe": 34815, "anyl": 34816, "\u0120deleting": 34817, "\u0120Surveillance": 34818, "\u0120directives": 34819, "\u0120iterations": 34820, "\u0120Rox": 34821, "\u0120Milky": 34822, "Father": 34823, "\u0120patented": 34824, "447": 34825, "\u0120precursor": 34826, "\u0120maiden": 34827, "\u0120Phen": 34828, "\u0120Vegan": 34829, "\u0120Patent": 34830, "Kelly": 34831, "Redditor": 34832, "\u0120nods": 34833, "\u0120ventilation": 34834, "\u0120Schwarz": 34835, "\u0120wizards": 34836, "\u0120ominous": 34837, "\u0120Heads": 34838, "\u0120BG": 34839, "\u0120lumber": 34840, "\u0120Spiel": 34841, "\u0120isEnabled": 34842, "\u0120ancestral": 34843, "\u0120Ships": 34844, "\u0120wrestler": 34845, "phi": 34846, "\u0120yuan": 34847, "\u0120Rebellion": 34848, "\u0120iceberg": 34849, "\u0120magically": 34850, "\u0120diversion": 34851, "arro": 34852, "ythm": 34853, "\u0120Riders": 34854, "\u0120Robbie": 34855, "\u0120Kara": 34856, "\u0120Maintenance": 34857, "\u0120Herb": 34858, "\u0120harms": 34859, "packed": 34860, "\u0120Feinstein": 34861, "\u0120marrying": 34862, "\u0120blending": 34863, "\u0120Rates": 34864, "\u01201880": 34865, "\u0120wrink": 34866, "\u0120Unch": 34867, "\u0120Torch": 34868, "described": 34869, "\u0120humanoid": 34870, "ilitating": 34871, "\u0120Conv": 34872, "\u0120Feld": 34873, "IGHTS": 34874, "\u0120whistleblower": 34875, "ortmund": 34876, "etsy": 34877, "arrett": 34878, "\u0120Mono": 34879, "\u0120Ike": 34880, "\u0120CNBC": 34881, "\u0120WAY": 34882, "\u0120MDMA": 34883, "\u0120Individuals": 34884, "\u0120supplemental": 34885, "\u0120powerhouse": 34886, "\u0120Stru": 34887, "Focus": 34888, "aphael": 34889, "\u0120Colleg": 34890, "atti": 34891, "ZA": 34892, "\u0120perenn": 34893, "\u0120Signature": 34894, "\u0120Rodney": 34895, "\u0120cubes": 34896, "iddled": 34897, "\u0120Dante": 34898, "\u0120INV": 34899, "ilingual": 34900, "\u0120Cth": 34901, "\u0120sofa": 34902, "\u0120intimidate": 34903, "\u0120Roe": 34904, "\u0120Diplom": 34905, "\u0120Countries": 34906, "ayson": 34907, "\u0120extradition": 34908, "\u0120disabling": 34909, "\u0120Cardiff": 34910, "\u0120memorandum": 34911, "\u0120Trace": 34912, "\u0120???": 34913, "sector": 34914, "\u0120Rouhani": 34915, "\u0120Yates": 34916, "\u0120Freeze": 34917, "\u0120bladder": 34918, "Motor": 34919, "\u0120Promise": 34920, "antasy": 34921, "\u0120foreseeable": 34922, "\u0120Cologne": 34923, "container": 34924, "\u0120Trees": 34925, "\u0120Gors": 34926, "\u0120Sinclair": 34927, "\u0120barring": 34928, "keye": 34929, "\u0120slashed": 34930, "\u0120Statistical": 34931, "\u00e9\u0129": 34932, "\u0120\u00e2\u0138\u00ba": 34933, "Allows": 34934, "\u0120humility": 34935, "\u0120drilled": 34936, "\u0120Furn": 34937, "443": 34938, "\u0120sewage": 34939, "\u0120homepage": 34940, "\u0120courtyard": 34941, "\u0120vile": 34942, "\u0120subsidiaries": 34943, "ajo": 34944, "directory": 34945, "\u0120ammon": 34946, "Vers": 34947, "charges": 34948, "\u0120}}": 34949, "\u0120Chains": 34950, "\u0120246": 34951, "nob": 34952, "\u0120percept": 34953, "\u0120grit": 34954, "\u0120fishermen": 34955, "\u0120Iraqis": 34956, "\u0120DISTR": 34957, "\u0120FULL": 34958, "\u0120Evaluation": 34959, "graph": 34960, "atial": 34961, "\u0120cooperating": 34962, "\u0120melan": 34963, "\u0120enlightened": 34964, "\u0120ali": 34965, "tailed": 34966, "\u0120salute": 34967, "\u0120weakest": 34968, "\u0120Bulldogs": 34969, "UA": 34970, "\u0120Alloy": 34971, "\u0120semen": 34972, "ocene": 34973, "\u0120Williamson": 34974, "spr": 34975, ",\u00e2\u0122\u0136": 34976, "\u0120GF": 34977, "ittens": 34978, "Beat": 34979, "\u0120Junk": 34980, "iphate": 34981, "\u0120Farmers": 34982, "\u0120Bitcoins": 34983, "igers": 34984, "dh": 34985, "\u0120Loyal": 34986, "payer": 34987, "\u0120entertained": 34988, "\u0120penned": 34989, "\u0120coupon": 34990, "Queue": 34991, "\u0120weakening": 34992, "carry": 34993, "\u0120underestimate": 34994, "\u0120shootout": 34995, "\u0120charismatic": 34996, "\u0120Procedure": 34997, "\u0120prudent": 34998, "inances": 34999, "\u0120riches": 35000, "\u0120cortical": 35001, "\u0120strides": 35002, "\u0120drib": 35003, "\u0120Oilers": 35004, "540": 35005, "\u0120Perform": 35006, "\u0120Bangkok": 35007, "\u0120euth": 35008, "SER": 35009, "\u0120simplistic": 35010, "tops": 35011, "campaign": 35012, "Quality": 35013, "\u0120impoverished": 35014, "\u0120Eisenhower": 35015, "\u0120augment": 35016, "\u0120Harden": 35017, "\u0120intervened": 35018, "\u0120listens": 35019, "\u0120Kok": 35020, "\u0120sage": 35021, "\u0120rubbish": 35022, "\u0120Ded": 35023, "\u0120mull": 35024, "pelling": 35025, "\u0120videot": 35026, "Production": 35027, "DJ": 35028, "miah": 35029, "\u0120adaptations": 35030, "\u0120medically": 35031, "\u0120boarded": 35032, "\u0120arrogance": 35033, "\u0120scrapped": 35034, "\u0120oppress": 35035, "FORMATION": 35036, "\u0120junction": 35037, "415": 35038, "EEEE": 35039, "Skill": 35040, "\u0120subdu": 35041, "\u0120Suggest": 35042, "\u0120Pett": 35043, "\u0120lett": 35044, "\u0120Manip": 35045, "\u0120Caf": 35046, "\u0120Cooperation": 35047, "Ther": 35048, "\u0120regained": 35049, "\u00b6\u00e6": 35050, "reflect": 35051, "\u0120thugs": 35052, "\u0120Shelby": 35053, "\u0120dictates": 35054, "\u0120Weiner": 35055, "\u0120Hale": 35056, "\u0120battleground": 35057, "schild": 35058, "\u0120condol": 35059, "hunt": 35060, "ositories": 35061, "\u0120accuses": 35062, "Filename": 35063, "\u0120shri": 35064, "\u0120motivate": 35065, "\u0120reflections": 35066, "Null": 35067, "\u0120Lobby": 35068, "\u00a5\u00b5": 35069, "\u0120SATA": 35070, "\u0120Backup": 35071, "\u00d1\u0125": 35072, "nin": 35073, "\u0120Correction": 35074, "\u0120juicy": 35075, "utra": 35076, "\u0120Pric": 35077, "\u0120restraining": 35078, "\u0120Airbnb": 35079, "\u0120Arrest": 35080, "\u0120appropriations": 35081, "\u0120slopes": 35082, "\u0120manslaughter": 35083, "\u0120workings": 35084, "\u0120Huss": 35085, "\u0120Frey": 35086, "Leave": 35087, "\u0120Harmony": 35088, "\u0120Feder": 35089, "\u0120430": 35090, "\u0120trench": 35091, "\u0120gladly": 35092, "\u0120bullpen": 35093, "\u0120Gau": 35094, "bones": 35095, "\u0120groove": 35096, "\u0120pretext": 35097, "\u00e3\u0127\u012d": 35098, "\u0120transmitter": 35099, "\u0120Component": 35100, "\u0120underage": 35101, "\u0120Empires": 35102, "Tile": 35103, "\u0120oy": 35104, "\u0120Marvin": 35105, "\u0120CAS": 35106, "\u0120bloss": 35107, "\u0120replicated": 35108, "\u0120Mariners": 35109, "Marcus": 35110, "\u0120Blocks": 35111, "\u0120liberated": 35112, "\u0120butterfly": 35113, "Feel": 35114, "\u0120fermentation": 35115, "\u0120youtube": 35116, "\u0120offend": 35117, "\u0120Term": 35118, "resist": 35119, "\u0120cessation": 35120, "\u0120insurgency": 35121, "\u0120bir": 35122, "\u0120Raise": 35123, "595": 35124, "\u0120hypotheses": 35125, "502": 35126, "\u0120plaque": 35127, "ocrat": 35128, "\u0120jackets": 35129, "\u0120HuffPost": 35130, "among": 35131, "\u0120confer": 35132, "487": 35133, "\u0120Lilly": 35134, "\u0120adapting": 35135, "\u0120Fay": 35136, "\u0120shoved": 35137, "vec": 35138, "\u0120refine": 35139, "\u0120gon": 35140, "\u0120gunmen": 35141, "zai": 35142, "\u0120Shuttle": 35143, "\u0120Izan": 35144, "\u01201913": 35145, "\u0120plethora": 35146, "\u00c2\u00b7\u00c2\u00b7": 35147, "\u0120510": 35148, "\u0120puberty": 35149, "\u0120241": 35150, "\u0120Wealth": 35151, "\u0120Alma": 35152, "\u0120MEM": 35153, "\u0120Adults": 35154, "Cas": 35155, "prison": 35156, "Race": 35157, "\u0120waterproof": 35158, "\u0120athleticism": 35159, "\u0120capitalize": 35160, "\u0120Juice": 35161, "\u0120illuminated": 35162, "\u0120Pascal": 35163, "\u0120irritation": 35164, "\u0120Witnesses": 35165, "adle": 35166, "\u0120Astro": 35167, "\u0120fax": 35168, "\u0120Elvis": 35169, "Primary": 35170, "\u0120Lich": 35171, "\u0120Elves": 35172, "\u0120residing": 35173, "\u0120stumble": 35174, "319": 35175, "\u0120PKK": 35176, "\u0120adversaries": 35177, "DOS": 35178, "\u0120Ritual": 35179, "\u0120smear": 35180, "\u0120arson": 35181, "idental": 35182, "\u0120scant": 35183, "\u0120monarchy": 35184, "\u0120halftime": 35185, "\u0120residue": 35186, "\u0120indign": 35187, "\u0120Shaun": 35188, "\u0120Elm": 35189, "auri": 35190, "Aff": 35191, "WATCH": 35192, "\u0120Lyon": 35193, "helps": 35194, "361": 35195, "\u0120lobbyist": 35196, "\u0120diminishing": 35197, "\u0120outbreaks": 35198, "\u0120goats": 35199, "favorite": 35200, "\u0120Nah": 35201, "sonian": 35202, "\u0120Booster": 35203, "\u0120sandbox": 35204, "\u0120Fare": 35205, "\u0120Malta": 35206, "\u0120attRot": 35207, "\u0120MOR": 35208, "lde": 35209, "\u0120navigating": 35210, "Touch": 35211, "\u0120untrue": 35212, "\u0120Disaster": 35213, "\u0120ludicrous": 35214, "Password": 35215, "\u0120JFK": 35216, "blogspot": 35217, "416": 35218, "\u0120UNDER": 35219, "ernal": 35220, "\u0120delaying": 35221, "TOP": 35222, "\u0120implants": 35223, "\u0120AVG": 35224, "\u0120Huge": 35225, "attr": 35226, "\u0120journalistic": 35227, "\u0120Peyton": 35228, "\u0120IA": 35229, "Rap": 35230, "goal": 35231, "\u0120Programme": 35232, "\u0120smashing": 35233, "wives": 35234, "println": 35235, "\u0120Plague": 35236, "inus": 35237, "EEP": 35238, "\u0120cruiser": 35239, "\u0120Parish": 35240, "uminium": 35241, "\u0120occupants": 35242, "\u0120Jihad": 35243, "mop": 35244, "\u0120pint": 35245, "\u0120hect": 35246, "\u0120Mecca": 35247, "director": 35248, "\u0120Funding": 35249, "\u0120Mixed": 35250, "\u0120stag": 35251, "Tier": 35252, "\u0120gust": 35253, "\u0120brightly": 35254, "orsi": 35255, "\u0120uphill": 35256, "RD": 35257, "\u0120lesions": 35258, "\u0120Bundy": 35259, "livious": 35260, "\u0120biologist": 35261, "\u0120Faculty": 35262, "\u0120Authorization": 35263, "\u0120244": 35264, "Allow": 35265, "\u00ef\u00b8": 35266, "\u0120Giul": 35267, "\u0120pertinent": 35268, "otaur": 35269, "esse": 35270, "\u0120Roof": 35271, "\u0120unmanned": 35272, "351": 35273, "\u0120Shak": 35274, "\u0120Orient": 35275, "\u0120endanger": 35276, "Dir": 35277, "\u0120replen": 35278, "edient": 35279, "\u0120tailor": 35280, "\u0120gadgets": 35281, "\u0120audible": 35282, "\u00e2\u013a\u0128": 35283, "Nice": 35284, "\u0120bombard": 35285, "\u0120Rape": 35286, "\u0120defiance": 35287, "\u0120TWO": 35288, "\u0120Filipino": 35289, "\u0120unaffected": 35290, "ervatives": 35291, "\u0120soared": 35292, "\u0120Bolton": 35293, "\u0120compromising": 35294, "\u0120Brewers": 35295, "RAL": 35296, "\u0120AHL": 35297, "icycle": 35298, "\u0120vampires": 35299, "\u0120dipped": 35300, "oyer": 35301, "\u0120XIII": 35302, "\u0120sideways": 35303, "\u0120Waste": 35304, "\u0120Diss": 35305, "\u0120\u00e2\u0136\u013e\u00e2\u0136\u0122\u00e2\u0136\u0122": 35306, "$.": 35307, "\u0120habitats": 35308, "\u0120Beef": 35309, "truth": 35310, "trained": 35311, "split": 35312, "Rus": 35313, "Andy": 35314, "\u0120Bram": 35315, "REP": 35316, "pid": 35317, "\u00e8\u00a3\u0127": 35318, "\u0120Mutant": 35319, "Anim": 35320, "\u0120Marina": 35321, "\u0120futile": 35322, "highest": 35323, "frequency": 35324, "\u0120epilepsy": 35325, "\u0120coping": 35326, "\u0120concise": 35327, "\u0120tracing": 35328, "\u0120SUN": 35329, "panel": 35330, "\u0120Sophie": 35331, "\u0120Crowley": 35332, "\u0120Adolf": 35333, "\u0120Shooter": 35334, "\u0120shaky": 35335, "\u0120IG": 35336, "\u0120Lies": 35337, "\u0120Barber": 35338, "pkg": 35339, "\u0120uptake": 35340, "\u0120predatory": 35341, "ULTS": 35342, "/**": 35343, "\u0120intoxicated": 35344, "\u0120Westbrook": 35345, "odder": 35346, "hement": 35347, "\u0120baseman": 35348, "APD": 35349, "storage": 35350, "\u0120Fifty": 35351, "editor": 35352, "GEN": 35353, "UTION": 35354, "irting": 35355, "\u0120sewing": 35356, "rift": 35357, "\u0120agony": 35358, "\u0120Sands": 35359, "\u0120254": 35360, "Cash": 35361, "\u0120lodge": 35362, "\u0120punt": 35363, "Natural": 35364, "\u0120Ideas": 35365, "\u0120erroneous": 35366, "\u0120Sensor": 35367, "\u0120Hannity": 35368, "\u01201921": 35369, "\u0120mould": 35370, "\u0120Gon": 35371, "kaya": 35372, "\u0120anonymously": 35373, "\u0120KEY": 35374, "\u0120simulator": 35375, "Winter": 35376, "\u0120streamed": 35377, "507": 35378, "?\",": 35379, "\u0120teased": 35380, "\u0120coefficient": 35381, "\u0120wartime": 35382, "\u0120THR": 35383, "''.": 35384, "\u0120Banking": 35385, "mpire": 35386, "\u0120fandom": 35387, "\u0120lia": 35388, "Ga": 35389, "\u0120downhill": 35390, "\u0120interpreting": 35391, "Individual": 35392, "Norm": 35393, "\u0120jealousy": 35394, "bitcoin": 35395, "\u0120pleasures": 35396, "\u0120Toys": 35397, "\u0120Chevrolet": 35398, "\u0120Advisor": 35399, "IZE": 35400, "\u0120receptions": 35401, "706": 35402, "Cro": 35403, "\u0120262": 35404, "\u0120citrus": 35405, "iru": 35406, "Reviewer": 35407, "jected": 35408, "UES": 35409, "anz": 35410, "1981": 35411, "\u0120Worker": 35412, "\u0120complied": 35413, "orescent": 35414, "continental": 35415, "Ton": 35416, "\u0120Prism": 35417, "\u0120Sheep": 35418, "\u0120288": 35419, "nox": 35420, "\u0120Vog": 35421, "Ord": 35422, "\u0120realms": 35423, "tek": 35424, "\u0120irrigation": 35425, "\u0120bicycles": 35426, "\u0120electronically": 35427, "poly": 35428, "tall": 35429, "());": 35430, "\u0120aesthetics": 35431, "\u0120Integrated": 35432, "Explore": 35433, "\u0120dunk": 35434, "476": 35435, "pain": 35436, "\u0120Jacques": 35437, "\u0120Dmit": 35438, "Frames": 35439, "\u0120reunited": 35440, "\u0120humid": 35441, "Dro": 35442, "Political": 35443, "\u0120youthful": 35444, "\u0120entails": 35445, "\u0120mosquito": 35446, "363": 35447, "species": 35448, "\u0120coordinating": 35449, "\u0120Mayhem": 35450, "\u0120Magnus": 35451, "Mount": 35452, "Improved": 35453, "\u0120STATE": 35454, "ATTLE": 35455, "\u0120flowed": 35456, "\u0120tackled": 35457, "\u0120fashioned": 35458, "\u0120reorgan": 35459, "ivari": 35460, "finger": 35461, "\u0120reluctantly": 35462, "etting": 35463, "\u0120Vand": 35464, "young": 35465, "\u0120Garland": 35466, "\u0120presumption": 35467, "\u0120amenities": 35468, "\u0120Pleasant": 35469, "onential": 35470, "\u0120Oxy": 35471, "\u0120morals": 35472, "\u0120Yah": 35473, "Ready": 35474, "Simon": 35475, "Enh": 35476, "Demon": 35477, "\u0120clich": 35478, "Monitor": 35479, "\u0120DU": 35480, "\u0120welcomes": 35481, "\u0120standout": 35482, "\u0120dreadful": 35483, "\u0120bananas": 35484, "\u0120balloons": 35485, "hooting": 35486, "basic": 35487, "\u0120suffix": 35488, "\u0120duly": 35489, "cano": 35490, "Chain": 35491, "atos": 35492, "\u0120geopolitical": 35493, "\u0120(&": 35494, "\u0120Gemini": 35495, "\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124\u00c3\u0125\u00c3\u0124": 35496, "\u0120acquitted": 35497, "Luck": 35498, "protect": 35499, "1024": 35500, "\u0120scarcity": 35501, "\u0120mindfulness": 35502, "ecided": 35503, "DN": 35504, "prime": 35505, "\u0120Presidents": 35506, "\u0120VIDEO": 35507, "\u0120(\u00e2\u012a\u0134": 35508, "addock": 35509, "NOR": 35510, "\u0120Pru": 35511, "pun": 35512, "\u0120LOL": 35513, "))))": 35514, "\u0120Liqu": 35515, "\u0120SAS": 35516, "\u0120styling": 35517, "\u0120punishments": 35518, "\u0120numb": 35519, "\u0120ascertain": 35520, "\u0120Rockies": 35521, "flu": 35522, "Thumbnail": 35523, "\u0120perpetrated": 35524, "\u0120Semi": 35525, "\u0120disarm": 35526, "\u0120Older": 35527, "\u0120Exception": 35528, "\u0120exponentially": 35529, "\u0120Communities": 35530, "\u0120abolish": 35531, "\u0120Partner": 35532, "ptoms": 35533, "\u0120777": 35534, "\u0120Foley": 35535, "\u0120Cases": 35536, "\u0120grease": 35537, "\u0120Rebirth": 35538, "Ground": 35539, "\u0120;)": 35540, "\u0120Doctrine": 35541, "ikini": 35542, "Ye": 35543, "\u0120Blossom": 35544, "\u0120persists": 35545, "bill": 35546, "\u0120infusion": 35547, "\u0120buddies": 35548, "911": 35549, "\u0120Patient": 35550, "\u0120demos": 35551, "\u0120acquaintance": 35552, "\u0120Paw": 35553, "atari": 35554, "\u0120xml": 35555, "\u0120fascination": 35556, "\u0120Serve": 35557, "\u00cf\u0124": 35558, "branded": 35559, "\u0120az": 35560, "Returns": 35561, "\u0120overshadow": 35562, "\u0120roam": 35563, "\u0120speedy": 35564, "numbered": 35565, "helial": 35566, "\u0120disciple": 35567, "\u0120assurances": 35568, "given": 35569, "pecting": 35570, "\u0120Natalie": 35571, "\u00e7\u0136\u00b0": 35572, "\u0120mosquitoes": 35573, "rotein": 35574, "\u0120numeric": 35575, "\u0120independents": 35576, "\u0120transitional": 35577, "\u0120reactionary": 35578, "\u0120Mechdragon": 35579, "doctor": 35580, "\u0120shortest": 35581, "\u0120sequential": 35582, "\u0120Bac": 35583, "\u0120Accounts": 35584, "\u00e3\u0123\u012e": 35585, "achy": 35586, "ractive": 35587, "\u0120Regiment": 35588, "\u0120breathtaking": 35589, "fficiency": 35590, "\u0120Bates": 35591, "\u0120311": 35592, "\u0120wardrobe": 35593, "fts": 35594, "\u0120Berk": 35595, "Simply": 35596, "\u0120Riverside": 35597, "ivering": 35598, "idential": 35599, "lucent": 35600, "\u0120enriched": 35601, "\u0120Conver": 35602, "\u0120Giving": 35603, "\u00e3\u0125\u013b": 35604, "\u0120legalize": 35605, "\u0120FTC": 35606, "\u0120freaking": 35607, "Mix": 35608, "\u0120terrestrial": 35609, "esian": 35610, "cients": 35611, "Wing": 35612, "LOAD": 35613, "\u0120ledge": 35614, "\u0120Violent": 35615, "\u0120Metall": 35616, "\u0120308": 35617, "\u0120southeastern": 35618, "hetto": 35619, "Meat": 35620, "\u0120slowdown": 35621, "\u0120retreated": 35622, "Jeremy": 35623, "endas": 35624, "*****": 35625, "eric": 35626, "\u0120reins": 35627, "oppable": 35628, "\u0120Humanity": 35629, "earances": 35630, "rigan": 35631, "Camera": 35632, "\u0120waivers": 35633, "soc": 35634, "\u0120alteration": 35635, "transform": 35636, "\u0120Cemetery": 35637, "506": 35638, "\u0120indefinite": 35639, "\u0120stimulating": 35640, "yg": 35641, "603": 35642, "\u0120Sop": 35643, "\u0120descriptive": 35644, "Phase": 35645, "\u0120Edmund": 35646, "\u0120pneumonia": 35647, "ventus": 35648, "Amb": 35649, "\u0120laboratories": 35650, "\u0120Exclusive": 35651, "ugar": 35652, "Were": 35653, "\u0120malfunction": 35654, "\u0120homosexuals": 35655, "\u0120-------": 35656, "uni": 35657, "\u0120turbines": 35658, "\u0120Equity": 35659, "Du": 35660, "\u0120minded": 35661, "\u0120RH": 35662, "\u0120Blackhawks": 35663, "\u0120feats": 35664, "\u01201700": 35665, "repl": 35666, "362": 35667, "laden": 35668, "\u0120indispensable": 35669, "lyss": 35670, "tti": 35671, "\u0120reel": 35672, "\u0120diverted": 35673, "\u0120likeness": 35674, "\u0120subscriptions": 35675, "\u0120fingert": 35676, "\u0120filthy": 35677, "destruct": 35678, "draft": 35679, "\u0120Bernardino": 35680, "launch": 35681, "\u0120perplex": 35682, "\u0120SUM": 35683, "carb": 35684, "\u0120sweater": 35685, "\u0120Venture": 35686, "\u0120Jag": 35687, "\u0120Celeb": 35688, "\u0120Voters": 35689, "\u0120steadfast": 35690, "\u0120athletics": 35691, "\u0120Hanson": 35692, "\u0120Drac": 35693, "Tracker": 35694, "\u0120commend": 35695, "\u0120Presidency": 35696, "\u0120DID": 35697, "informed": 35698, "\u0120webpage": 35699, "Pretty": 35700, "\u0120forcefully": 35701, "\u00e3\u0125\u0125\u00e3\u0124\u00af": 35702, "\u0120relocation": 35703, "\u0120satire": 35704, "\u00e2\u012b": 35705, "\u0120Sunderland": 35706, "\u00e6\u0126": 35707, "Voice": 35708, "????????": 35709, "\u0120informant": 35710, "\u0120bowel": 35711, "\u0120Uniform": 35712, "\u0120...\"": 35713, "\u0120purge": 35714, "\u0120picnic": 35715, "\u0120Umb": 35716, "\u0120UPDATE": 35717, "\u0120Sapphire": 35718, "\u0120Stall": 35719, "learn": 35720, "\u0120objectively": 35721, "\u0120obliter": 35722, "\u0120loophole": 35723, "\u0120journeys": 35724, "\u0120omission": 35725, "Pros": 35726, "\u0120Sidney": 35727, "ploma": 35728, "\u0120sprayed": 35729, "\u0120guru": 35730, "\u0120traitor": 35731, "\u0120timet": 35732, "\u0120snapping": 35733, "\u0120Sevent": 35734, "urnal": 35735, "\u0120Ukip": 35736, "\u0120bowed": 35737, "poral": 35738, "liberal": 35739, "Ros": 35740, "Questions": 35741, "iOS": 35742, "\u0120summarize": 35743, "STAT": 35744, "\u01201850": 35745, "apest": 35746, "\u0120lender": 35747, "\u0120Variable": 35748, "bringing": 35749, "\u0120LORD": 35750, ",)": 35751, "\u0120collapses": 35752, "xiety": 35753, "\u0120Ned": 35754, "YD": 35755, "\u0120Scha": 35756, "\u0120antibody": 35757, "\u0120disband": 35758, "yre": 35759, "illusion": 35760, "\u0120rover": 35761, "shed": 35762, "\u0120Hirosh": 35763, "cci": 35764, "\u0120calam": 35765, "\u0120Morton": 35766, "Pinterest": 35767, "\u01201928": 35768, "\u0120Euras": 35769, "ordes": 35770, "\u0120fences": 35771, "\u0120Inventory": 35772, "\u0120Valencia": 35773, "\u0120Ud": 35774, "\u0120Tiff": 35775, "\u0120sque": 35776, "\u0120quotation": 35777, "\u0120troublesome": 35778, "erker": 35779, "QUEST": 35780, "\u0120Kingdoms": 35781, "south": 35782, "\u0120levy": 35783, "Prince": 35784, "\u0120Sting": 35785, "\u0120nicknamed": 35786, "\u0120appe": 35787, "\u0120photographic": 35788, "\u0120corpus": 35789, "reference": 35790, "\u0120Trog": 35791, "Unt": 35792, ")=(": 35793, "\u0120Latvia": 35794, "\u0120activating": 35795, "\u0120licensee": 35796, "\u0120disparities": 35797, "\u0120Newsletter": 35798, "\u00e3\u0125\u0125\u00e3\u0125\u012a": 35799, "\u0120freeing": 35800, "\u0120Jeep": 35801, "\u0120Perception": 35802, "insk": 35803, "\u0120silicone": 35804, "\u0120Hayden": 35805, "Lean": 35806, "\u0120Suzuki": 35807, "ibrarian": 35808, "668": 35809, "\u0120spor": 35810, "\u0120correlations": 35811, "aghetti": 35812, "\u0120tuber": 35813, "\u0120IPCC": 35814, "ilus": 35815, "\u0120Vu": 35816, "\u0120wealthiest": 35817, "\u0120Carbuncle": 35818, "anza": 35819, "\u0120fooled": 35820, "\u0120Zur": 35821, "\u0120daddy": 35822, "rano": 35823, "ilian": 35824, "\u0120knockout": 35825, "fman": 35826, "required": 35827, "\u0120Wikileaks": 35828, "\u0120Duffy": 35829, "ONT": 35830, "\u0120insol": 35831, "\u0120Objects": 35832, "\u0120bou": 35833, "\u0120Nordic": 35834, "\u0120Insert": 35835, "scan": 35836, "\u0120dancers": 35837, "\u0120idiots": 35838, "majority": 35839, "\u0120Neville": 35840, "\u0120FreeBSD": 35841, "\u0120tart": 35842, "panic": 35843, "690": 35844, "\u0120cocoa": 35845, "\u0120sampled": 35846, "\u0120lookup": 35847, "Indust": 35848, "\u0120injections": 35849, "genre": 35850, "\u0120au": 35851, "\u0120roadway": 35852, "\u0120genitals": 35853, "Kind": 35854, "\u0120Examiner": 35855, "\u0120Yaz": 35856, "Fresh": 35857, "\u0120paralysis": 35858, "\u0120Aluminum": 35859, "\u0120reap": 35860, "ok\u00c3\u00a9": 35861, "\u0120sloppy": 35862, "\u0120Tunnel": 35863, "posium": 35864, "nery": 35865, "enic": 35866, "\u0120herbal": 35867, "\u0120Outer": 35868, "\u0120Builder": 35869, "\u0120incur": 35870, "\u0120ideologies": 35871, "\u0120backups": 35872, "consuming": 35873, "\u0120Detect": 35874, "deck": 35875, "\u0120KNOW": 35876, "\u0120Gret": 35877, "\u0120MIC": 35878, "\u0120toughness": 35879, "\u0120Exhibit": 35880, "\u0120hive": 35881, "Les": 35882, "\u0120SCHOOL": 35883, "\u0120Atari": 35884, "alde": 35885, "\u0120Null": 35886, "andestine": 35887, "mouse": 35888, "\u0120brigade": 35889, "489": 35890, "\u0120revol": 35891, "\u0120Lawson": 35892, "\u0120Wah": 35893, "opoly": 35894, "ebted": 35895, "\u0120Saunders": 35896, "\u0120313": 35897, "\u0120Winc": 35898, "\u0120taboo": 35899, "\u0120Helmet": 35900, "\u0120wedge": 35901, "chip": 35902, "\u0120Tina": 35903, "bg": 35904, "\u0120infuri": 35905, "rn": 35906, "\u0120anomalies": 35907, "\u0120Sync": 35908, "\u0120Exam": 35909, "\u0120Commit": 35910, "\u0120Diary": 35911, "\u0120ALSO": 35912, "\u0120Debor": 35913, "omedical": 35914, "\u0120comprehension": 35915, "655": 35916, "\u0120empowering": 35917, "\u0120ire": 35918, "\u0120juices": 35919, "\u0120ETH": 35920, "\u0120Boxing": 35921, "=\"/": 35922, "\u0120facilitated": 35923, "poke": 35924, "\u0120Parsons": 35925, "\u0120Moder": 35926, "travel": 35927, "\u0120civilizations": 35928, "\u0120libertarians": 35929, "\u0120rune": 35930, "\u0120Clarks": 35931, "athed": 35932, "\u0120campaigners": 35933, "\u0120Dispatch": 35934, "\u0120Fahrenheit": 35935, "\u0120Capcom": 35936, "----------": 35937, "\u0120lace": 35938, "\u0120draining": 35939, "\u0120liner": 35940, "\u0120Artificial": 35941, "\u00c3\u00a9n": 35942, "task": 35943, "]).": 35944, "\u0120GMO": 35945, "\u0120Operator": 35946, "ordinary": 35947, "\u0120Influence": 35948, "\u0120Ups": 35949, "\u0120potency": 35950, "ussen": 35951, "ospons": 35952, "\u0120Swim": 35953, "\u0120Deadline": 35954, "Unity": 35955, "\u0120culinary": 35956, "\u0120enlightenment": 35957, "\u0120wearer": 35958, "\u0120mined": 35959, "\u0120ply": 35960, "\u0120incest": 35961, "\u0120DVDs": 35962, "Walk": 35963, "BTC": 35964, "Trade": 35965, "\u0120deval": 35966, "iband": 35967, "\u0120Oversight": 35968, "Palestinian": 35969, "\u0120dart": 35970, "\u0120mul": 35971, "LR": 35972, "\u0120removable": 35973, "\u0120Realms": 35974, "\u00ec\u013f": 35975, "\u0120miscar": 35976, "\u0120Vulkan": 35977, "685": 35978, "\u00c3\u00a8re": 35979, "\u0120Sap": 35980, "\u0120merging": 35981, "\u0120Carly": 35982, "chester": 35983, "\u0120brisk": 35984, "\u0120luxurious": 35985, "\u0120Generator": 35986, "\u0120bitterness": 35987, "\u0120edible": 35988, "\u0120243": 35989, "TG": 35990, "\u0120rectangle": 35991, "WithNo": 35992, "below": 35993, "Jenn": 35994, "\u0120darkest": 35995, "\u0120hitch": 35996, "\u0120dosage": 35997, "\u0120scaven": 35998, "\u0120Keller": 35999, "\u0120Illustrated": 36000, "Certainly": 36001, "\u0120Mavericks": 36002, "Marginal": 36003, "\u0120diarrhea": 36004, "\u0120enormously": 36005, "\u0120999": 36006, "shr": 36007, "quart": 36008, "\u0120adamant": 36009, "\u0120Mew": 36010, "\u0120renovation": 36011, "\u0120cervical": 36012, "\u0120Percentage": 36013, "eners": 36014, "\u0120Kimber": 36015, "\u0120floats": 36016, "\u0120dex": 36017, "\u0120Witcher": 36018, "\u0120Swansea": 36019, "dm": 36020, "\u0120salty": 36021, "yellow": 36022, "\u0120cape": 36023, "\u0120Drain": 36024, "\u0120Paula": 36025, "\u0120Toledo": 36026, "lesi": 36027, "Magazine": 36028, "\u0120Wick": 36029, "\u0120Mn": 36030, "\u0120Ack": 36031, "\u0120Riding": 36032, "ASON": 36033, "\u0120homophobic": 36034, "ARP": 36035, "\u0120wandered": 36036, "CPU": 36037, "oodoo": 36038, "\u0120Pipe": 36039, "\u0120tightening": 36040, "\u0120Butt": 36041, "318": 36042, "\u0120deserted": 36043, "Session": 36044, "\u0120facilitating": 36045, "Jump": 36046, "\u0120emergencies": 36047, "OWER": 36048, "\u0120exhaustive": 36049, "\u0120AFTER": 36050, "\u0120heartbeat": 36051, "\u0120Label": 36052, "acky": 36053, "\u0120Certified": 36054, "iltration": 36055, "Ze": 36056, "\u0120Utt": 36057, "\u01201300": 36058, "\u0120presume": 36059, "\u0120Disp": 36060, "\u0120surged": 36061, "\u0120dolls": 36062, "Columb": 36063, "\u0120chimpan": 36064, "\u0120Razor": 36065, "\u0120ticks": 36066, "\u0120councillor": 36067, "\u0120pilgrimage": 36068, "\u0120Rebels": 36069, "\u0120QC": 36070, "\u0120Auction": 36071, "xia": 36072, "ikk": 36073, "bred": 36074, "\u0120insertion": 36075, "\u0120coarse": 36076, "dB": 36077, "SEE": 36078, "\u0120Zap": 36079, "\u0120Foo": 36080, "\u0120contempor": 36081, "\u0120Quarterly": 36082, "otions": 36083, "\u0120Alchemist": 36084, "\u0120Trey": 36085, "\u0120Duo": 36086, "Sweet": 36087, "804": 36088, "\u0120Giov": 36089, "\u0120funn": 36090, "Nin": 36091, "hoff": 36092, "\u0120ramifications": 36093, "\u01201922": 36094, "\u0120Experts": 36095, "azes": 36096, "\u0120garments": 36097, "arial": 36098, "\u0120Nab": 36099, "\u0120257": 36100, "\u0120Ved": 36101, "\u0120humorous": 36102, "\u0120Pompe": 36103, "\u0120nylon": 36104, "\u0120lurking": 36105, "\u0120Sergey": 36106, "\u0120Mattis": 36107, "\u0120misogyny": 36108, "\u0120Components": 36109, "\u0120Watching": 36110, "\u0120Folk": 36111, "ractical": 36112, "Bush": 36113, "\u0120taped": 36114, "\u0120grouping": 36115, "\u0120beads": 36116, "\u01202048": 36117, "\u0120condu": 36118, "querque": 36119, "Reading": 36120, "\u0120grievances": 36121, "Ultra": 36122, "\u0120endpoint": 36123, "Hig": 36124, "\u0120Static": 36125, "\u0120Scarborough": 36126, "Lua": 36127, "\u0120Messi": 36128, "aqu": 36129, "\u0120PsyNet": 36130, "\u0120Rudd": 36131, "\u0120avenue": 36132, "vp": 36133, "Jer": 36134, "\u0120shady": 36135, "\u0120Resist": 36136, "\u0120Artemis": 36137, "\u0120careless": 36138, "\u0120brokers": 36139, "\u0120temperament": 36140, "\u0120520": 36141, "Tags": 36142, "\u0120Turning": 36143, "\u0120uttered": 36144, "\u0120pedd": 36145, "\u0120improvised": 36146, "\u0120:(": 36147, "\u0120tabl": 36148, "\u0120plains": 36149, "1600": 36150, "pressure": 36151, "\u0120Essence": 36152, "margin": 36153, "friends": 36154, "\u0120Restoration": 36155, "\u0120pollut": 36156, "\u0120Poker": 36157, "\u0120Augustine": 36158, "\u0120CIS": 36159, "\u0120SEAL": 36160, "orama": 36161, "\u0120thwart": 36162, "seek": 36163, "\u0120pagan": 36164, "\u00c2\u00ba": 36165, "cpu": 36166, "\u0120garn": 36167, "\u0120assortment": 36168, "\u0120ILCS": 36169, "tower": 36170, "Recommended": 36171, "\u0120unborn": 36172, "\u0120RandomRedditor": 36173, "\u0120RandomRedditorWithNo": 36174, "\u0120paralyzed": 36175, "\u0120eruption": 36176, "\u0120intersect": 36177, "\u0120Stoke": 36178, "\u0120Sco": 36179, "Bind": 36180, "\u00e5\u00be": 36181, "\u0120PNG": 36182, "\u0120Negative": 36183, "\u0120NOAA": 36184, "Leon": 36185, "\u0120alloy": 36186, "\u0120Lama": 36187, "\u0120Diversity": 36188, "575": 36189, "\u0120underestimated": 36190, "\u0120Scor": 36191, "\u0120mural": 36192, "\u0120busted": 36193, "soon": 36194, "lif": 36195, "\u0120nonex": 36196, "\u0120allergy": 36197, "\u0120Underworld": 36198, "\u0120Rays": 36199, "\u0120Blasio": 36200, "\u0120hrs": 36201, "\u0120Dir": 36202, "\u0120327": 36203, "byter": 36204, "\u0120replacements": 36205, "\u0120activates": 36206, "rived": 36207, "MH": 36208, "\u0120pans": 36209, "\u0120HI": 36210, "\u0120longitudinal": 36211, "\u0120nuisance": 36212, "aler": 36213, "\u0120swell": 36214, "\u0120Signed": 36215, "sci": 36216, "\u0120Isles": 36217, "\u0120AGA": 36218, "\u0120defiant": 36219, "\u0120sonic": 36220, "ocon": 36221, "KC": 36222, "\u0120Aim": 36223, "tie": 36224, "ahah": 36225, "\u0120mL": 36226, "DX": 36227, "\u0120bisc": 36228, "\u0120Billboard": 36229, "\u0120SYSTEM": 36230, "NEY": 36231, "gaard": 36232, "\u0120distressed": 36233, "formerly": 36234, "Alan": 36235, "\u0120chefs": 36236, "\u0120optics": 36237, "\u0120Comet": 36238, "\u0120AMC": 36239, "\u0120redesigned": 36240, "irmation": 36241, "\u0120sightings": 36242, "382": 36243, "311": 36244, "\u0120WB": 36245, "\u0120contraction": 36246, "\u0120TOTAL": 36247, "Dual": 36248, "\u0120startled": 36249, "\u0120understandably": 36250, "\u0120sunglasses": 36251, "ETHOD": 36252, "\u0120docker": 36253, "\u0120surfing": 36254, "\u0120HEL": 36255, "\u0120Slack": 36256, "tones": 36257, "\u0120shalt": 36258, "Visual": 36259, "498": 36260, "Department": 36261, "cussion": 36262, "\u0120unrestricted": 36263, "\u0120tad": 36264, "\u0120rename": 36265, "employed": 36266, "\u0120educating": 36267, "\u0120grinned": 36268, "bedroom": 36269, "\u0120Activities": 36270, "\u0120Velvet": 36271, "\u0120SWAT": 36272, "\u0120shuffle": 36273, "igor": 36274, "\u0120saturation": 36275, "Finding": 36276, "cream": 36277, "icter": 36278, "\u0120vodka": 36279, "tracking": 36280, "tec": 36281, "\u0120foreground": 36282, "iesta": 36283, "\u0120vehement": 36284, "\u0120ECB": 36285, "\u0120Tie": 36286, "Ey": 36287, "\u0120turtles": 36288, "\u0120Railroad": 36289, "\u0120Katz": 36290, "\u0120Frames": 36291, "\u0120menace": 36292, "\u0120Fellowship": 36293, "\u0120Essential": 36294, "uggish": 36295, "\u0120drip": 36296, "chwitz": 36297, "\u0120Kyoto": 36298, "sb": 36299, "\u0120Nina": 36300, "Parameter": 36301, "\u0120alarms": 36302, "\u0120Claud": 36303, "\u0120pioneering": 36304, "\u0120chiefly": 36305, "\u0120Scream": 36306, "Collection": 36307, "\u0120thankfully": 36308, "\u0120Ronaldo": 36309, "\u00e5\u0143\u0132": 36310, "strip": 36311, "\u0120Disneyland": 36312, "commercial": 36313, "Seeing": 36314, "Soul": 36315, "\u0120evacuate": 36316, "\u0120civ": 36317, "\u0120Ashe": 36318, "\u0120divides": 36319, "\u0120Dagger": 36320, "rehensive": 36321, "\u0120berries": 36322, "\u0120DF": 36323, "\u0120sushi": 36324, "\u0120plurality": 36325, "WI": 36326, "\u0120disadvantaged": 36327, "\u0120battalion": 36328, "obiles": 36329, "451": 36330, "\u0120cling": 36331, "\u0120undeniable": 36332, "\u0120Lounge": 36333, "\u0120haunt": 36334, "phe": 36335, "\u0120quantify": 36336, "\u0120differed": 36337, "\u0120[*]": 36338, "\u0120Viz": 36339, "cum": 36340, "slave": 36341, "\u0120videog": 36342, "\u0120quar": 36343, "\u0120bundles": 36344, "\u0120Alonso": 36345, "tackle": 36346, "\u0120neuronal": 36347, "\u0120landslide": 36348, "confirmed": 36349, "\u0120Depth": 36350, "\u0120renewables": 36351, "Bear": 36352, "\u0120Macedonia": 36353, "\u0120jerseys": 36354, "\u0120bunk": 36355, "\u0120Spawn": 36356, "\u0120Controls": 36357, "\u0120Buchanan": 36358, "\u0120robotics": 36359, "\u0120emphasizing": 36360, "\u0120Tutorial": 36361, "hyp": 36362, "iston": 36363, "\u0120monumental": 36364, "\u00e6\u00b0": 36365, "\u0120Carry": 36366, "\u0120tbsp": 36367, "enance": 36368, "Hill": 36369, "arthed": 36370, "\u0120rotten": 36371, "Dean": 36372, "\u0120twisting": 36373, "\u0120goodwill": 36374, "\u0120immersion": 36375, "Living": 36376, "\u0120brushes": 36377, "\u0120CGI": 36378, "\u0120Atk": 36379, "traditional": 36380, "\u0120phantom": 36381, "\u0120Stamina": 36382, "\u0120expansions": 36383, "\u0120Marin": 36384, "\u0120embarked": 36385, "\u0120Eg": 36386, "intestinal": 36387, "\u0120PEOPLE": 36388, "\u0120Booth": 36389, "\u0120Appalach": 36390, "\u0120relegated": 36391, "VT": 36392, "MIT": 36393, "\u0120muster": 36394, "\u0120withdrawing": 36395, "\u0120microscope": 36396, "\u0120Gathering": 36397, "\u0120Crescent": 36398, "\u0120Argentine": 36399, "\u0120Decre": 36400, "\u0120Dominic": 36401, "\u0120buds": 36402, "antage": 36403, "\u0120Ion": 36404, "\u0120widened": 36405, "ONSORED": 36406, "\u0120Gloves": 36407, "iannopoulos": 36408, "razen": 36409, "feel": 36410, "\u0120repayment": 36411, "\u0120hindsight": 36412, "\u0120REALLY": 36413, "\u0120Pistol": 36414, "\u0120Brah": 36415, "\u0120watts": 36416, "\u0120survives": 36417, "\u0120flurry": 36418, "issy": 36419, "Alert": 36420, "\u0120Uruguay": 36421, "Phoenix": 36422, "Slow": 36423, "\u0120Grave": 36424, "\u0120Fir": 36425, "\u0120manageable": 36426, "\u0120tariff": 36427, "\u0120UDP": 36428, "\u0120Pistons": 36429, "\u0120Nigerian": 36430, "\u0120strikeouts": 36431, "\u0120cosmetics": 36432, "whelming": 36433, "fab": 36434, "cape": 36435, "proxy": 36436, "\u0120rethink": 36437, "\u0120overcoming": 36438, "simple": 36439, "\u0120woo": 36440, "\u0120distracting": 36441, "\u0120Stanton": 36442, "\u0120Tulsa": 36443, "\u0120Dock": 36444, "659": 36445, "\u0120discord": 36446, "\u0120Emacs": 36447, "\u0120Ves": 36448, "\u0120ROB": 36449, "\u0120reassuring": 36450, "\u0120consortium": 36451, "Muslims": 36452, "321": 36453, "\u0120prompts": 36454, "sei": 36455, "\u0120Hitch": 36456, "imposed": 36457, "\u0120Fool": 36458, "\u0120indiscrim": 36459, "wrong": 36460, "buquerque": 36461, "Davis": 36462, "!]": 36463, "\u0120timeless": 36464, "\u0120NEED": 36465, "\u0120pesticide": 36466, "\u0120rallying": 36467, "\u0120Calder": 36468, "\u0120\u00e5\u00a4": 36469, "\u0120xp": 36470, "\u0120Unle": 36471, "\u0120Export": 36472, "luaj": 36473, "Buff": 36474, ")[": 36937, "\u0120sqor": 36938, "Saudi": 36939, "\u0120istg": 36940, "\u0120indulge": 36941, "proc": 36942, "\u0120disgusted": 36943, "\u0120compounded": 36944, "\u0120nem": 36945, "\u0120schooling": 36946, "\u0120Cure": 36947, "processing": 36948, "Sol": 36949, "\u0120proverb": 36950, "itized": 36951, "\u0120Alvarez": 36952, "\u0120scarf": 36953, "\u0120rectangular": 36954, "reve": 36955, "\u0120hormonal": 36956, "\u0120Stress": 36957, "itizen": 36958, "\u0120425": 36959, "girls": 36960, "\u0120Noir": 36961, "\u0120Rapp": 36962, "\u0120marches": 36963, "church": 36964, "\u0120Uses": 36965, "\u0120405": 36966, "\u0120Berm": 36967, "\u0120ordinances": 36968, "\u0120Judgment": 36969, "Charges": 36970, "\u0120Zin": 36971, "\u0120dusty": 36972, "\u0120strawberries": 36973, "\u0120perce": 36974, "\u0120Thur": 36975, "\u0120Deborah": 36976, "netflix": 36977, "\u0120Lambert": 36978, "\u0120amused": 36979, "\u0120Guang": 36980, "YOU": 36981, "RGB": 36982, "\u0120CCTV": 36983, "\u0120fiat": 36984, "rang": 36985, "\u0120federation": 36986, "\u0120Mant": 36987, "\u0120Bust": 36988, "\u0120Mare": 36989, "respective": 36990, "\u0120Migration": 36991, "\u0120BIT": 36992, "590": 36993, "\u0120patriotism": 36994, "\u0120outlining": 36995, "region": 36996, "\u0120Jos\u00c3\u00a9": 36997, "\u0120blasting": 36998, "\u0120Ezra": 36999, "Bs": 37000, "\u0120undermines": 37001, "\u0120Smooth": 37002, "\u0120clashed": 37003, "radio": 37004, "\u0120transitioning": 37005, "\u0120Buccaneers": 37006, "\u0120Owl": 37007, "\u0120plugs": 37008, "\u0120hiatus": 37009, "\u0120Pinball": 37010, "\u0120mig": 37011, "\u0120Nutr": 37012, "\u0120Wolfe": 37013, "\u0120integers": 37014, "\u0120orbits": 37015, "\u0120Edwin": 37016, "\u0120DirectX": 37017, "bite": 37018, "\u0120blazing": 37019, "vr": 37020, "Edge": 37021, "\u0120PID": 37022, "exit": 37023, "\u0120Comed": 37024, "\u0120Pathfinder": 37025, "\u0120Guid": 37026, "\u0120Signs": 37027, "\u0120Zer": 37028, "\u0120Agenda": 37029, "\u0120reimbursement": 37030, "Mesh": 37031, "iPhone": 37032, "\u0120Marcos": 37033, "\u0120Sites": 37034, "hate": 37035, "enburg": 37036, "\u0120sockets": 37037, "pend": 37038, "Batman": 37039, "vir": 37040, "\u0120SHOW": 37041, "\u0120provisional": 37042, "conn": 37043, "\u0120Deaths": 37044, "ATIVE": 37045, "Profile": 37046, "sym": 37047, "JA": 37048, "\u0120ninja": 37049, "installed": 37050, "idates": 37051, "ebra": 37052, "\u0120Omaha": 37053, "\u0120seizing": 37054, "\u0120Beasts": 37055, "\u0120salts": 37056, "Mission": 37057, "Generally": 37058, "\u0120Trilogy": 37059, "heon": 37060, "legates": 37061, "\u0120dime": 37062, "\u0120faire": 37063, "parable": 37064, "Graph": 37065, "\u0120totaling": 37066, "\u0120diagrams": 37067, "\u0120Yanuk": 37068, "plet": 37069, "\u0120Meh": 37070, "\u0120mythical": 37071, "\u0120Stephens": 37072, "autical": 37073, "ochemistry": 37074, "\u0120kilograms": 37075, "\u0120elbows": 37076, "ancock": 37077, "\u0120BCE": 37078, "\u0120Prague": 37079, "\u0120improv": 37080, "\u0120Devin": 37081, "\u0120\"\\": 37082, "paralle": 37083, "\u0120supremacists": 37084, "\u0120Billion": 37085, "\u0120regimen": 37086, "innacle": 37087, "\u0120requisite": 37088, "angan": 37089, "\u0120Burlington": 37090, "ainment": 37091, "\u0120Objective": 37092, "omsky": 37093, "GV": 37094, "\u0120unilateral": 37095, "\u0120tc": 37096, "\u0120hires": 37097, "mental": 37098, "\u0120involuntary": 37099, "\u0120transpl": 37100, "\u0120ASCII": 37101, "\u00c2\u00a8": 37102, "Events": 37103, "\u0120doubted": 37104, "\u0120Kaplan": 37105, "\u0120Courage": 37106, "igon": 37107, "\u0120Managing": 37108, "\u0120Tart": 37109, "\u0120falsehood": 37110, "\u0120Violet": 37111, "\u0120airs": 37112, "\u0120fertilizer": 37113, "Britain": 37114, "\u0120aquatic": 37115, "ouf": 37116, "Words": 37117, "\u0120Hartford": 37118, "\u0120evenings": 37119, "\u0120Vengeance": 37120, "quite": 37121, "Gall": 37122, "\u0120Pret": 37123, "\u0120pdf": 37124, "\u0120LM": 37125, "\u0120Sochi": 37126, "\u0120Intercept": 37127, "920": 37128, "\u0120profitability": 37129, "\u0120Idle": 37130, "\u0120MacDonald": 37131, "\u0120Establishment": 37132, "umsy": 37133, "\u0120gatherings": 37134, "\u0120Naj": 37135, "Charlie": 37136, "\u0120ascent": 37137, "\u0120Protector": 37138, "\u0120algebra": 37139, "\u0120bios": 37140, "forums": 37141, "ELS": 37142, "Introduced": 37143, "\u0120335": 37144, "\u0120astronomy": 37145, "Contribut": 37146, "\u0120Polic": 37147, "Platform": 37148, "\u0120containment": 37149, "wrap": 37150, "\u0120coronary": 37151, "\u0120Jelly": 37152, "manager": 37153, "\u0120heartbreaking": 37154, "cair": 37155, "\u0120Chero": 37156, "cgi": 37157, "Medical": 37158, "\u0120Accountability": 37159, "!!\"": 37160, "ophile": 37161, "\u0120psychotic": 37162, "\u0120Restrict": 37163, "\u0120equitable": 37164, "issues": 37165, "\u01201905": 37166, "\u0120Nek": 37167, "cised": 37168, "\u0120Tracking": 37169, "\u0120ozone": 37170, "\u0120cooker": 37171, "rosis": 37172, "\u0120reopen": 37173, "\u0120infinity": 37174, "\u0120Pharmaceutical": 37175, "ensional": 37176, "Attempt": 37177, "\u0120Rory": 37178, "Marco": 37179, "\u0120awaits": 37180, "HOW": 37181, "treated": 37182, "\u0120bolst": 37183, "\u0120revered": 37184, "\u0120pods": 37185, "oppers": 37186, "0010": 37187, "\u0120amplitude": 37188, "rican": 37189, "SPONSORED": 37190, "\u0120trousers": 37191, "\u0120halves": 37192, "\u0120Kaine": 37193, "\u0120Cutler": 37194, "\u0120AUTH": 37195, "\u0120splendid": 37196, "\u0120preventive": 37197, "\u0120Dudley": 37198, "ifacts": 37199, "uminati": 37200, "\u0120Yin": 37201, "\u0120admon": 37202, "\u0120Vag": 37203, "\u0120inverted": 37204, "\u0120hastily": 37205, "\u0120Hague": 37206, "Lyn": 37207, "\u0120ledger": 37208, "\u0120astronomical": 37209, "getting": 37210, "\u0120circa": 37211, "\u0120Cic": 37212, "\u0120Tennis": 37213, "Limited": 37214, "\u0120dru": 37215, "\u0120BYU": 37216, "\u0120travellers": 37217, "\u0120pane": 37218, "\u0120Intro": 37219, "\u0120patiently": 37220, "\u0120aiding": 37221, "\u0120loos": 37222, "\u0120Tough": 37223, "\u0120293": 37224, "\u0120consumes": 37225, "SourceFile": 37226, "\u0120\"\"\"": 37227, "\u0120bonding": 37228, "\u0120tilted": 37229, "\u0120menstrual": 37230, "\u0120Celestial": 37231, "ULAR": 37232, "Plugin": 37233, "\u0120risking": 37234, "Naz": 37235, "\u0120Riyadh": 37236, "\u0120accredited": 37237, "\u0120skirm": 37238, "\u00e9\u013d": 37239, "\u0120examiner": 37240, "\u0120messing": 37241, "\u0120nearing": 37242, "\u0120Chern": 37243, "\u0120Beckham": 37244, "\u0120swapped": 37245, "\u0120goose": 37246, "Kay": 37247, "\u0120lofty": 37248, "\u0120Wallet": 37249, "\u0120['": 37250, "\u0120apocalypse": 37251, "\u0120bamboo": 37252, "\u0120SPACE": 37253, "\u0120Elena": 37254, "\u0120306": 37255, "acons": 37256, "\u0120tightened": 37257, "\u0120adolescence": 37258, "\u0120rainy": 37259, "\u0120vandalism": 37260, "\u0120Newtown": 37261, "\u0120conject": 37262, "cakes": 37263, "\u0120cheated": 37264, "\u0120moderators": 37265, "params": 37266, "EFF": 37267, "\u0120deceit": 37268, "\u0120STL": 37269, "\u0120Tanzania": 37270, "\u0120RI": 37271, "\u01201923": 37272, "\u0120Exile": 37273, "thel": 37274, "\u0120theolog": 37275, "\u0120quirky": 37276, "\u0120Irvine": 37277, "\u0120needy": 37278, "oris": 37279, "Um": 37280, "Ka": 37281, "\u0120mailbox": 37282, "322": 37283, "\u0120bos": 37284, "\u0120Petra": 37285, "KING": 37286, "\u0120enlarged": 37287, "Often": 37288, "\u0120badass": 37289, "\u0120343": 37290, "\u0120Places": 37291, "\u0120CAD": 37292, "\u0120pristine": 37293, "\u0120intervening": 37294, "direction": 37295, "\u0120laz": 37296, "\u0120DSM": 37297, "\u0120projecting": 37298, "\u0120Funk": 37299, "agog": 37300, "payment": 37301, "nov": 37302, "\u0120chatter": 37303, "ARB": 37304, "\u0120examinations": 37305, "\u0120Household": 37306, "\u0120Gus": 37307, "Ford": 37308, "414": 37309, "Boss": 37310, "\u0120mystic": 37311, "\u0120leaps": 37312, "\u0120Bav": 37313, "ulz": 37314, "budget": 37315, "Football": 37316, "\u0120subsidized": 37317, "\u0120firsthand": 37318, "\u0120coincide": 37319, "ocular": 37320, "Conn": 37321, "\u0120Collabor": 37322, "\u0120fools": 37323, "amura": 37324, "ahar": 37325, "rists": 37326, "\u0120swollen": 37327, "\u0120expended": 37328, "\u0120Pau": 37329, "sup": 37330, "\u0120spar": 37331, "\u0120keynote": 37332, "suff": 37333, "\u0120unequal": 37334, "\u0120progressing": 37335, "strings": 37336, "\u0120Gamergate": 37337, "Disney": 37338, "\u0120Eleven": 37339, "omnia": 37340, "\u0120scripted": 37341, "\u0120earners": 37342, "brother": 37343, "\u0120Enabled": 37344, "\u00e6\u00b3": 37345, "\u0120larvae": 37346, "\u0120LOC": 37347, "mess": 37348, "Wilson": 37349, "\u0120Template": 37350, "successfully": 37351, "\u0120paramount": 37352, "\u0120camouflage": 37353, "\u0120binds": 37354, "\u0120Quiet": 37355, "\u0120Shutterstock": 37356, "rush": 37357, "\u0120mascot": 37358, "fortune": 37359, "\u0120Colt": 37360, "\u0120Beyon": 37361, "habi": 37362, "\u0120hairc": 37363, "\u0120267": 37364, "\u0120Deus": 37365, "\u0120twitch": 37366, "\u0120concentrating": 37367, "\u0120nipples": 37368, "cible": 37369, "\u0120gir": 37370, "NZ": 37371, "Math": 37372, "nih": 37373, "Required": 37374, "\u0120ponder": 37375, "\u0120SAN": 37376, "\u0120weddings": 37377, "\u0120loneliness": 37378, "NES": 37379, "\u0120Mahjong": 37380, "695": 37381, "addle": 37382, "\u0120Garner": 37383, "\u0120COUR": 37384, "Bridge": 37385, "\u0120spree": 37386, "\u0120Caldwell": 37387, "\u0120bribery": 37388, "\u0120\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd\u00ef\u00bf\u00bd": 37389, "plugins": 37390, "\u0120racket": 37391, "\u0120champagne": 37392, "versible": 37393, "Vote": 37394, "\u0120modifiers": 37395, "Mayor": 37396, "680": 37397, "\u0120assemblies": 37398, "\u0120Sultan": 37399, "\u0120Ning": 37400, "\u0120Ladies": 37401, "\u0120sulfur": 37402, "\u0120orbs": 37403, "\u0120-----": 37404, "_______": 37405, "\u0120Journalism": 37406, "\u0120esports": 37407, "\u0120lush": 37408, "\u0120hue": 37409, "\u0120spectral": 37410, "Honest": 37411, "\u00e3\u0125\u0131": 37412, "\u0120bushes": 37413, "\u0120reinforcement": 37414, "\u0120reopened": 37415, "\u0120Wheels": 37416, "\u0120Morg": 37417, "rieving": 37418, "\u0120auxiliary": 37419, "\u0120jQuery": 37420, "\u0120BAT": 37421, "tesque": 37422, "\u0120vertex": 37423, "pure": 37424, "frey": 37425, "\u00e3\u0124\u00ba": 37426, "dos": 37427, "\u0120typh": 37428, "\u0120cull": 37429, "\u0120eq": 37430, "\u0120decon": 37431, "\u0120tossing": 37432, "\u0120disparate": 37433, "\u0120Brigham": 37434, "printf": 37435, "ledged": 37436, "\u0120sund": 37437, "\u0120cozy": 37438, "\u0120hepatitis": 37439, "performing": 37440, "\u0120aval": 37441, "\u0120GG": 37442, "future": 37443, "\u0120petertodd": 37444, "\u0120Kosovo": 37445, "\u0120magnets": 37446, "Already": 37447, "\u0120Edison": 37448, "\u0120Ceres": 37449, "\u0120RAID": 37450, "\u0120brilliance": 37451, "576": 37452, "\u0120derives": 37453, "\u0120hypertension": 37454, "\u0120\u00ce\u0136": 37455, "\u0120lambda": 37456, "\u0120flair": 37457, "\u0120missionaries": 37458, "\u0120rapes": 37459, "\u0120Starter": 37460, "\u0120Months": 37461, "\u0120defy": 37462, "\u0120seismic": 37463, "\u0120Raphael": 37464, "\u0120eurozone": 37465, "656": 37466, "zsche": 37467, "\u0120scratched": 37468, "\u0120bows": 37469, "\u0120Lennon": 37470, "\u0120Gaia": 37471, "\u0120dripping": 37472, "facts": 37473, "Ale": 37474, "\u0120frogs": 37475, "\u0120Breast": 37476, "ogeneity": 37477, "\u0120Prosecutor": 37478, "\u0120amplified": 37479, "\u0120Hodg": 37480, "\u0120Fn": 37481, "Thousands": 37482, "\u0120NIH": 37483, "\u0120Monitoring": 37484, "FTWARE": 37485, "\u0120Priebus": 37486, "\u0120Growing": 37487, "hunter": 37488, "\u0120diagnose": 37489, "\u0120Mald": 37490, "\u0120LR": 37491, "\u0120crowned": 37492, "\u0120bursting": 37493, "\u0120dissolution": 37494, "javascript": 37495, "\u0120usefulness": 37496, "\u0120Execution": 37497, ":(": 37498, "\u0120Ivory": 37499, "aah": 37500, "\u0120persecuted": 37501, "violence": 37502, "istas": 37503, "\u0120Crate": 37504, "\u0120impulses": 37505, "\u0120Spani": 37506, "edes": 37507, "Handle": 37508, "\u0120Zerg": 37509, "thinkable": 37510, "Lastly": 37511, "\u0120spontaneously": 37512, "\u0120inconvenient": 37513, "\u0120dismissing": 37514, "\u0120plotted": 37515, "\u0120eighty": 37516, "\u0120737": 37517, "rish": 37518, "\u0120Thornton": 37519, "atham": 37520, "\u0120sitcom": 37521, "Ven": 37522, "Recipe": 37523, "tel": 37524, "lund": 37525, "\u0120clears": 37526, "\u0120Sasuke": 37527, "\u0120258": 37528, "\u0120opting": 37529, "\u0120enraged": 37530, "esthetic": 37531, "\u0120Ae": 37532, "uchs": 37533, "Prep": 37534, "Flow": 37535, "\u0120runoff": 37536, "\u0120Eating": 37537, "\u0120Giles": 37538, "\u0120Acting": 37539, "resources": 37540, "ibaba": 37541, "\u0120rpm": 37542, "\u0120skewed": 37543, "\u0120Blanc": 37544, "\u0120Sakuya": 37545, "\u0120hotter": 37546, "\u01201924": 37547, "opian": 37548, "cko": 37549, "\u0120crumbling": 37550, "\u0120captains": 37551, "\u0120Appropriations": 37552, "leaders": 37553, "dropping": 37554, "anuts": 37555, "\u0120reversing": 37556, "\u0120Pose": 37557, "\u0120Sek": 37558, "Scot": 37559, "\u0120Idea": 37560, "cise": 37561, "\u0120Slovenia": 37562, "\u0120317": 37563, "Doctor": 37564, "\u0120crocod": 37565, "aldi": 37566, "Sea": 37567, "\u0120Farrell": 37568, "\u0120mercenaries": 37569, "\u0120RNC": 37570, "\u0120Guess": 37571, "\u0120pacing": 37572, "Machine": 37573, "StreamerBot": 37574, "\u0120Charity": 37575, "\u0120298": 37576, "\u0120cannons": 37577, "\u0120Toby": 37578, "TPPStreamerBot": 37579, "\u0120Passion": 37580, "cfg": 37581, "Thom": 37582, "\u0120badges": 37583, "\u0120Bernstein": 37584, ".\u00e2\u0122\u0135": 37585, "\u0120POP": 37586, "\u0120Conj": 37587, "\u0120initialization": 37588, "\u0120biodiversity": 37589, "Dub": 37590, "\u0120feudal": 37591, "\u0120disclaimer": 37592, "\u0120crow": 37593, "\u0120ignition": 37594, "arf": 37595, "SHA": 37596, "\u0120kHz": 37597, "hazard": 37598, "\u0120Artists": 37599, "oeuv": 37600, "679": 37601, "\u0120Rudy": 37602, "Nine": 37603, "\u0120Ramadan": 37604, "\u00e5\u00bd": 37605, "itto": 37606, "\u0120adrenaline": 37607, "Cert": 37608, "\u0120smelled": 37609, "\u0120impunity": 37610, "\u0120agendas": 37611, "\u0120Reborn": 37612, "\u0120Concent": 37613, "\u0120Seems": 37614, "\u0120omega": 37615, "\u0120Dustin": 37616, "\u0120backer": 37617, "\u0120Sauce": 37618, "\u0120Boyle": 37619, "WIN": 37620, "\u0120spins": 37621, "\u0120pauses": 37622, "upt": 37623, "\u0120shredded": 37624, "\u0120strapped": 37625, "\u0120Corruption": 37626, "\u0120scratches": 37627, "\u0120ni": 37628, "\u0120attire": 37629, "\u0120SAF": 37630, "FactoryReloaded": 37631, "\u0120IPS": 37632, "\u0120(%": 37633, "\u0120seminar": 37634, "focus": 37635, "civil": 37636, "\u01201860": 37637, "intosh": 37638, "\u0120continual": 37639, "\u0120abbrevi": 37640, "\u0120Sok": 37641, "ocobo": 37642, "XM": 37643, "\u0120frantic": 37644, "\u0120unavoidable": 37645, "\u0120artery": 37646, "\u0120annotations": 37647, "bath": 37648, "Climate": 37649, "\u0120dors": 37650, "\u0120Slide": 37651, "coord": 37652, "\u0120Reload": 37653, "\u0120LDL": 37654, "\u0120Lovecraft": 37655, "\u0120unimagin": 37656, "\u0120resembled": 37657, "\u0120barracks": 37658, "np": 37659, "\u0120surrogate": 37660, "\u0120categorized": 37661, "\u00e3\u0124\u00a9": 37662, "\u0120vaccinated": 37663, "\u0120drainage": 37664, "\u0120indist": 37665, "\u0120WhatsApp": 37666, "\u01201870": 37667, "olerance": 37668, "invoke": 37669, "amorph": 37670, "\u0120reconnect": 37671, "\u0120emanc": 37672, "\u0120blindness": 37673, "\u01201280": 37674, "internet": 37675, "collar": 37676, "\u0120altru": 37677, "\u0120abyss": 37678, "\u0120TRI": 37679, "657": 37680, "\u0120infused": 37681, "HEAD": 37682, "\u0120forestry": 37683, "\u0120Woody": 37684, "\u0120Ci": 37685, "wi": 37686, "sam": 37687, "784": 37688, "holiday": 37689, "\u0120mogul": 37690, "\u0120Fees": 37691, "\u0120DEN": 37692, "Internal": 37693, "urbed": 37694, "fusc": 37695, "atom": 37696, "\u0120Illusion": 37697, "\u0120polled": 37698, "\u0120flap": 37699, "\u0120coax": 37700, "LGBT": 37701, "Analy": 37702, "\u0120Sections": 37703, "\u0120Californ": 37704, "emn": 37705, "\u0120hither": 37706, "\u0120NIGHT": 37707, "\u0120nailed": 37708, "\u0120Pipeline": 37709, "391": 37710, "oof": 37711, "\u0120Primal": 37712, "verend": 37713, "\u0120slashing": 37714, "\u0120retri": 37715, "aviour": 37716, "\u0120departing": 37717, "gil": 37718, "ISC": 37719, "\u0120midway": 37720, "\u0120ultrasound": 37721, "\u0120behaving": 37722, "\u0120Tara": 37723, "classes": 37724, "Virtual": 37725, "\u0120Colonial": 37726, "\u0120stripping": 37727, "\u0120orchestrated": 37728, "\u0120Graves": 37729, "452": 37730, "\u0120Ironically": 37731, "\u0120Writers": 37732, "\u0120lends": 37733, "\u0120Manz": 37734, "\u0120raven": 37735, "\u0120oxidative": 37736, "\u0120266": 37737, "ELF": 37738, "actually": 37739, "ascar": 37740, "Draft": 37741, "\u0120favourable": 37742, "\u0120humiliating": 37743, "\u0120fidelity": 37744, "\u0120Hof": 37745, "\u0120Xuan": 37746, "496": 37747, "\u0120layered": 37748, "atis": 37749, "790": 37750, "\u0120paycheck": 37751, "iton": 37752, "Kar": 37753, "\u0120VMware": 37754, "\u0120Farmer": 37755, "\u0120servic": 37756, "glomer": 37757, "\u0120slump": 37758, "\u0120Fabric": 37759, "\u0120DOC": 37760, "esting": 37761, "\u0120reassure": 37762, "\u0120phyl": 37763, "volt": 37764, "itory": 37765, "Rules": 37766, "\u0120oxidation": 37767, "\u0120prized": 37768, "\u0120mistress": 37769, "\u0120Django": 37770, "WARN": 37771, "\u00e5\u0133": 37772, "\u0120encode": 37773, "\u0120Feedback": 37774, "\u0120stupidity": 37775, "Ian": 37776, "\u0120Yugoslavia": 37777, "\u00d7\u00a8": 37778, "acl": 37779, "UTE": 37780, "1977": 37781, "\u0120qualifies": 37782, "\u0120pulses": 37783, "pretty": 37784, "\u0120froze": 37785, "\u0120ss": 37786, "Iterator": 37787, "\u0120urgently": 37788, "\u0120mailed": 37789, "\u0120Cham": 37790, "\u0120sustaining": 37791, "\u0120basil": 37792, "\u0120puppies": 37793, "ilant": 37794, "\u0120PLEASE": 37795, "lap": 37796, "aceous": 37797, "Fear": 37798, "\u0120Mastery": 37799, "automatic": 37800, "\u0120TAG": 37801, "\u0120antim": 37802, "agles": 37803, "473": 37804, "frames": 37805, "\u0120whispers": 37806, "\u0120Whoever": 37807, "\u0120bravery": 37808, "\u0120UKIP": 37809, "ractions": 37810, "\"\"\"": 37811, "\u0120tame": 37812, "\u0120parted": 37813, "everything": 37814, "CONT": 37815, "\u0120indebted": 37816, "\u0120addr": 37817, "rek": 37818, "IRED": 37819, "\u0120eminent": 37820, "clinton": 37821, "\u0120ousted": 37822, "\u0120reviewer": 37823, "\u0120meltdown": 37824, "\u0120rearr": 37825, "\u0120Yao": 37826, "thereal": 37827, "abyte": 37828, "\u0120stumbling": 37829, "\u0120batches": 37830, "\u0120259": 37831, "\u0120contraceptive": 37832, "\u0120prostitute": 37833, "ensis": 37834, "Decl": 37835, "\u0120Strikes": 37836, "Military": 37837, "\u0120Oath": 37838, "vacc": 37839, "ppings": 37840, "052": 37841, "\u0120partName": 37842, "amping": 37843, "Reports": 37844, "KI": 37845, "CHR": 37846, "\u0120subtly": 37847, "swers": 37848, "Blake": 37849, "usual": 37850, "\u0120contestants": 37851, "\u0120cartridges": 37852, "\u0120GREAT": 37853, "\u0120blush": 37854, "\u0120\u00e2\u0122\u00ba": 37855, "472": 37856, "\u0120reasoned": 37857, "\u00e3\u0125\u00a4": 37858, "paralleled": 37859, "\u0120dyn": 37860, "agate": 37861, "\u0120nightly": 37862, "\u00e5\u0128": 37863, "556": 37864, "\u0120semantic": 37865, "\u0120Advoc": 37866, "\u0120!!": 37867, "\u0120disagrees": 37868, "\u0120BW": 37869, "Veh": 37870, "\u0120harming": 37871, "\u0120embraces": 37872, "\u0120strives": 37873, "\u0120inland": 37874, "\u0120Kard": 37875, "\u0120heats": 37876, "\u0120Ginny": 37877, "utan": 37878, "ernaut": 37879, "ylene": 37880, "\u0120Elev": 37881, "JD": 37882, "\u0120hars": 37883, "\u0120Starr": 37884, "\u0120skysc": 37885, "\u0120collaborators": 37886, "Usually": 37887, "\u0120revolutions": 37888, "\u0120STATS": 37889, "\u0120dismantle": 37890, "\u0120confidently": 37891, "\u0120kinetic": 37892, "Ali": 37893, "\u0120percentile": 37894, "\u0120extracting": 37895, "illian": 37896, "estead": 37897, "\u0120physicists": 37898, "\u0120Marshal": 37899, "\u0120fellowship": 37900, "\u0120dashed": 37901, "\u0120UR": 37902, "\u0120Sioux": 37903, "\u0120Compact": 37904, "amide": 37905, "Python": 37906, "\u0120Leigh": 37907, "\u0120Pharmac": 37908, "istrates": 37909, "herical": 37910, "\u0120fue": 37911, "\u0120Emin": 37912, "\u0120({": 37913, "\u0120Neighborhood": 37914, "\u0120disrupting": 37915, "\u0120Dup": 37916, "\u0120gland": 37917, "\u0120Sev": 37918, "\u0120Marian": 37919, "argon": 37920, "\u0120Dund": 37921, "\u0120": 46904, "\u0120Philips": 46905, "\u0120Kafka": 46906, "\u0120upheaval": 46907, "\u0120sentimental": 46908, "\u0120sax": 46909, "\u0120Akira": 46910, "serial": 46911, "Matrix": 46912, "\u0120electing": 46913, "\u0120commenter": 46914, "\u0120Nebula": 46915, "plets": 46916, "\u0120Nadu": 46917, "\u0120Adren": 46918, "\u0120enshr": 46919, "\u0120RAND": 46920, "financial": 46921, "\u0120Clyde": 46922, "utherford": 46923, "\u0120signage": 46924, "\u0120deline": 46925, "\u0120phosphate": 46926, "roversial": 46927, "fascist": 46928, "\u0120Vall": 46929, "\u0120Bethlehem": 46930, "\u0120fors": 46931, "\u0120english": 46932, "Solid": 46933, "Nature": 46934, "\u0120va": 46935, "\u0120Guests": 46936, "\u0120tantal": 46937, "\u0120autoimmune": 46938, ";;;;;;;;;;;;": 46939, "\u0120Totally": 46940, "\u0120Ov": 46941, "\u0120defences": 46942, "\u0120Coconut": 46943, "\u0120tranquil": 46944, "\u0120ploy": 46945, "\u0120flavours": 46946, "\u0120Flask": 46947, "\u00e3\u0124\u00a8\u00e3\u0125\u00ab": 46948, "\u0120Weston": 46949, "\u0120Volvo": 46950, "870": 46951, "\u0120microphones": 46952, "verbal": 46953, "RPG": 46954, "\u0120iii": 46955, ";}": 46956, "028": 46957, "\u0120headlined": 46958, "\u0120primed": 46959, "\u0120hoard": 46960, "\u0120Shad": 46961, "\u0120ENTER": 46962, "\u0120triangular": 46963, "\u0120capit": 46964, "lik": 46965, "\u0120Ancients": 46966, "\u0120lash": 46967, "\u0120convol": 46968, "\u0120colonel": 46969, "enemy": 46970, "Gra": 46971, "\u0120pubs": 46972, "utters": 46973, "\u0120assigns": 46974, "\u0120Penet": 46975, "\u0120Monstrous": 46976, "\u0120Bowen": 46977, "ilver": 46978, "Haunted": 46979, "\u0120Ding": 46980, "started": 46981, "plin": 46982, "\u0120contaminants": 46983, "\u0120DOE": 46984, "ffen": 46985, "\u0120Technician": 46986, "Ry": 46987, "\u0120robbers": 46988, "\u0120hotline": 46989, "\u0120Guardiola": 46990, "\u0120Kaufman": 46991, "rower": 46992, "\u0120Dresden": 46993, "\u0120Alpine": 46994, "Elf": 46995, "\u0120fmt": 46996, "\u0120Sard": 46997, "urses": 46998, "gpu": 46999, "Unix": 47000, "\u0120unequivocally": 47001, "\u0120Citizenship": 47002, "quad": 47003, "mire": 47004, "\u0120Sweeney": 47005, "Battery": 47006, "615": 47007, "\u0120pancakes": 47008, "\u0120oats": 47009, "Maps": 47010, "\u0120Contrast": 47011, "mbudsman": 47012, "\u0120EPS": 47013, "\u0120subcommittee": 47014, "\u0120sourcing": 47015, "\u0120sizing": 47016, "\u0120Buffer": 47017, "\u0120Mandatory": 47018, "\u0120moderates": 47019, "\u0120Patterns": 47020, "\u0120Chocobo": 47021, "\u0120Zan": 47022, "\u0120STATES": 47023, "\u0120Judging": 47024, "\u0120Inher": 47025, "*:": 47026, "\u0120bil": 47027, "\u0120Yen": 47028, "\u0120exhilar": 47029, "ollower": 47030, "zers": 47031, "\u0120snug": 47032, "maximum": 47033, "\u0120despicable": 47034, "\u0120PACK": 47035, "\u0120Annex": 47036, "\u0120sarcastic": 47037, "\u0120latex": 47038, "\u0120tamp": 47039, "\u0120Sao": 47040, "bah": 47041, "\u0120Reverend": 47042, "\u0120Chinatown": 47043, "\u0120AUT": 47044, "documented": 47045, "\u0120GABA": 47046, "\u0120Canaan": 47047, "\u0120\u00d9\u0127": 47048, "\u0120governs": 47049, "prev": 47050, "Esc": 47051, "\u0120Estimates": 47052, "OSP": 47053, "\u0120endeavour": 47054, "\u0120Closing": 47055, "ometime": 47056, "everyone": 47057, "\u0120worsen": 47058, "\u0120scanners": 47059, "\u0120deviations": 47060, "\u0120Robotics": 47061, "\u0120Compton": 47062, "\u0120sorcerer": 47063, "\u0120endogenous": 47064, "\u0120emulation": 47065, "\u0120Piercing": 47066, "\u0120Aph": 47067, "\u0120Socket": 47068, "\u0120bould": 47069, "\u0120OU": 47070, "\u0120Borderlands": 47071, "\u01201863": 47072, "Gordon": 47073, "\u0120WTO": 47074, "\u0120restricts": 47075, "\u0120mosaic": 47076, "\u0120melodies": 47077, "\u00e7\u0126": 47078, "Tar": 47079, "\u0120disson": 47080, "\u0120Provides": 47081, "\u0120......": 47082, "bek": 47083, "FIX": 47084, "\u0120broom": 47085, "anship": 47086, "Doctors": 47087, "\u0120nerds": 47088, "\u0120Regions": 47089, "naissance": 47090, "\u0120mete": 47091, "\u0120crept": 47092, "plings": 47093, "\u0120girlfriends": 47094, "knit": 47095, "igent": 47096, "owe": 47097, "\u0120ushered": 47098, "\u0120Baz": 47099, "Mobil": 47100, "434": 47101, "\u0120Presents": 47102, "origin": 47103, "\u0120insomnia": 47104, "\u0120Aux": 47105, "439": 47106, "\u0120Chili": 47107, "irsch": 47108, "GAME": 47109, "\u0120gestation": 47110, "algia": 47111, "romising": 47112, "$,": 47113, "crow": 47114, "\u0120Inspection": 47115, "atomic": 47116, "Relations": 47117, "JOHN": 47118, "roman": 47119, "\u0120Clockwork": 47120, "\u0120Bakr": 47121, "mone": 47122, "MET": 47123, "\u0120thirsty": 47124, "\u0120bc": 47125, "\u0120faculties": 47126, "Rum": 47127, "\u0120nuance": 47128, "\u0120Darius": 47129, "pleting": 47130, "fters": 47131, "etchup": 47132, "Registration": 47133, "\u0120KE": 47134, "Rah": 47135, "\u0120preferential": 47136, "\u0120Lash": 47137, "\u0120HH": 47138, "Valid": 47139, "\u0120NAV": 47140, "\u0120starve": 47141, "\u0120Gong": 47142, "zynski": 47143, "\u0120Actress": 47144, "\u0120wik": 47145, "\u0120unaccompanied": 47146, "lvl": 47147, "Bride": 47148, "ADS": 47149, "\u0120Commando": 47150, "\u0120Vaughn": 47151, "Wallet": 47152, "\u0120hopping": 47153, "\u0120Vie": 47154, "\u0120caveats": 47155, "\u0120alas": 47156, "ifled": 47157, "abuse": 47158, "661": 47159, "\u0120ibn": 47160, "\u0120gul": 47161, "\u0120robbing": 47162, "til": 47163, "ILA": 47164, "\u0120mitigating": 47165, "\u0120aptly": 47166, "\u0120tyrant": 47167, "\u0120midday": 47168, "\u0120Gilmore": 47169, "\u0120Decker": 47170, "\u0120\u00c2\u00a7\u00c2\u00a7": 47171, "partial": 47172, "Exactly": 47173, "\u0120phenotype": 47174, "\u0120[+]": 47175, "\u0120Plex": 47176, "\u0120Ips": 47177, "versions": 47178, "\u0120ebook": 47179, "\u0120chic": 47180, "gross": 47181, "\":\"\"},{\"": 47182, "\u0120Surprisingly": 47183, "Morgan": 47184, "\u0120residues": 47185, "\u0120Confederation": 47186, "infeld": 47187, "\u0120lyr": 47188, "moderate": 47189, "\u0120perpendicular": 47190, "VK": 47191, "\u0120synchronized": 47192, "\u0120refreshed": 47193, "\u0120adore": 47194, "\u0120Torment": 47195, "olina": 47196, "\u01202600": 47197, "ItemTracker": 47198, "\u0120pies": 47199, "\u0120FAT": 47200, "\u0120RHP": 47201, "048": 47202, "\u0120RESP": 47203, "\u0120BJ": 47204, "allows": 47205, "Pand": 47206, "\u0120unwelcome": 47207, "\u0120Voc": 47208, "\u0120Bastard": 47209, "\u0120OW": 47210, "\u0120LAR": 47211, "\u0120Healer": 47212, "Environmental": 47213, "\u0120Kenyan": 47214, "\u0120Trance": 47215, "\u0120Pats": 47216, "\u0120aliases": 47217, "\u0120Garfield": 47218, "\u0120campaigner": 47219, "\u0120advancements": 47220, "\u0120Okinawa": 47221, "\u0120Coh": 47222, "owsky": 47223, "\u0120starved": 47224, "\u0120sizeable": 47225, "\u0120:-)": 47226, "\u0120mRNA": 47227, "\u0120suspensions": 47228, "istar": 47229, "Scotland": 47230, "Prin": 47231, "------------------------------------------------": 47232, "\u0120502": 47233, "\u0120teaspoons": 47234, "\u01201050": 47235, "\u0120coercive": 47236, "\u0120Masonic": 47237, "edded": 47238, "\u0120Passenger": 47239, "\u0120latt": 47240, "\u0120braces": 47241, "\u0120Steal": 47242, "\u0120NYT": 47243, "\u0120Kats": 47244, "\u0120Celest": 47245, "aez": 47246, "Tu": 47247, "\u0120Coulter": 47248, "\u00f0\u0141\u013a": 47249, "Flickr": 47250, "\u0120Wilmington": 47251, "iths": 47252, "++;": 47253, "\u0120vending": 47254, "\u0120negro": 47255, "\u0120Phi": 47256, "\u0120Yellowstone": 47257, "Callback": 47258, "\u0120shampoo": 47259, "\u0120Shades": 47260, "wat": 47261, "\u0120superhuman": 47262, "\u0120ridiculed": 47263, "\u0120holiest": 47264, "ombo": 47265, "\u0120interns": 47266, "\u0120hone": 47267, "\u0120Paragu": 47268, "URI": 47269, "\u0120dangling": 47270, "\u00e3\u0124\u00bb": 47271, "sov": 47272, "ictional": 47273, "availability": 47274, "\u0120revocation": 47275, "\u0120dow": 47276, "inic": 47277, "\u0120THEIR": 47278, "\u0120iso": 47279, "\u0120outings": 47280, "\u0120Lethal": 47281, "\u0120)))": 47282, "\u0120inaccur": 47283, "\u0120outlandish": 47284, "\u0120anus": 47285, "letico": 47286, "idon": 47287, "lol": 47288, "\u0120unregulated": 47289, "\u0120succumbed": 47290, "\u0120cuff": 47291, "\u0120Wasteland": 47292, "letal": 47293, "\u0120substr": 47294, "\u0120coffers": 47295, "\u0120automakers": 47296, "ovi": 47297, "\u0120Xue": 47298, "\u0120Daytona": 47299, "\u0120jarring": 47300, "\u0120fumes": 47301, "\u0120disbanded": 47302, "zik": 47303, "itton": 47304, "\u0120strikingly": 47305, "\u0120spores": 47306, "Adapter": 47307, ".):": 47308, "\u0120Lyndon": 47309, "ivalry": 47310, "\u0120orally": 47311, "\u0120tumultuous": 47312, "\u0120displeasure": 47313, "\u0120cones": 47314, "orrect": 47315, "\u0120appease": 47316, "\u0120derby": 47317, "\u0120Tripoli": 47318, "\u0120Aless": 47319, "\u0120poked": 47320, "\u0120Guilty": 47321, "vP": 47322, "Enough": 47323, "\u0120originals": 47324, "699": 47325, "\u0120rabbi": 47326, "\u0120proverbial": 47327, "\u0120postpone": 47328, "elope": 47329, "\u0120Misty": 47330, "\u0120staffed": 47331, "\u0120Unemployment": 47332, "reditary": 47333, "\u0120diligent": 47334, "recomm": 47335, "measures": 47336, "asin": 47337, "825": 47338, "\u0120ponds": 47339, "\u0120mmol": 47340, "\u0120SAR": 47341, "\u0120CARE": 47342, "\u0120371": 47343, "\u0120clenched": 47344, "\u0120Corsair": 47345, "\u0120caricature": 47346, "zn": 47347, "attach": 47348, "\u0120Schro": 47349, "speak": 47350, "painted": 47351, "\u0120Suc": 47352, "\u0120ENT": 47353, "\u0120cellul": 47354, "\u0120Paid": 47355, "diagn": 47356, "WHERE": 47357, "\u0120texted": 47358, "Barn": 47359, "\u0120retracted": 47360, "\u0120Referred": 47361, "Sav": 47362, "\u0120upkeep": 47363, "\u0120workplaces": 47364, "\u0120Tokens": 47365, "\u0120amplify": 47366, "clinical": 47367, "\u0120multic": 47368, "mberg": 47369, "\u0120convoluted": 47370, "Region": 47371, "565": 47372, "\u0120Topic": 47373, "\u0120snail": 47374, "\u0120saline": 47375, "\u0120insurrection": 47376, "\u0120Petr": 47377, "forts": 47378, "BAT": 47379, "\u0120Navajo": 47380, "\u0120rudimentary": 47381, "\u0120Laksh": 47382, "ONDON": 47383, "Measure": 47384, "\u0120transformer": 47385, "\u0120Goddard": 47386, "\u0120coincides": 47387, "irin": 47388, "Rex": 47389, "\u0120Bok": 47390, "quit": 47391, "\u0120shotguns": 47392, "\u0120proletarian": 47393, "\u0120scorp": 47394, "\u0120Ada": 47395, "514": 47396, "\u0120slander": 47397, "recorded": 47398, "\u0120embell": 47399, "risome": 47400, "\u0120apologizing": 47401, "\u0120Mulcair": 47402, "\u0120Gibraltar": 47403, "Cla": 47404, "\u0120allot": 47405, "\u0120Attention": 47406, "\u0120433": 47407, "leave": 47408, "\u0120whine": 47409, "\u0120Issa": 47410, "\u0120Faust": 47411, "\u0120Barron": 47412, "heny": 47413, "\u0120victimized": 47414, "Jews": 47415, "\u0120nurturing": 47416, "ettel": 47417, "Winged": 47418, "\u0120Subtle": 47419, "\u0120flavorful": 47420, "\u0120Reps": 47421, "enged": 47422, "callback": 47423, "\u0120directional": 47424, "\u0120clasp": 47425, "\u0120Directions": 47426, "planet": 47427, "iculture": 47428, "Helper": 47429, "icion": 47430, "acia": 47431, "\u0120\u00e7\u00a5\u0140": 47432, "\u0120surges": 47433, "\u0120canoe": 47434, "\u0120Premiership": 47435, "been": 47436, "\u0120defied": 47437, "\u0120Trooper": 47438, "\u0120tripod": 47439, "\u0120gasp": 47440, "\u0120Euph": 47441, "\u0120Ads": 47442, "vernight": 47443, "highly": 47444, "Role": 47445, "\u0120entangled": 47446, "\u0120Zeit": 47447, "618": 47448, "\u0120Rusty": 47449, "\u0120havens": 47450, "\u0120Vaughan": 47451, "HAEL": 47452, "\u0120SERVICE": 47453, "/,": 47454, "\u0120stricken": 47455, "\u0120delusions": 47456, "\u0120bis": 47457, "\u0120Haf": 47458, "\u0120gratification": 47459, "\u0120enticing": 47460, "UNCH": 47461, "Adams": 47462, "\u0120OLED": 47463, "\u0120Beetle": 47464, "\u01201899": 47465, "\u0120SOFTWARE": 47466, "ategor": 47467, "VL": 47468, "\u0120Totem": 47469, "\u0120Gators": 47470, "ATURES": 47471, "\u0120impedance": 47472, "Registered": 47473, "\u0120Cary": 47474, "\u0120Aerial": 47475, "onne": 47476, "enium": 47477, "\u0120dred": 47478, "\u0120Beg": 47479, "\u0120concurrently": 47480, "\u0120superpower": 47481, "\u0120Xan": 47482, "jew": 47483, "imester": 47484, "\u0120Dickinson": 47485, "\u00e2\u0136\u0123": 47486, "Fla": 47487, "\u0120pree": 47488, "\u0120Rollins": 47489, "\u00a9\u00b6\u00e6": 47490, "\u0120denomination": 47491, "\u0120Lana": 47492, "516": 47493, "\u0120inciting": 47494, "scribed": 47495, "juries": 47496, "\u0120Wonders": 47497, "approximately": 47498, "\u0120suspending": 47499, "\u0120mountainous": 47500, "\u0120Laugh": 47501, "oidal": 47502, "Ns": 47503, "Detect": 47504, ")=": 47505, "\u0120Luthor": 47506, "\u0120Schwarzenegger": 47507, "\u0120Muller": 47508, "\u0120Devi": 47509, "ecycle": 47510, "Jar": 47511, "613": 47512, "\u0120Longh": 47513, "Bah": 47514, "\u0120SPORTS": 47515, "nw": 47516, "\u0120refinement": 47517, "\u0120waterways": 47518, "\u0120diner": 47519, "Blade": 47520, "683": 47521, "Fac": 47522, "\u0120initials": 47523, "\u0120rog": 47524, "\u0120paranormal": 47525, "BUT": 47526, "\u0120[(": 47527, "\u0120Swanson": 47528, "\u0120Mesh": 47529, "\u00e2\u0138\u00ac": 47530, "Improve": 47531, "\u0120Radiation": 47532, "\u0120Esther": 47533, "\u0120Esk": 47534, "\u0120Aly": 47535, "iky": 47536, "\u0120irrad": 47537, "\u0120Buckingham": 47538, "\u0120refill": 47539, "\u0120._": 47540, "Repe": 47541, "CONCLUS": 47542, "\u0120differentiated": 47543, "\u0120chirop": 47544, "\u0120Atkins": 47545, "Pattern": 47546, "\u0120excise": 47547, "\u0120cabal": 47548, "NSA": 47549, "\u0120STA": 47550, "\u0120SIL": 47551, "\u0120Paraly": 47552, "\u0120rye": 47553, "\u0120Howell": 47554, "\u0120Countdown": 47555, "nesses": 47556, "alysed": 47557, "\u0120resize": 47558, "\u00e3\u0124\u00bd": 47559, "\u0120budgetary": 47560, "\u0120Stras": 47561, "wang": 47562, "\u0120apiece": 47563, "\u0120precincts": 47564, "\u0120peach": 47565, "\u0120skyline": 47566, "\u0120353": 47567, "popular": 47568, "Appearances": 47569, "\u0120Mechanics": 47570, "\u0120DevOnline": 47571, "Sullivan": 47572, "Zen": 47573, "\u0120pu": 47574, "opolis": 47575, "544": 47576, "\u0120deform": 47577, "\u0120counteract": 47578, "\u0120Lange": 47579, "\u0120417": 47580, "Console": 47581, "774": 47582, "\u0120nodding": 47583, "\u0120populism": 47584, "\u0120hep": 47585, "\u0120counselling": 47586, "compliance": 47587, "UFF": 47588, "\u0120undeniably": 47589, "\u0120railing": 47590, "\u0120Horowitz": 47591, "\u0120Simone": 47592, "\u0120Bungie": 47593, "\u0120ak": 47594, "\u0120Talks": 47595, "xff": 47596, "flake": 47597, "Crash": 47598, "\u0120sweaty": 47599, "\u0120banquet": 47600, "\u0120OFFIC": 47601, "\u0120inventive": 47602, "\u0120astronomer": 47603, "\u0120Stamford": 47604, "\u0120Scare": 47605, "\u0120GREEN": 47606, "olicited": 47607, "\u0120rusher": 47608, "\u0120centrist": 47609, "ighting": 47610, "\u0120subclass": 47611, "\u0120disav": 47612, "\u0120defund": 47613, "\u0120Nanto": 47614, "ociate": 47615, "mast": 47616, "\u0120pacif": 47617, "\u0120mend": 47618, "eers": 47619, "immigration": 47620, "ESSION": 47621, "\u0120numbering": 47622, "\u0120laughable": 47623, "\u0120Ended": 47624, "viation": 47625, "emark": 47626, "Pitt": 47627, "\u0120meticulous": 47628, "\u0120LF": 47629, "\u0120congratulated": 47630, "\u0120Birch": 47631, "\u0120swayed": 47632, "\u0120semifinals": 47633, "\u0120humankind": 47634, "matter": 47635, "\u0120Equip": 47636, "opausal": 47637, "Said": 47638, "\u0120Layout": 47639, "\u0120voicing": 47640, "\u0120thug": 47641, "\u0120pornographic": 47642, "IPS": 47643, "\u0120moaning": 47644, "\u0120grievance": 47645, "\u0120confessions": 47646, "escal": 47647, "TEXTURE": 47648, "Authent": 47649, "osaurus": 47650, "Purchase": 47651, "\u0120relegation": 47652, "alter": 47653, "\u0120\u00c2\u0142\u00c2\u0142": 47654, "\u0120riddled": 47655, "\u0120ogre": 47656, "\u0120Lowell": 47657, "Occup": 47658, "Eat": 47659, "\u0120Hyder": 47660, "\u0120Adviser": 47661, "Commerce": 47662, "Hunt": 47663, "\u0120Orth": 47664, "\u0120Competitive": 47665, "\u0120CLA": 47666, "CDC": 47667, "\u0120salads": 47668, "Fle": 47669, "\u0120industrialized": 47670, "`,": 47671, "\u0120OWN": 47672, "\u0120beck": 47673, "\u0120Particularly": 47674, "oubt": 47675, "\u0120mM": 47676, "\u0120Hussain": 47677, "\u0120Chennai": 47678, "\u0120920": 47679, "\u0120appointing": 47680, "\u0120Cullen": 47681, ",,,,,,,,": 47682, "\u0120pores": 47683, "verified": 47684, "\u0120biochemical": 47685, "emate": 47686, "\u0120cowardly": 47687, "\u0120Helsinki": 47688, "\u0120Ethiopian": 47689, "SOURCE": 47690, "ERC": 47691, "estro": 47692, "\u0120biotech": 47693, "\u0120Sour": 47694, "\u0120brewer": 47695, "Bloomberg": 47696, "\u0120intensify": 47697, "Glass": 47698, "anco": 47699, "\u0120FDR": 47700, "greSQL": 47701, "\u0120Fires": 47702, "\u00a9\u00b6\u00e6\u00a5\u00b5": 47703, "eco": 47704, "1001": 47705, "\u0120Homeless": 47706, "\u0120instantaneous": 47707, "\u0120Haste": 47708, "igel": 47709, "Diamond": 47710, "\u0120paving": 47711, "\u0120landfill": 47712, "\u0120dads": 47713, "houn": 47714, ":]": 47715, "\u0120incendiary": 47716, "\u0120Livingston": 47717, "\u0120Hilbert": 47718, "\u0120Checks": 47719, "styles": 47720, "inators": 47721, "\u0120Clive": 47722, "phrine": 47723, "\u0120chimpanzees": 47724, "\u0120pall": 47725, "\u0120JM": 47726, "\u0120Aadhaar": 47727, "\u00f0\u013f": 47728, "\u0120achievable": 47729, "disabled": 47730, "PET": 47731, "OOOOOOOO": 47732, "Mot": 47733, "\u0120intangible": 47734, "\u0120ballet": 47735, "\u0120Webs": 47736, "\u0120Estimated": 47737, "Effects": 47738, "\u0120bailed": 47739, "Joshua": 47740, "\u0120turbulence": 47741, "\u0120occupant": 47742, "\u0120Daylight": 47743, "\u0120361": 47744, "meet": 47745, "\u0120statically": 47746, "\u0120onlook": 47747, "\u0120ki": 47748, "illegal": 47749, "\u0120velvet": 47750, "\u0120dehydration": 47751, "\u0120acquies": 47752, "\u0120Rez": 47753, "akura": 47754, "\u0120Upton": 47755, "atro": 47756, "\u0120incomprehensible": 47757, "\u0120backdoor": 47758, "\u0120Rhino": 47759, "727": 47760, "\u0120maths": 47761, ")+": 47762, "\u0120heresy": 47763, "\u0120df": 47764, "\u0120Roche": 47765, "\u0120Lydia": 47766, "\u0120pancreat": 47767, "reply": 47768, "arrell": 47769, "\u0120solicitation": 47770, "\u0120circadian": 47771, "BIP": 47772, "\u0120foray": 47773, "\u0120cryptic": 47774, "izu": 47775, "imeo": 47776, "\u0120Tomato": 47777, "\u0120Homs": 47778, "examination": 47779, "\u0120quarry": 47780, "\u0120Valiant": 47781, "\u0120Jericho": 47782, "\u0120INCLUD": 47783, "\u01201840": 47784, "519": 47785, "\u0120resists": 47786, "\u0120snapshots": 47787, "\u0120Spur": 47788, "\u0120Antiqu": 47789, "Login": 47790, "\u0120bestselling": 47791, "\u0120antic": 47792, "\u0120Sutherland": 47793, "\u00e3\u0124\u00a2\u00e3\u0125\u00ab": 47794, "\u0120~/": 47795, "\u0120Parm": 47796, "\u00e8\u0125": 47797, "Pages": 47798, "intensity": 47799, "\u0120immobil": 47800, "\u01201865": 47801, "zzo": 47802, "\u0120nifty": 47803, "\u0120fentanyl": 47804, "\u0120Preservation": 47805, "ophen": 47806, "\u0120darts": 47807, "\u0120Dinosaur": 47808, "pointers": 47809, "\u0120Rite": 47810, "suggest": 47811, "awareness": 47812, "\u0120Sheridan": 47813, "\u0120stances": 47814, "\u0120sorcery": 47815, "\u0120perjury": 47816, "\u0120Nikola": 47817, "iever": 47818, "\u0120fiance": 47819, "\u0120Jordanian": 47820, "\u0120Balloon": 47821, "\u0120nab": 47822, "\u0120kb": 47823, "\u0120humanities": 47824, "\u0120Tanaka": 47825, "hillary": 47826, "\u0120consultancy": 47827, "\u0120Zub": 47828, "\u0120remission": 47829, "\u0120confid": 47830, "CHQ": 47831, "\u0120Fug": 47832, "\u0120improvis": 47833, "Yep": 47834, "/_": 47835, "\u0120unwillingness": 47836, "\u0120portfolios": 47837, "055": 47838, "\u0120Instructor": 47839, "aiman": 47840, "\u0120claimants": 47841, "Mbps": 47842, "\u0120Bye": 47843, "received": 47844, "Tweet": 47845, "\u0120indemn": 47846, "riz": 47847, "amara": 47848, "Nat": 47849, "\u0120evaluates": 47850, "\u0120Lur": 47851, "epad": 47852, "FOX": 47853, "\u0120Thro": 47854, "\u0120rusty": 47855, "\u0120bedrock": 47856, "\u0120Oprah": 47857, "JB": 47858, "\u0120manipulative": 47859, "\u0120willful": 47860, "\u0120relapse": 47861, "\u0120extant": 47862, "Theme": 47863, "Sensor": 47864, "\u0120Stability": 47865, "govern": 47866, "\u0120poppy": 47867, "\u0120knack": 47868, "\u0120insulated": 47869, "\u0120Tile": 47870, "\u0120Extrem": 47871, "\u0120untold": 47872, "\u0120converge": 47873, "\u0120refuel": 47874, "igroup": 47875, "\u0120distortions": 47876, "\u0120ravaged": 47877, "\u0120mechanically": 47878, "\u0120Reilly": 47879, "\u0120Nose": 47880, "\u0120Incarnation": 47881, "\u0120Becky": 47882, "abbling": 47883, "\u0120taco": 47884, "\u0120rake": 47885, "\u0120melancholy": 47886, "\u0120illustrious": 47887, "\u0120Dartmouth": 47888, "Guide": 47889, "\u0120Razer": 47890, "\u0120Benz": 47891, "Ultimate": 47892, "\u0120Surprise": 47893, "\u0120pageant": 47894, "offer": 47895, "Whoever": 47896, "\u0120wiser": 47897, "\u0120chemist": 47898, "\u0120HELL": 47899, "\u0120Bulk": 47900, "\u0120plutonium": 47901, "\u0120COVER": 47902, "\u00d6\u00bc": 47903, "failed": 47904, "\u0120tirelessly": 47905, "\u0120infertility": 47906, "\u0120Trident": 47907, "\u0120Showtime": 47908, "\u0120Civ": 47909, "Vice": 47910, "requires": 47911, "ittance": 47912, "\u0120uncontrolled": 47913, "interesting": 47914, "561": 47915, "\u0120innovate": 47916, "ategic": 47917, "Lie": 47918, "\u0120Selling": 47919, "Ul": 47920, "\u0120savior": 47921, "\u0120Tosh": 47922, "\u0120swast": 47923, "PASS": 47924, "\u0120rink": 47925, "\u0120cardio": 47926, "\u0120Iro": 47927, "udi": 47928, "\u0120vantage": 47929, "\u0120vans": 47930, "\u0120Ni\u00c3\u00b1o": 47931, "+=": 47932, "\u0120propagate": 47933, "": 49029, "\u0120leukemia": 49030, "\u0120eluc": 49031, "\u0120announcer": 49032, "\u0120Lithuan": 49033, "\u0120Armageddon": 49034, "\u00e5\u0129": 49035, "Lenin": 49036, "\u0120Ruk": 49037, "\u0120pepp": 49038, "\u0120Romantic": 49039, "\u0120PIT": 49040, "\u0120Interstellar": 49041, "\u0120Atkinson": 49042, "Raid": 49043, "Js": 49044, "Goal": 49045, "Course": 49046, "\u0120vanishing": 49047, "esley": 49048, "\u0120Rounds": 49049, "Elsa": 49050, "593": 49051, "\u0120redundancy": 49052, "\u0120STAND": 49053, "\u0120prophetic": 49054, "\u0120habitable": 49055, "ryu": 49056, "\u0120faintly": 49057, "MODE": 49058, "\u0120flanked": 49059, "IRC": 49060, "Awesome": 49061, "\u0120spurious": 49062, "\u0120Zah": 49063, "\u0120MSG": 49064, "\u0120shading": 49065, "\u0120motivational": 49066, "\u0120Santana": 49067, "\u0120SPR": 49068, "\u0120excruciating": 49069, "omial": 49070, "\u0120Miko": 49071, "\u0120Leopard": 49072, "Abyss": 49073, "\u0120[|": 49074, "dirty": 49075, "\u0120baths": 49076, "\u0120demoral": 49077, "andre": 49078, "PB": 49079, "\u0120unification": 49080, "\u0120sacrament": 49081, "\u0120[&": 49082, "\u0120priceless": 49083, "\u0120gelatin": 49084, "\u0120emanating": 49085, "\u0120Allaah": 49086, "986": 49087, "\u0120outburst": 49088, "\u0120eras": 49089, "\u0120XVI": 49090, "\u0120SPI": 49091, "Ott": 49092, "\u0120Lazarus": 49093, "PLIED": 49094, "Flying": 49095, "blogs": 49096, "Wisconsin": 49097, "Raven": 49098, "\u0120rebate": 49099, "\u0120creeps": 49100, "\u0120Span": 49101, "\u0120Painter": 49102, "\u0120Kira": 49103, "\u0120Amos": 49104, "\u0120Corvette": 49105, "Consumer": 49106, "\u0120Recover": 49107, "cki": 49108, "\u0120pesky": 49109, "\u0120Invention": 49110, "Companies": 49111, "\u0120challengers": 49112, "ademic": 49113, "\u0120Ukrainians": 49114, "\u0120Neurolog": 49115, "\u0120Forsaken": 49116, "\u0120entrants": 49117, "\u0120embattled": 49118, "\u0120defunct": 49119, "\u0120Glacier": 49120, "\u0120poisons": 49121, "\u0120Horses": 49122, "makes": 49123, "\u0120Dirt": 49124, "\u0120423": 49125, "hhh": 49126, "\u0120Transformation": 49127, "QUIRE": 49128, "..................": 49129, "\u0120traveller": 49130, "\u0120Sexy": 49131, "\u0120Kern": 49132, "ipolar": 49133, "\u0120ransomware": 49134, "oooooooooooooooo": 49135, "Ec": 49136, "ruby": 49137, "Professional": 49138, "\u0120Outbreak": 49139, "argument": 49140, "Grey": 49141, "\u0120Fifa": 49142, "\u0120CHO": 49143, "\u0120FORM": 49144, "\u0120Amtrak": 49145, "-[": 49146, "\u0120cradle": 49147, "\u0120antioxidants": 49148, "\u00e3\u0123\u00ae\u00e5\u00ae": 49149, "736": 49150, "\u0120NASL": 49151, "\u0120Contributions": 49152, "Indiana": 49153, "\u0120STEP": 49154, "CSS": 49155, "\u0120salient": 49156, "\u0120allocations": 49157, "yrights": 49158, "\u0120mashed": 49159, "\u0120Cutter": 49160, "Sexual": 49161, "\u0120pounded": 49162, "\u0120fanbase": 49163, "\u0120casc": 49164, "\u0120Transparency": 49165, "\u0120analytic": 49166, "\u0120Summoner": 49167, "\u00d7\u0140": 49168, "\u0120ADC": 49169, "detail": 49170, "\u0120vanquished": 49171, "\u0120crabs": 49172, "arie": 49173, "Destroy": 49174, "\u0120Sack": 49175, "\u0120transistor": 49176, "Alabama": 49177, "\u0120Koen": 49178, "\u0120Fisheries": 49179, "cone": 49180, "\u0120annexed": 49181, "\u0120MGM": 49182, "esa": 49183, "\u0120faked": 49184, "\u0120Congratulations": 49185, "\u0120hindered": 49186, "\u0120correctional": 49187, "\u0120ITV": 49188, "leeve": 49189, "\u0120inappropriately": 49190, "licks": 49191, "\u0120trespass": 49192, "\u0120paws": 49193, "\u0120negotiator": 49194, "\u0120Christensen": 49195, "limits": 49196, "\u0120Dianne": 49197, "\u0120elegance": 49198, "\u0120Contracts": 49199, "anke": 49200, "Obj": 49201, "\u0120vigilance": 49202, "\u0120castles": 49203, "\u0120NAD": 49204, "\u0120Holo": 49205, "\u0120emphatically": 49206, "\u0120Titus": 49207, "\u0120Serving": 49208, "\u0120Richie": 49209, "\u0120Pigs": 49210, "568": 49211, "\u0120animosity": 49212, "\u0120Attributes": 49213, "\u0120Uriel": 49214, "MQ": 49215, "myra": 49216, "\u0120Applicant": 49217, "\u0120psychiatrists": 49218, "\u0120Vij": 49219, "\u0120Abby": 49220, "agree": 49221, "Push": 49222, "\u0120kWh": 49223, "hiba": 49224, "\u0120incite": 49225, "\u0120Weasley": 49226, "\u0120Taxi": 49227, "ministic": 49228, "hyper": 49229, "\u0120Farn": 49230, "\u0120601": 49231, "\u0120Nationwide": 49232, "Fake": 49233, "952": 49234, "\u0120maize": 49235, "\u0120interacted": 49236, "\u0120transitioned": 49237, "\u0120parasitic": 49238, "\u0120harmonic": 49239, "\u0120decaying": 49240, "\u0120baseless": 49241, "nsics": 49242, "\u0120transpired": 49243, "\u0120abundantly": 49244, "\u0120Forensic": 49245, "\u0120treadmill": 49246, "\u0120Jav": 49247, "aband": 49248, "\u0120sshd": 49249, "\u0120frontman": 49250, "\u0120Jakarta": 49251, "oller": 49252, "drops": 49253, "\u0120SERVICES": 49254, "romptu": 49255, "ophical": 49256, "hospital": 49257, "bledon": 49258, "645": 49259, "\u0120midrange": 49260, "\u0120EVENT": 49261, "culated": 49262, "rawled": 49263, "\u0120perched": 49264, "\u0120overboard": 49265, "\u0120Peel": 49266, "\u0120Pwr": 49267, "\u0120Carth": 49268, "\u0120COMPLE": 49269, "coe": 49270, "shall": 49271, "\u0120deterrence": 49272, "METHOD": 49273, "\u0120Absent": 49274, "MEN": 49275, "\u0120sill": 49276, "\u0120LEVEL": 49277, "York": 49278, "\u0120sinners": 49279, "\u0120OPEC": 49280, "\u0120Nur": 49281, "\u0120Designs": 49282, "selection": 49283, "\u0120unworthy": 49284, "CHA": 49285, "\u0120strengthens": 49286, "883": 49287, "edly": 49288, "\u0120slicing": 49289, "\u0120malnutrition": 49290, "\u0120filmmaking": 49291, "\u0120Polk": 49292, "urated": 49293, "\u0120421": 49294, "breakers": 49295, "!'\"": 49296, "\u0120wetlands": 49297, "\u0120Discrimination": 49298, "\u0120allowable": 49299, "\u0120steered": 49300, "\u0120Sicily": 49301, "SAM": 49302, "\u0120mustache": 49303, "\u0120mids": 49304, "\u0120clipped": 49305, "\u0120circulate": 49306, "\u0120brittle": 49307, "\u0120Buildings": 49308, "raised": 49309, "\u0120Roundup": 49310, "\u0120wealthier": 49311, "\u0120overwrite": 49312, "\u0120overpowered": 49313, "\u0120Gerrard": 49314, "sites": 49315, "PDATED": 49316, "\u0120acutely": 49317, "\u0120Gamble": 49318, "\u0120pim": 49319, "\u0120Kus": 49320, "Typically": 49321, "Deploy": 49322, "\u0120Moroccan": 49323, "potion": 49324, "combe": 49325, "\u0120vigilante": 49326, "\u0120363": 49327, "Stew": 49328, "\u0120Bagg": 49329, "\u0120resided": 49330, "\u0120Spo": 49331, "\u0120remnant": 49332, "\u0120emptiness": 49333, "brainer": 49334, "\u0120outpatient": 49335, "priority": 49336, "\u0120leptin": 49337, "\u0120Payton": 49338, "\u0120Gleaming": 49339, "\u0120Shed": 49340, "\u0120Polo": 49341, "\u0120Mormonism": 49342, "restricted": 49343, "arlane": 49344, "wx": 49345, "\u0120creatine": 49346, "\u0120Anon": 49347, "\u0120STUD": 49348, "\u0120JUL": 49349, "\u0120Tee": 49350, "528": 49351, "089": 49352, "\u0120hatched": 49353, "Dispatch": 49354, "\u0120Composite": 49355, "\u0120451": 49356, "puff": 49357, "\u0120XCOM": 49358, "\u0120Orn": 49359, "\u0120THANK": 49360, "ENDED": 49361, "\u0120Asheville": 49362, "\u0120\u00c3\u013e": 49363, "\u0120mango": 49364, "\u0120Slightly": 49365, "worldly": 49366, "\u0120Wander": 49367, "\u0120Expand": 49368, "\u0120Chr": 49369, "Mist": 49370, "\u0120orthodoxy": 49371, "\u0120UNESCO": 49372, "regate": 49373, "Elsewhere": 49374, "kie": 49375, "irled": 49376, "\u0120topple": 49377, "\u0120adoptive": 49378, "\u0120Legs": 49379, "dress": 49380, "\u0120Sagan": 49381, "bare": 49382, "\u0120Glou": 49383, "Crunch": 49384, "\u0120helpers": 49385, "\u0120chronically": 49386, "\u0120Huma": 49387, "10000": 49388, "\u0120accommodating": 49389, "\u00e4\u00ba\u0136": 49390, "\u0120wrinkles": 49391, "\u0120dodged": 49392, "fourth": 49393, "\u0120precon": 49394, "\u0120compressor": 49395, "\u0120Kare": 49396, "\u0120evict": 49397, "\u0120Warwick": 49398, "imar": 49399, "\u0120modernization": 49400, "\u0120bandwagon": 49401, "\u0120refuted": 49402, "\u0120netted": 49403, "\u0120Naples": 49404, "\u0120Genie": 49405, "perors": 49406, "\u0120fielded": 49407, "\u0120dere": 49408, "\u0120Parables": 49409, "lees": 49410, "\u0120trout": 49411, "aspers": 49412, "\u0120nihil": 49413, "\u0120happiest": 49414, "\u0120floppy": 49415, "\u0120Loft": 49416, "\u0120Heard": 49417, "\u0120unison": 49418, "\u0120lug": 49419, "\u0120Redmond": 49420, "classic": 49421, "Supporters": 49422, "SHIP": 49423, "GMT": 49424, "\u0120fuelled": 49425, "\u00e7\u0132": 49426, "\u0120dd": 49427, "\u0120Eminem": 49428, "\u01201897": 49429, "NYSE": 49430, "\u0120secretaries": 49431, "\u0120FIA": 49432, "\u0120Canaveral": 49433, "Favorite": 49434, "\u0120pomp": 49435, "\u0120detainee": 49436, "ership": 49437, "aimon": 49438, "iour": 49439, "\u0120Apex": 49440, "\u0120plantations": 49441, "amia": 49442, "acion": 49443, "Rust": 49444, "\u0120towed": 49445, "\u0120Truly": 49446, "577": 49447, "\u0120sheltered": 49448, "rider": 49449, "Wo": 49450, "\u0120lair": 49451, "\u0120Intelligent": 49452, "improve": 49453, "matically": 49454, "\u0120etiquette": 49455, "adra": 49456, "allo": 49457, "\u0120Juno": 49458, "anything": 49459, "\u0120Struggle": 49460, "\u0120Predict": 49461, "\u0120Grimes": 49462, "\u0120AMERICA": 49463, "ctx": 49464, "\u0120Situation": 49465, "WOOD": 49466, "\u0120soluble": 49467, "meier": 49468, "\u0120intolerable": 49469, "angering": 49470, "\u0120uninterrupted": 49471, "\u0120tooltip": 49472, "\u0120interrogated": 49473, "\u0120gunned": 49474, "\u0120Sneak": 49475, "\u00e6\u0143\u00a6": 49476, "\u0120tether": 49477, "\u0120crumble": 49478, "Lens": 49479, "\u0120clustered": 49480, "\u0120Syl": 49481, "\u0120Hasan": 49482, "\u0120dystopian": 49483, "wana": 49484, "\u0120joystick": 49485, "\u0120Thib": 49486, "ammu": 49487, "Tomorrow": 49488, "546": 49489, "\u0120overcame": 49490, "\u0120minimized": 49491, "ceptor": 49492, "Runner": 49493, "ENGTH": 49494, "\u0120Brenda": 49495, "\u0120Achievements": 49496, "\u0120torches": 49497, "\u0120rapport": 49498, "\u0120Investigator": 49499, "\u0120Handling": 49500, "relation": 49501, "grey": 49502, "815": 49503, "\u0120kcal": 49504, "\u0120Commands": 49505, "dq": 49506, "\u0120curls": 49507, "\u0120bearer": 49508, "\u0120cynicism": 49509, "itri": 49510, "\u0120Useful": 49511, "Bee": 49512, "DCS": 49513, "\u0120abras": 49514, "Pract": 49515, "BILITIES": 49516, "712": 49517, "\u0120debugger": 49518, "\u0120debtor": 49519, "\u0120Lia": 49520, "\u0120Kers": 49521, "\u0120exacerbate": 49522, "\u0120Stacy": 49523, "\u0120Bland": 49524, "\u0120Scenes": 49525, "\u0120branching": 49526, "\u00e2\u0138\u012a\u00e2\u0138\u012a\u00e2\u0138\u012a\u00e2\u0138\u012a\u00e2\u0138\u012a\u00e2\u0138\u012a\u00e2\u0138\u012a\u00e2\u0138\u012a": 49527, "apeake": 49528, "\u0120salsa": 49529, "\u0120mishand": 49530, "\u0120Konami": 49531, "\u0120Nib": 49532, "\u0120anecdote": 49533, "\u0120agreeable": 49534, "\u00cf\u012b": 49535, "\u0120Nathaniel": 49536, "\u0120Heisman": 49537, "\u0120Beware": 49538, "\u01201886": 49539, "spective": 49540, "691": 49541, "522": 49542, "\u0120inhibits": 49543, "\u0120hashing": 49544, "\u01201889": 49545, "\u00e5\u00b0\u0128": 49546, "vich": 49547, "Pure": 49548, "\u0120solidly": 49549, "\u0120aspirin": 49550, "imaru": 49551, "\u0120streetcar": 49552, "\u0120UCS": 49553, "\u0120Judd": 49554, "\u0120flashbacks": 49555, "pins": 49556, "\u01201440": 49557, "\u0120UNHCR": 49558, "\u0120Symptoms": 49559, "TIT": 49560, "538": 49561, "Fra": 49562, "%);": 49563, "\u0120ooz": 49564, "\u0120curfew": 49565, "\u0120calmed": 49566, "\u0120participates": 49567, "TeX": 49568, "\u0120nonsensical": 49569, "\u0120fullback": 49570, "\u0120DeL": 49571, "monkey": 49572, "hari": 49573, "\u0120metabolites": 49574, "\u0120looted": 49575, "\u0120ALWAYS": 49576, "\u0120BCC": 49577, "Lt": 49578, "ochet": 49579, "Bone": 49580, "\u0120vetoed": 49581, "\u0120gcc": 49582, "\u0120CLICK": 49583, "\u01201888": 49584, "saf": 49585, "\u0120stiffness": 49586, "\u0120lowly": 49587, "\u0120Geh": 49588, "verson": 49589, "orset": 49590, "\u0120unforeseen": 49591, "\u0120anesthesia": 49592, "\u0120Optical": 49593, "\u0120reconstructed": 49594, "\u0120Tup": 49595, "shows": 49596, "NEWS": 49597, "\u0120Newspaper": 49598, "\u0120ASA": 49599, "tera": 49600, "Numbers": 49601, "\u0120inexplicable": 49602, "\u00d7\u0133": 49603, "\u0120hardness": 49604, "untarily": 49605, "\u0120Acer": 49606, "gradient": 49607, "ARDIS": 49608, "\u0120woodland": 49609, "\u0120metaphors": 49610, "\u0120Wembley": 49611, "\u0120Pavel": 49612, "philis": 49613, "\u0120rewriting": 49614, "\u0120perceptual": 49615, "\u01201070": 49616, "worms": 49617, "\u0120Downs": 49618, "\u0120unsurprisingly": 49619, "\u0120tagging": 49620, "flame": 49621, "\u0120litres": 49622, "\u0120bounces": 49623, "\u0120Babe": 49624, "shut": 49625, "\u0120overdoses": 49626, "\u0120Sheila": 49627, "\u0120Chau": 49628, "\u0120Bless": 49629, "Capture": 49630, "\u0120Significant": 49631, "\u0120Scion": 49632, "\u0120389": 49633, "\u0120McH": 49634, "\u0120Titanium": 49635, "\u0120Meal": 49636, "ameda": 49637, "agents": 49638, "aggressive": 49639, "Billy": 49640, "763": 49641, "\u0120Saying": 49642, "DERR": 49643, "itone": 49644, "Collins": 49645, "Bound": 49646, "\u0120bolted": 49647, "\u0120DMCA": 49648, "953": 49649, "\u0120uniqueness": 49650, "\u0120epigen": 49651, "unci": 49652, "antam": 49653, "\u0120reckoning": 49654, "chairs": 49655, "OGR": 49656, "\u0120Senegal": 49657, "\u01201862": 49658, "relevant": 49659, "\u0120\u00c2\u00af": 49660, "\u0120pharmacies": 49661, "\u0120Geral": 49662, "vier": 49663, "Yan": 49664, "ORPG": 49665, "\u0120rabid": 49666, "bending": 49667, "\u0120UNITED": 49668, "\u0120465": 49669, "Assembly": 49670, "\u0120weep": 49671, "\u0120behest": 49672, "\u0120Mothers": 49673, "\u0120Jace": 49674, "hid": 49675, "\u0120whirlwind": 49676, "\u0120UNIVERS": 49677, "\u0120utopian": 49678, "\u0120kidnap": 49679, "Philipp": 49680, "Kin": 49681, "893": 49682, "\u0120livestream": 49683, "\u0120MISS": 49684, "\u0120subversive": 49685, "\u0120Techniques": 49686, "\u0120JUSTICE": 49687, "\u0120BASE": 49688, "\u0120387": 49689, "\u0120assailants": 49690, "\u0120Hardcore": 49691, "\u0120sprinkled": 49692, "\u0120Pse": 49693, "\u00e9\u013c": 49694, "printed": 49695, "\u0120Hau": 49696, "ORGE": 49697, "\u0120TOUR": 49698, "\u0120laced": 49699, "\u0120itch": 49700, "Giving": 49701, "\u0120ported": 49702, "781": 49703, "////////////////////////////////": 49704, "breeding": 49705, "\u0120logger": 49706, "\u0120HOL": 49707, "innie": 49708, "Firstly": 49709, "\u0120embryonic": 49710, "\u0120delegated": 49711, "pai": 49712, "OIL": 49713, "\u0120centrally": 49714, "\u0120Rx": 49715, "\u0120Scouting": 49716, "Dutch": 49717, "\u0120hereditary": 49718, "\u0120Cruiser": 49719, "sat": 49720, "529": 49721, "\u0120Marriott": 49722, "othermal": 49723, "\u0120prohibitions": 49724, "Earn": 49725, "\u0120Stab": 49726, "\u0120Colleges": 49727, "\u0120Belief": 49728, "stretched": 49729, "\u0120LH": 49730, "\u0120EntityItem": 49731, "CIA": 49732, "\u0120unrem": 49733, "\u0120laureate": 49734, "\u0120denominations": 49735, "summary": 49736, "hler": 49737, "Spect": 49738, "\u0120Klaus": 49739, "\u0120Beans": 49740, "\u0120insur": 49741, "\u0120PAX": 49742, "\u0120fielder": 49743, "\u0120Vet": 49744, "\u0120Sparrow": 49745, "zie": 49746, "\u0120SQ": 49747, "\u0120Mondays": 49748, "\u0120Offline": 49749, "\u0120Lerner": 49750, "\u0120Extensions": 49751, "Ireland": 49752, "\u0120patronage": 49753, "\u0120contrasted": 49754, "\u0120Mania": 49755, "hirt": 49756, "Moscow": 49757, "\u0120condemns": 49758, "\u0120Ange": 49759, "\u0120composing": 49760, "\u0120Pepe": 49761, "\u0120Paddock": 49762, "\u0120heterogeneity": 49763, "\u0120ideologically": 49764, "\u0120fishes": 49765, "\u0120cursing": 49766, "\u0120Rutherford": 49767, "\u0120Floating": 49768, "\u0120Amelia": 49769, "Tea": 49770, "Synopsis": 49771, "\u0120stunts": 49772, "\u0120bead": 49773, "\u0120stocking": 49774, "\u0120MILL": 49775, "obook": 49776, "massive": 49777, "\\<": 49778, "\u0120hump": 49779, "\u0120Preferences": 49780, "EngineDebug": 49781, "geist": 49782, "\u0120Nieto": 49783, "omever": 49784, "ishy": 49785, "evaluate": 49786, "colonial": 49787, "Alternative": 49788, "\u0120GoPro": 49789, "\u0120Vortex": 49790, "\u0120NETWORK": 49791, "ansky": 49792, "Secure": 49793, "\u0120Thrust": 49794, "Snake": 49795, "\u0120parcels": 49796, "\u0120samurai": 49797, "\u0120actresses": 49798, "Nap": 49799, "MF": 49800, "iferation": 49801, "Beer": 49802, "523": 49803, "\u0120Ily": 49804, "ointment": 49805, "Ping": 49806, "\u0120striped": 49807, "\u0120Mellon": 49808, "ossession": 49809, "\u0120neutron": 49810, "endium": 49811, "\u0120aph": 49812, "\u0120Flavoring": 49813, "\u0120383": 49814, "\u0120responsiveness": 49815, "\u0120Jindal": 49816, "\u0120Hitchcock": 49817, "Denver": 49818, "\u0120DRAGON": 49819, "smanship": 49820, "\u0120Dupl": 49821, "\u0120sly": 49822, "\u0120webcam": 49823, "\u0120Twain": 49824, "\u0120Darling": 49825, "iliate": 49826, "consumer": 49827, "DIT": 49828, "\u0120namesake": 49829, "\u0120unorthodox": 49830, "\u0120funer": 49831, "\u0120PLoS": 49832, "\u0120CONTROL": 49833, "ozyg": 49834, "oglobin": 49835, "FACE": 49836, "ERG": 49837, "\u0120Dia": 49838, "\u0120Fiesta": 49839, "cele": 49840, "034": 49841, "\u0120enclave": 49842, "\u00e2\u0138\u00ac\u00e2\u0138\u00ac": 49843, "onement": 49844, "alist": 49845, "Mand": 49846, "\u0120homegrown": 49847, "\u0120Fancy": 49848, "\u0120conceptions": 49849, "\u0120Contains": 49850, "ureen": 49851, "\u0120reiterate": 49852, "\u0120meager": 49853, "\u0120installments": 49854, "Spawn": 49855, "627": 49856, "\u0120photoc": 49857, "\u0120Cabrera": 49858, "\u0120Rosenthal": 49859, "\u0120Lansing": 49860, "isner": 49861, "\u0120invests": 49862, "\u0120UFOs": 49863, "EXP": 49864, "Hardware": 49865, "\u0120tragically": 49866, "\u0120concedes": 49867, "ieft": 49868, "cham": 49869, "borgh": 49870, "\u0120Schr": 49871, "\u0120Melanie": 49872, "\u0120Hoy": 49873, "\u0120visitation": 49874, "\u0120idiosyncr": 49875, "\u0120fractions": 49876, "\u0120foreskin": 49877, "obos": 49878, "\u0120poaching": 49879, "\u0120VIEW": 49880, "\u0120stimulates": 49881, "\u0120Gork": 49882, "canon": 49883, "MIC": 49884, "\u0120Nemesis": 49885, "\u0120Indra": 49886, "\u0120DMV": 49887, "\u0120529": 49888, "\u0120inspecting": 49889, "\u0120grandma": 49890, "\u0120Whedon": 49891, "\u0120Shant": 49892, "\u0120Purg": 49893, "ikan": 49894, "\u0120Teg": 49895, "\u0120CLR": 49896, "zac": 49897, "Victoria": 49898, "\u0120Verify": 49899, "ionics": 49900, "\u0120partying": 49901, "\u0120Mou": 49902, "colour": 49903, "\u0120testimonies": 49904, "lations": 49905, "\u0120pressuring": 49906, "hiro": 49907, "acers": 49908, "\u0120fid": 49909, "angler": 49910, "\u0120CSI": 49911, "\u0120hereafter": 49912, "\u0120dissidents": 49913, "reporting": 49914, "iphany": 49915, "chev": 49916, "\u0120solitude": 49917, "\u0120lobe": 49918, "\u0120indis": 49919, "\u0120credential": 49920, "recent": 49921, "adult": 49922, "\u0120Nirvana": 49923, "\u0120Franchise": 49924, "Layer": 49925, "Hyp": 49926, "\u0120Berkshire": 49927, "\u0120wills": 49928, "tif": 49929, "\u0120totem": 49930, "\u0120Judah": 49931, "repair": 49932, "Instant": 49933, "548": 49934, "\u0120embassies": 49935, "\u0120bottleneck": 49936, "\u0120bount": 49937, "\u0120typew": 49938, "\u0120Alvin": 49939, "jing": 49940, "imilar": 49941, "Rush": 49942, "\u0120brim": 49943, "\u0120HELP": 49944, "Aim": 49945, "]'": 49946, "\u0120passively": 49947, "\u0120bounded": 49948, "\u0120Rated": 49949, "\u0120criminality": 49950, "\u0120biomark": 49951, "\u0120dispatcher": 49952, "\u0120Towards": 49953, "\u0120+++": 49954, "righteous": 49955, "frog": 49956, "\u0120Panc": 49957, "Carter": 49958, "032": 49959, "\u00e6\u00a9\u0141": 49960, "\u0120ultraviolet": 49961, "\u0120Licensed": 49962, "\u0120Tata": 49963, "\u0120Blessing": 49964, "\u0120GAM": 49965, "\u0120chemically": 49966, "\u0120Seaf": 49967, "\u0120RELE": 49968, "\u0120Mercenary": 49969, "capitalist": 49970, "\u0120formulations": 49971, "\u0120annihilation": 49972, "\u0120Verb": 49973, "\u0120Argon": 49974, "\u0120unloaded": 49975, "\u0120morphed": 49976, "\u0120conquering": 49977, "backer": 49978, "IELD": 49979, "\u0120thefts": 49980, "\u0120frontrunner": 49981, "\u0120Royale": 49982, "\u0120Fundamental": 49983, "elight": 49984, "Chip": 49985, "necessary": 49986, "ayn": 49987, "\u0120Slip": 49988, "\u0120448": 49989, "cerned": 49990, "Pause": 49991, "\u0120shockingly": 49992, "\u0120ABV": 49993, "\u0120composure": 49994, "733": 49995, "\u0120Motorsport": 49996, "ahime": 49997, "Murray": 49998, "Mach": 49999, "\u0120grids": 50000, "\u0120debian": 50001, "\u0120furthermore": 50002, "\u0120dexterity": 50003, "\u0120Collections": 50004, "oslov": 50005, "ilage": 50006, "bj": 50007, "\u0120Monteneg": 50008, "\u0120strutConnector": 50009, "\u0120massacres": 50010, "\u0120briefs": 50011, "fetched": 50012, "uvian": 50013, "olition": 50014, "Failure": 50015, "emonic": 50016, "\u0120flared": 50017, "\u0120claimant": 50018, "\u0120cures": 50019, "\u0120giveaways": 50020, "\u0120Substance": 50021, "alions": 50022, "\u0120cringe": 50023, "\u0120Kul": 50024, "\u0120aristocracy": 50025, "\u0120Ulster": 50026, "olated": 50027, "housing": 50028, "\u0120MIS": 50029, "\u0120glared": 50030, "\u0120Wilhelm": 50031, "needs": 50032, "lambda": 50033, "builders": 50034, "\u0120VIS": 50035, "\u0120radiator": 50036, "\u0120Ghostbusters": 50037, "\u0120436": 50038, "actual": 50039, "\u0120herds": 50040, "\u00c3\u00a7a": 50041, "watching": 50042, "\u0120countering": 50043, "Charge": 50044, "\u0120charred": 50045, "\u0120warheads": 50046, "\u0120iodine": 50047, "\u0120Macy": 50048, "041": 50049, "\u0120departures": 50050, "\u0120Sins": 50051, "\u0120dyed": 50052, "\u0120Concepts": 50053, "gado": 50054, "713": 50055, "\u0120quotations": 50056, "\u0120gist": 50057, "\u0120Christy": 50058, "\u0120antigen": 50059, "\u0120Hemp": 50060, "\u0120Drawn": 50061, "\u0120Barg": 50062, "ezvous": 50063, "\u0120paternity": 50064, "\u0120ardu": 50065, "\u0120Anchorage": 50066, "\u0120Rik": 50067, "\u0120overloaded": 50068, "\u0120Username": 50069, "\u0120Tammy": 50070, "\u0120Nau": 50071, "\u0120Cellular": 50072, "\u0120waning": 50073, "\u0120rodent": 50074, "\u0120Worcester": 50075, "ilts": 50076, "\u0120Tad": 50077, "\u0120dwellings": 50078, "\u0120bullish": 50079, "431": 50080, "\u0120retaliate": 50081, "\u0120migraine": 50082, "\u0120Chevron": 50083, "CHECK": 50084, "\u0120donkey": 50085, "crim": 50086, "SPA": 50087, "\u0120Analog": 50088, "\u0120marquee": 50089, "\u0120Haas": 50090, "Bir": 50091, "\u0120GDDR": 50092, "\u0120Downloads": 50093, "\u0120willpower": 50094, "\u0120Forth": 50095, "\u0120Recorded": 50096, "\u0120impossibility": 50097, "\u0120Logged": 50098, "\u0120Franks": 50099, "\u0120Ratt": 50100, "initions": 50101, "\u0120cleaners": 50102, "\u0120sorely": 50103, "\u0120flickering": 50104, "\u0120Examination": 50105, "catching": 50106, "alloween": 50107, "Msg": 50108, "\u0120dunno": 50109, "Fa": 50110, "\u0120dysph": 50111, "crazy": 50112, ".''.": 50113, "\u0120mainline": 50114, "\u0120cs": 50115, "\u0120ptr": 50116, "\u0120Wally": 50117, "igun": 50118, "951": 50119, "\u0120Bigfoot": 50120, "fights": 50121, "\u0120retrieving": 50122, "Jr": 50123, "\u0120duplication": 50124, "\u0120Explan": 50125, "\u0120relational": 50126, "\u0120quaint": 50127, "\u0120biscuits": 50128, "\u0120ado": 50129, "\u0120shudder": 50130, "\u0120antidote": 50131, "blooded": 50132, "ksh": 50133, "\u0120sauces": 50134, "\u0120reinvest": 50135, "\u0120dispensary": 50136, "\u0120Diver": 50137, "\u01209000": 50138, "student": 50139, "\u0120insepar": 50140, "escap": 50141, "\u0120toddlers": 50142, "\u0120GPIO": 50143, "\u0120Assignment": 50144, "headers": 50145, "\u0120lackluster": 50146, "\u0120aback": 50147, "956": 50148, "\u0120toolbar": 50149, "745": 50150, "\u0120oust": 50151, "\u0120contemplation": 50152, "\u0120PRESIDENT": 50153, "\u0120458": 50154, "======": 50155, "\u0120guaranteeing": 50156, "\u0120Heist": 50157, "\u0120Cannes": 50158, "\u013b\u00bd": 50159, "\u0120collaborator": 50160, "\u0120Amp": 50161, "\u0120gou": 50162, "\u0120SHALL": 50163, "stories": 50164, "783": 50165, "\u0120mobilized": 50166, "\u0120brood": 50167, "\u0120LU": 50168, "\u0120\u00f0\u0141\u0133": 50169, "\u0120refin": 50170, "\u0120Anthropology": 50171, "vind": 50172, "illi": 50173, "\u0120warranties": 50174, "\u0120Babel": 50175, "\u0120swath": 50176, "\u0120caches": 50177, "\u0120antagonists": 50178, "artifacts": 50179, "\u0120hotly": 50180, "\u0120Starts": 50181, "\u0120G\u00c3\u00b6": 50182, "zag": 50183, "!!!!!": 50184, "\u0120scourge": 50185, "\u0120conspiring": 50186, "ruits": 50187, "reverse": 50188, "\u0120Sheen": 50189, "\u0120Jesuit": 50190, "\u0120Giovanni": 50191, "adies": 50192, "\u0120buttocks": 50193, "earcher": 50194, "acan": 50195, "\u0120volleyball": 50196, "\u0120shrouded": 50197, "\u0120scoreboard": 50198, "bats": 50199, "\u0120IPM": 50200, "\u0120asses": 50201, "\u0120deregulation": 50202, "\u0120Telegram": 50203, "\u0120Reboot": 50204, "\u01207000": 50205, "\u0120Canary": 50206, "\u0120kernels": 50207, "\u0120Fran\u00c3\u00a7ois": 50208, "\u0120Duff": 50209, "\u0120Pon": 50210, "\u0120Leica": 50211, "\u0120Garmin": 50212, "\u0120orphans": 50213, "\u0120Claudia": 50214, "\u0120calendars": 50215, "\u0120Leilan": 50216, "ento": 50217, "Rocket": 50218, "\u0120brunch": 50219, "\u0120Hawking": 50220, "ainers": 50221, "\u0120sensibilities": 50222, "\u0120kW": 50223, "\u0120Kand": 50224, "\u0120reclaimed": 50225, "\u0120interestingly": 50226, "\u00d7\u00a9": 50227, "romy": 50228, "JM": 50229, "\u0120Enhancement": 50230, "bush": 50231, "Skip": 50232, "\u0120rappers": 50233, "\u0120gazing": 50234, "pedia": 50235, "athlon": 50236, "Revolution": 50237, "\u0120snipers": 50238, "\u0120reverted": 50239, "\u0120conglomerate": 50240, "Terry": 50241, "794": 50242, "\u0120harsher": 50243, "\u0120desolate": 50244, "\u0120Hitman": 50245, "Commission": 50246, "\u0120(/": 50247, "\u00e2\u0122\u00a6.\"": 50248, "Compar": 50249, "\u0120amplification": 50250, "ominated": 50251, "\u0120regress": 50252, "\u0120Collider": 50253, "\u0120informants": 50254, "\u0120gazed": 50255, "<|endoftext|>": 50256} \ No newline at end of file diff --git a/java/extensions/semantickernel-gpt3-tokenizer/src/main/resources/vocab.bpe b/java/extensions/semantickernel-gpt3-tokenizer/src/main/resources/vocab.bpe new file mode 100644 index 0000000000..226b0752ca --- /dev/null +++ b/java/extensions/semantickernel-gpt3-tokenizer/src/main/resources/vocab.bpe @@ -0,0 +1,50001 @@ +#version: 0.2 +Ä  t +Ä  a +h e +i n +r e +o n +Ä t he +e r +Ä  s +a t +Ä  w +Ä  o +e n +Ä  c +i t +i s +a n +o r +e s +Ä  b +e d +Ä  f +in g +Ä  p +o u +Ä a n +a l +a r +Ä t o +Ä  m +Ä o f +Ä  in +Ä  d +Ä  h +Ä an d +i c +a s +l e +Ä t h +i on +o m +l l +en t +Ä  n +Ä  l +s t +Ä  re +v e +Ä  e +r o +l y +Ä b e +Ä  g +Ä  T +c t +Ä  S +i d +o t +Ä  I +u t +e t +Ä  A +Ä  is +Ä  on +i m +a m +o w +a y +a d +s e +Ä th at +Ä  C +i g +Ä f or +a c +Ä  y +v er +u r +Ä  u +l d +Ä s t +Ä  M +' s +Ä  he +Ä  it +at ion +it h +i r +c e +Ä y ou +i l +Ä  B +Ä w h +o l +Ä  P +Ä w ith +Ä  1 +t er +c h +Ä a s +Ä w e +Ä  ( +n d +i ll +Ä  D +i f +Ä  2 +a g +er s +k e +Ä  " +Ä  H +e m +Ä c on +Ä  W +Ä  R +he r +Ä w as +Ä  r +o d +Ä  F +u l +at e +Ä a t +r i +p p +o re +Ä T he +Ä s e +u s +Ä p ro +Ä h a +u m +Ä a re +Ä d e +a in +an d +Ä o r +ig h +es t +is t +a b +r om +Ä  N +t h +Ä c om +Ä  G +u n +o p +0 0 +Ä  L +Ä n ot +es s +Ä e x +Ä  v +re s +Ä  E +e w +it y +an t +Ä b y +e l +o s +or t +o c +q u +Ä f rom +Ä ha ve +Ä s u +i ve +ou ld +Ä s h +Ä th is +n t +r a +p e +igh t +ar t +m ent +Ä a l +u st +en d +- - +al l +Ä  O +ac k +Ä c h +Ä  le +i es +re d +ar d +Ãĸ Äĸ +ou t +Ä  J +Ä a b +e ar +i v +al ly +ou r +o st +g h +p t +Ä p l +as t +Ä c an +a k +om e +u d +T he +Ä h is +Ä d o +Ä g o +Ä h as +g e +' t +Ä  U +r ou +Ä s a +Ä  j +Ä b ut +Ä w or +Ä a ll +e ct +Ä  k +am e +Ä w ill +o k +Ä w he +Ä the y +id e +0 1 +f f +ic h +p l +t her +Ä t r +. . +Ä in t +i e +u re +ag e +Ä n e +i al +a p +in e +ic e +Ä m e +Ä o ut +an s +on e +on g +ion s +Ä wh o +Ä  K +Ä u p +Ä the ir +Ä a d +Ä  3 +Ä u s +at ed +ou s +Ä m ore +u e +o g +Ä S t +in d +i ke +Ä s o +im e +p er +. " +b er +i z +a ct +Ä on e +Ä sa id +Ä  - +a re +Ä you r +c c +Ä T h +Ä c l +e p +a ke +ab le +i p +Ä con t +Ä wh ich +i a +Ä  im +Ä ab out +Ä we re +ver y +u b +Ä h ad +Ä  en +Ä com p +, " +Ä I n +Ä u n +Ä a g +i re +ac e +a u +ar y +Ä w ould +as s +r y +Ä  ÃĸÄĸ +c l +o ok +e re +s o +Ä  V +ig n +i b +Ä of f +Ä t e +v en +Ä  Y +i le +o se +it e +or m +Ä 2 01 +Ä re s +Ä m an +Ä p er +Ä o ther +or d +ul t +Ä be en +Ä l ike +as e +an ce +k s +ay s +ow n +en ce +Ä d is +ct ion +Ä an y +Ä a pp +Ä s p +in t +res s +ation s +a il +Ä  4 +ic al +Ä the m +Ä he r +ou nt +Ä C h +Ä a r +Ä  if +Ä the re +Ä p e +Ä y ear +a v +Ä m y +Ä s ome +Ä whe n +ou gh +ac h +Ä th an +r u +on d +ic k +Ä o ver +ve l +Ä  qu +Ċ Ċ +Ä s c +re at +re e +Ä I t +ou nd +p ort +Ä al so +Ä p art +f ter +Ä k n +Ä be c +Ä t ime +en s +Ä  5 +op le +Ä wh at +Ä n o +d u +m er +an g +Ä n ew +-- -- +Ä g et +or y +it ion +ing s +Ä j ust +Ä int o +Ä  0 +ent s +o ve +t e +Ä pe ople +Ä p re +Ä it s +Ä re c +Ä t w +i an +ir st +ar k +or s +Ä wor k +ad e +o b +Ä s he +Ä o ur +w n +in k +l ic +Ä 1 9 +Ä H e +is h +nd er +au se +Ä h im +on s +Ä  [ +Ä  ro +f orm +i ld +at es +ver s +Ä on ly +o ll +Ä s pe +c k +e ll +am p +Ä a cc +Ä b l +i ous +ur n +f t +o od +Ä h ow +he d +Ä  ' +Ä a fter +a w +Ä at t +o v +n e +Ä pl ay +er v +ic t +Ä c ould +it t +Ä a m +Ä f irst +Ä  6 +Ä a ct +Ä  $ +e c +h ing +u al +u ll +Ä com m +o y +o ld +c es +at er +Ä f e +Ä be t +w e +if f +Ä tw o +oc k +Ä b ack +) . +id ent +Ä u nder +rou gh +se l +x t +Ä m ay +rou nd +Ä p o +p h +is s +Ä d es +Ä m ost +Ä d id +Ä ad d +j ect +Ä in c +f ore +Ä p ol +on t +Ä ag ain +cl ud +ter n +Ä kn ow +Ä ne ed +Ä con s +Ä c o +Ä  . +Ä w ant +Ä se e +Ä  7 +n ing +i ew +Ä Th is +c ed +Ä e ven +Ä in d +t y +Ä W e +at h +Ä the se +Ä p r +Ä u se +Ä bec ause +Ä f l +n g +Ä n ow +Ä ÃĸÄĸ Äĩ +c om +is e +Ä m ake +Ä the n +ow er +Ä e very +Ä U n +Ä se c +os s +u ch +Ä e m +Ä  = +Ä R e +i ed +r it +Ä in v +le ct +Ä su pp +at ing +Ä l ook +m an +pe ct +Ä  8 +ro w +Ä b u +Ä whe re +if ic +Ä year s +i ly +Ä d iff +Ä sh ould +Ä re m +T h +I n +Ä e v +d ay +' re +ri b +Ä re l +s s +Ä de f +Ä r ight +Ä s y +) , +l es +00 0 +he n +Ä th rough +Ä T r +_ _ +Ä w ay +Ä d on +Ä  , +Ä 1 0 +as ed +Ä as s +ub lic +Ä re g +Ä A nd +i x +Ä  very +Ä in clud +ot her +Ä im p +ot h +Ä su b +Ä ÃĸÄĸ Äļ +Ä be ing +ar g +Ä W h += = +ib le +Ä do es +an ge +r am +Ä  9 +er t +p s +it ed +ation al +Ä b r +Ä d own +Ä man y +ak ing +Ä c all +ur ing +it ies +Ä p h +ic s +al s +Ä de c +at ive +en er +Ä be fore +il ity +Ä we ll +Ä m uch +ers on +Ä th ose +Ä su ch +Ä  ke +Ä  end +Ä B ut +as on +t ing +Ä l ong +e f +Ä th ink +y s +Ä be l +Ä s m +it s +a x +Ä o wn +Ä pro v +Ä s et +if e +ment s +b le +w ard +Ä sh ow +Ä p res +m s +om et +Ä o b +Ä s ay +Ä S h +t s +f ul +Ä e ff +Ä g u +Ä in st +u nd +re n +c ess +Ä  ent +Ä Y ou +Ä go od +Ä st art +in ce +Ä m ade +t t +st em +ol og +u p +Ä  | +um p +Ä he l +ver n +ul ar +u ally +Ä a c +Ä m on +Ä l ast +Ä 2 00 +1 0 +Ä st ud +u res +Ä A r +sel f +ar s +mer ic +u es +c y +Ä m in +oll ow +Ä c ol +i o +Ä m od +Ä c ount +Ä C om +he s +Ä f in +a ir +i er +ÃĸÄĸ Äļ +re ad +an k +at ch +e ver +Ä st r +Ä po int +or k +Ä N ew +Ä s ur +o ol +al k +em ent +Ä us ed +ra ct +we en +Ä s ame +ou n +Ä A l +c i +Ä diff ere +Ä wh ile +---- ---- +Ä g ame +ce pt +Ä s im +.. . +Ä in ter +e k +Ä re port +Ä pro du +Ä st ill +l ed +a h +Ä he re +Ä wor ld +Ä th ough +Ä n um +ar ch +im es +al e +Ä S e +Ä I f +/ / +Ä L e +Ä re t +Ä re f +Ä tr ans +n er +ut ion +ter s +Ä t ake +Ä C l +Ä con f +w ay +a ve +Ä go ing +Ä s l +u g +Ä A meric +Ä spe c +Ä h and +Ä bet ween +ist s +Ä D e +o ot +I t +Ä e ar +Ä again st +Ä h igh +g an +a z +at her +Ä ex p +Ä o p +Ä in s +Ä g r +Ä hel p +Ä re qu +et s +in s +Ä P ro +is m +Ä f ound +l and +at a +us s +am es +Ä p erson +Ä g reat +p r +Ä s ign +Ä A n +' ve +Ä s omet +Ä s er +h ip +Ä r un +Ä  : +Ä t er +ire ct +Ä f ollow +Ä d et +ic es +Ä f ind +1 2 +Ä m em +Ä c r +e red +e x +Ä ex t +ut h +en se +c o +Ä te am +v ing +ou se +as h +at t +v ed +Ä sy stem +Ä A s +d er +iv es +m in +Ä le ad +Ä B l +c ent +Ä a round +Ä go vern +Ä c ur +vel op +an y +Ä c our +al th +ag es +iz e +Ä c ar +od e +Ä l aw +Ä re ad +' m +c on +Ä re al +Ä supp ort +Ä 1 2 +.. .. +Ä re ally +n ess +Ä f act +Ä d ay +Ä b oth +y ing +Ä s erv +Ä F or +Ä th ree +Ä w om +Ä m ed +od y +Ä The y +5 0 +Ä ex per +t on +Ä e ach +ak es +Ä c he +Ä c re +in es +Ä re p +1 9 +g g +ill ion +Ä g rou +ut e +i k +W e +g et +E R +Ä m et +Ä s ays +o x +Ä d uring +er n +iz ed +a red +Ä f am +ic ally +Ä ha pp +Ä I s +Ä ch ar +m ed +v ent +Ä g ener +i ent +p le +i et +re nt +1 1 +v es +pt ion +Ä 2 0 +form ation +Ä c or +Ä off ic +ie ld +Ä to o +is ion +Ä in f +Ä  Z +t he +o ad +Ä p ublic +Ä pro g +r ic +* * +Ä w ar +Ä p ower +v iew +Ä f ew +Ä l oc +Ä differe nt +Ä st ate +Ä he ad +' ll +Ä p oss +Ä st at +re t +ant s +Ä v al +Ä is s +Ä c le +i vers +an c +Ä ex pl +Ä an other +Ä  Q +Ä a v +th ing +n ce +W h +Ä ch ild +Ä s ince +i red +l ess +Ä l ife +Ä de velop +itt le +Ä de p +Ä p ass +ÃŖ ÄĨ +Ä t urn +or n +Th is +b ers +ro ss +Ä A d +Ä f r +Ä res p +Ä sec ond +o h +Ä  / +Ä dis c +Ä  & +Ä somet hing +Ä comp le +Ä  ed +Ä f il +Ä mon th +a j +u c +Ä govern ment +Ä with out +Ä le g +Ä d ist +Ä p ut +Ä qu est +an n +Ä pro t +2 0 +Ä ne ver +i ence +Ä le vel +Ä ar t +Ä th ings +Ä m ight +Ä eff ect +Ä cont ro +Ä c ent +Ä 1 8 +Ä all ow +Ä bel ie +ch ool +ot t +Ä inc re +Ä fe el +Ä res ult +Ä l ot +Ä f un +ot e +Ä t y +ere st +Ä cont in +Ä us ing +Ä b ig +2 01 +Ä as k +Ä b est +Ä  ) +I N +Ä o pp +3 0 +Ä num ber +in ess +S t +le ase +Ä c a +Ä m ust +Ä d irect +Ä g l +Ä  < +Ä op en +Ä p ost +Ä com e +Ä se em +ord ing +Ä we ek +ate ly +it al +Ä e l +ri end +Ä f ar +Ä t ra +in al +Ä p ri +Ä U S +Ä pl ace +Ä for m +Ä to ld +" : +ain s +at ure +Ä Tr ump +Ä st and +Ä  # +id er +Ä F r +Ä ne xt +Ä s oc +Ä p ur +Ä le t +Ä l ittle +Ä h um +Ä  i +r on +1 5 +Ä 1 5 +Ä comm un +Ä m ark +Ä The re +Ä w r +Ä Th at +Ä in formation +w ays +Ä b us +a pp +Ä inv est +m e +Ä h ard +ain ed +e ad +Ä im port +Ä app ro +Ä t est +Ä t ri +Ä re st +os ed +Ä f ull +Ä c are +Ä S p +Ä c ase +O N +Ä s k +Ä l ess +Ä  + +Ä part ic +Ä P l +ab ly +u ck +is hed +ch n +b e +Ä l ist +at or +Ä to p +Ä ad v +Ä B e +ru ct +Ä d em +r ation +l ing +g y +re en +g er +Ä h ome +Ä le ft +Ä bet ter +Ä d ata +Ä 1 1 +Ä att ack +Ä pro ble +l ine +ard s +Ä be h +r al +Ä H ow +Ä S he +ar ge +Ä  -- +: // +Ä b ro +Ä P h +at s +Ä bu ild +w w +id ed +a im +as es +en cy +Ä m ain +in ed +Ä includ ing +Ä  { +Ä g ot +Ä int erest +Ä ke ep +Ä  X +Ä e as +ain ing +Ä cl ass +ÃĸÄĸ ÂĻ +Ä N o +Ä v ar +Ä sm all +amp le +A T +Ä  ide +Ä S o +Ä re ce +Ä pol it +Ä m ov +Ä pl an +Ä per cent +iv ing +Ä c amp +Ä p ay +1 4 +s c +is ed +Ä u nt +one y +pl oy +== == +Ä did n +Ä I nd +el s +ert ain +Ä p os +__ __ +i ver +Ä pro cess +Ä prog ram +if ied +Ä R ep +1 6 +u ro +olog y +at ter +in a +Ä n ame +Ä A ll +Ä f our +Ä ret urn +v ious +b s +Ä call ed +Ä m ove +Ä S c +ir d +Ä grou p +Ä b re +Ä m en +Ä c ap +t en +e e +Ä d ri +le g +he re +uth or +Ä p at +Ä cur rent +id es +Ä p op +t o +ent ion +Ä al ways +Ä m il +Ä wom en +Ä 1 6 +Ä o ld +iv en +ra ph +Ä O r +r or +ent ly +Ä n ear +Ä E x +re am +s h +Ä 1 4 +Ä f ree +iss ion +st and +Ä C on +al ity +us ed +1 3 +Ä des ign +Ä ch ange +Ä ch ang +Ä b o +Ä v is +em ber +Ä b ook +read y +Ä k ill +2 5 +pp ed +Ä a way +Ä ab le +Ä count ry +Ä con st +ar n +Ä or der +A R +i or +i um +or th +1 8 +ail able +Ä s w +Ä m illion +Ä 1 3 +at ic +t ed +Ä G o +Ä o per +en g +Ä th ing +aj or +con om +Ä Com m +Ä wh y +u red +ur al +Ä s chool +b y +Ä M ar +Ä a ff +Ä d ays +Ä an n +us h +an e +I f +e g +Ä pro f +Ä he alth +ou th +B ut +ion al +. , +Ä s ol +Ä al ready +Ä 3 0 +Ä char act +H e +Ä f riend +E S +i ans +ic le +' d +Ä O n +Ä le ast +Ä p rom +Ä d r +Ä h ist +it her +Ä  est +i qu +1 7 +s on +Ä te ll +Ä t alk +oh n +o int +le ction +A N +Ä unt il +au gh +Ä l ater +Ä  ve +Ä v iew +end ing +iv ed +Ä wor d +w are +Ä c ost +Ä en ough +Ä g ive +Ä Un ited +Ä te chn +are nt +O R +Ä p ar +Ä D r +Ä 201 6 +r ist +er ing +Ä   +Ä l arge +s ide +ac y +cc ess +Ä w in +Ä import ant +Ä 19 9 +Ä does n +Ä 1 7 +Ä bus iness +Ä cle ar +Ä re se +" , +ur y +Ä e qu +as ter +al f +Ä Americ an +n ect +Ä ex pect +ivers ity +Ä o cc +Ä F l +Ä k ind +Ä me an +Ä p ast +Ä de v +Ä b as +le t +ra ft +Ä or gan +Ä de l +Ä per form +Ä st ory +Ä se ason +Ä C ol +Ä cl aim +Ä c ame +Ä with in +Ä l ine +Ä pro ject +Ä A t +Ä contro l +end ed +Ä S y +Ä a ir +iz ation +Ä  * +le y +Ä m oney +id d +Y ou +f or +Ä fam ily +Ä m aking +Ä b it +Ä pol ice +Ä happ en +Ä  vers +on y +u ff +Ä W hen +Ä s it +ide o +l f +is on +Ä su re +g in +Ä app ear +Ä l ight +Ä  es +o f +Ä w ater +Ä t imes +n ot +Ä g row +Ä comp any +Ä T e +ow s +Ä m ar +our ce +i ol +ar m +b r +Ä ex ample +Ä con c +Ä f ore +Ä T o +p ro +E N +ri es +Ä 2 5 +Ä C an +ne y +Ä act ually +Ä e ver +ur ity +ak en +ap s +Ä t ax +Ä m ajor +am a +Ä of ten +er al +Ä hum an +Ä j ob +is ter +Ä av ailable +oc r +en n +a id +iv id +Ä rec ord +? " +Ä s ing +Ä A m +id ence +Ä new s +st er +Ä e conom +Ä follow ing +Ä B r +is ing +Ä h our +m ost +um ent +Ä se x +Ä des c +Ä bec ome +Ä E d +Ä to ok +Ä ha ving +Ä produ ct +a ult +A s +ar ing +Ä me ans +Ä h op +un e +Ä ch o +Ä c ertain +Ä n on +Ä de al +2 4 +le ment +oc i +en e +Ä s ide +Ä P r +Ä M ay +Ä re ason +u ed +c hed +ul ation +Ä e lect +Ä offic ial +Ä poss ible +Ä h old +and s +ot s +Ä c ity +or ies +Ä se ver +Ä child ren +Ä on ce +Ä act iv +l er +Ä n ight +it ions +Ä J ohn +a pe +pl ay +Ä d one +Ä l im +Ä work ing +Ä P res +or ld +e b +Ä C o +Ä b ody +ail s +ut es +Ä M r +Ä whe ther +Ä a uthor +ro p +Ä pro per +Ä se en +) ; +Ä f ac +Ä S u +Ä con d +it ing +Ä cour se +Ä  } +-------- -------- +a ign +Ä ev ent +Ä en g +Ä p ot +Ä in tern +i am +Ä sh ort +em pt +ÃŖ Ĥ +Ä G od +il ar +8 0 +Ä or ig +I S +our n +ab ility +it ive +Ä d am +Ä 1 00 +Ä p ress +Ä do ing +Ä prot ect +r ing +Ä though t +Ä quest ion +re w +Ä W ar +Ä sever al +Ä St ate +Ä g iven +Ä f und +Ä T w +Ä w ent +an ces +w ork +p or +m y +4 0 +Ä ar g +art ment +ust om +Ä pol ic +Ä me et +Ä c reat +2 2 +Ä St ates +Ä g ames +ra w +ut ure +Ä under stand +ur s +Ä O b +l ish +s y +Ä m akes +Ä w on +ag on +Ä h tt +Ä l ove +ent ial +Ä comple te +p ar +Ä I m +A L +Ä acc ount + ł +ore d +ver t +Ä  ident +Ä 201 5 +Ä other s +Ä M in +i ber +ver age +The re +ition al +d d +Ä pro b +Ä you ng +Ä al ong +Ä acc ording +Ä y et +Ä mem bers +Ä Wh at +o id +Ä M an +A nd +Ä am ong +a i +Ä em ploy +Ä R es +Ä  > +Ä inv ol +Ä l ow +a f +Ä C ar +Ä h ig +Ä O ne +Ä S ec +in ation +Ä like ly +Ä an t +ag ed +Ä R uss +Ä b en +Ä re le +F or +b ack +Ä N ot +Ä pres ident +b all +Ä acc ess +ivid ual +Ä D em +Ä E uro +6 0 +Ä kn own +ir l +Ä G r +Ä ear ly +u se +iet y +ÃĸÄĸ Äĩ +Ä f ight +Ä s ent +Ä to day +Ä mark et +" . +Ä b ased +Ä str ong +ur ther +Ä de b +m ber +Ä proble m +Ä de ath +Ä soc ial +im ate +A S +ort un +Ä camp aign +er y +C h +Ä e y +i ally +Ä m us +w h +p os +Ä  er +Ä sa f +Ä month s +ir on +Ä v iol +Ä f ive +Ä st re +Ä play ers +in c +al d +y ear +a un +Ä su ccess +Ä pres ent +ere nce +Ä 201 4 +Ä su gg +Ä partic ular +Ä tr y +Ä sugg est +Ä Ch rist +on es +Ä pri v +2 3 +Ä c rit +Ä l and +Ä loc al +if y +2 9 +Ä a ut +E D +Ä G u +Ä m ult +Ä polit ical +Ä ask ed +Ä for mer +it ter +ri pt +Ä cl ose +Ä p ract +Ä Y ork +Ä get ting +Ä ac ross +Ä com b +Ä belie ve +Ä  z +Ä to get +Ä toget her +Ä C ent +ir c +Ä ind ividual +Ä M c +2 7 +is k +Ä E ng +Ä f ace +Ä 2 4 +Ä val ue +Ä are a +e v +Ä w rit +Ä Pres ident +Ä v ot +Ä ke y +Ä m om +p ut +Ä any thing +Ä exper ience +att le +Ä m ind +a ff +om m +Ä f uture +g ed +Ä c ut +Ä to t +it ch +Ä v ideo +Ä invest ig +Ä n et +Ä M y +r ict +i en +. ) +Ä imp ro +th ough +ward s +Ä con nect +Ä M ed +sel ves +ens ive +m b +o ber +at ors +A n +Ä 5 0 +Ä re du +res ent +Ä ab ove +Ä f re +Ä Euro pe +s w +Ä am ount +Ä A pp +Ä e ither +Ä mil it +Ä an al +Ä f ail +Ä E n +al es +Ä spec ial +Ä bl ack +I T +c her +Ä look ing +Ä f ire +y n +Ä al most +o on +Ä stud y +Ä m iss +c hes +ro wn +Ä t re +Ä commun ity +Ä med ia +Ä f ood +Ä com es +Ä Un iversity +Ä sing le +Wh at +u ly +Ä h alf +ag ue +h od +Ä Rep ublic +Ä start ed +Ä qu ick +ot o +b ook +Ä iss ue +it or +Ä el se +Ä cons ider +2 6 +ro du +Ä t aken +2 8 +9 9 +Ä W ith +Ä tr ue +Ä w a +Ä tr ad +Ä ag o +Ä m ess +ie f +Ä add ed +o ke +Ä b ad +Ä f av +3 3 +Ä sim ilar +as k +Ä D on +Ä charact er +ort s +Ä H ouse +Ä report ed +Ä ty pe +v al +i od +Ä How ever +Ä t arg +Ä ent ire +pp ing +Ä hist ory +Ä l ive +ff ic +.... .... +ed eral +Ä tr ying +Ä disc uss +Ä H ar +ac es +l ished +Ä se lf +os p +re st +Ä ro om +el t +Ä f all +ol ution +Ä e t +Ä  x +Ä is n +Ä ide a +b o +Ä s ound +Ä D ep +Ä some one +ci ally +ull y +Ä f oc +Ä ob ject +if t +ap er +Ä play er +Ä r ather +Ä serv ice +as hing +Ä D o +Ä P art +ru g +m on +p ly +Ä m or +Ä not hing +Ä prov ide +I C +un g +Ä part y +Ä ex ist +Ä m ag +7 0 +Ä r ul +Ä h ouse +Ä beh ind +Ä how ever +Ä W orld +Ä s um +Ä app lic +Ä  ; +Ä fun ction +g r +Ä P ol +Ä fr ont +2 00 +Ä ser ies +Ä t em +Ä ty p +ill s +Ä o pt +Ä point s +Ä bel ow +itt ed +Ä spec ific +Ä 201 7 +um b +Ä r a +Ä pre vious +Ä pre t +re me +Ä c ustom +Ä cour t +Ä M e +Ä re pl +Ä who le +g o +c er +Ä t reat +Ä A ct +Ä prob ably +Ä le arn +end er +Ä A ss +Ä vers ion +n ow +Ä che ck +Ä C al +R E +min ist +O n +our ces +Ä ben ef +Ä d oc +Ä det er +Ä en c +Ä su per +Ä add ress +Ä v ict +Ä 201 3 +Ä me as +t r +Ä f ield +W hen +Ä sign ific +u ge +Ä fe at +Ä comm on +l oad +Ä be gin +Ä br ing +Ä a ction +er man +Ä desc rib +Ä ind ust +Ä want ed +ri ed +m ing +Ä att empt +4 5 +f er +Ä d ue +ress ion +# # +Ä sh all +Ä s ix +o o +Ä st ep +Ä p ub +Ä him self +Ä 2 3 +Ä c op +Ä d est +Ä st op +A C +ib ility +Ä l ab +ic ult +Ä hour s +Ä cre ate +Ä f urther +Ä Americ a +Ä C ity +Ä d ou +he ad +S T +Ä N orth +c ing +Ä n ational +u le +Ä In st +Ä t aking +Ä Q u +ir t +Ä re d +Ä rese arch +v iron +Ä G e +Ä bre ak +an a +Ä sp ace +ater ial +Ä rec ent +Ä A b +Ä gener al +Ä h it +Ä per iod +Ä every thing +ive ly +Ä ph ys +Ä say ing +an ks +Ä c ou +Ä c ult +ac ed +e al +u ation +Ä c oun +l u +Ä includ e +Ä pos ition +Ä A fter +Ä Can ad +Ä E m +Ä im m +Ä R ed +Ä p ick +Ä com pl +Ä m atter +re g +e xt +ang u +is c +o le +a ut +Ä comp et +e ed +f ect +Ä 2 1 +Ä S en +Ä The se +as ing +Ä can not +Ä in it +Ä rel ations +ac hed +Ä b ar +Ä 4 0 +Ä T H +Ä 201 2 +Ä v ol +Ä g round +Ä sec urity +Ä up d +il t +3 5 +Ä conc ern +Ä J ust +Ä wh ite +Ä seem s +Ä H er +pe cially +i ents +Ä ann oun +Ä f ig +ight s +Ä st ri +l ike +id s +Ä s us +Ä w atch +Ä  Ãĸ +Ä w ind +Ä C ont +Ä it self +Ä m ass +A l +y le +iqu e +Ä N ational +Ä ab s +Ä p ack +Ä out side +Ä an im +Ä p ain +et er +Ä man ag +du ct +og n +Ä  ] +Ä Se pt +se c +o ff +Ä J an +Ä f oot +ad es +Ä th ird +Ä m ot +Ä ev idence +int on +Ä th reat +a pt +pl es +c le +Ä l o +Ä de cl +Ä it em +med i +Ä rep resent +om b +am er +Ä signific ant +og raph +s u +Ä c al +i res +00 00 +I D +A M +Ä sim ply +Ä long er +Ä f ile +O T +c he +S o +ate g +or g +Ä H is +Ä en er +Ä d om +Ä up on +il i +": " +Ä them selves +Ä com ing +Ä qu ite +Ä diff icult +Ä B ar +il ities +re l +end s +c ial +6 4 +Ä wom an +ra p +y r +Ä ne cess +ip s +Ä te xt +Ä requ ire +Ä milit ary +Ä re view +Ä resp ons +7 5 +Ä sub ject +Ä inst ead +Ä iss ues +Ä g en +" ," +Ä min utes +Ä we ap +r ay +am ed +t ime +b l +H ow +Ä c ode +Ä S m +Ä hig her +Ä St e +r is +Ä p age +Ä stud ents +Ä In tern +Ä met hod +Ä A ug +Ä P er +Ä A g +Ä polic y +Ä S w +Ä ex ec +Ä ac cept +um e +rib ut +Ä word s +Ä fin al +Ä chang es +Ä Dem ocr +Ä friend s +Ä res pect +Ä e p +Ä comp an +iv il +Ä dam age +** ** +og le +viron ment +Ä ne g +ent al +Ä a p +Ä tot al +iv al +! " +l im +Ä need s +Ä ag re +Ä develop ment +Ä a ge +ip le +2 1 +Ä result s +Ä A f +S h +Ä g un +Ä Ob ama +ro ll +Ä  @ +Ä right s +Ä B rit +Ä run ning +Ä was n +Ä p ort +Ä r ate +Ä pret ty +Ä targ et +Ä sa w +Ä c irc +Ä wor ks +ic ro +al t +o ver +ww w +Th at +l ier +Ä every one +ud e +Ä p ie +idd le +ra el +Ä r ad +Ä bl ock +Ä w alk +T o +ÃŖ ÄŖ +n es +Ä A ust +a ul +ro te +Ä S outh +ess ion +op h +Ä show s +Ä s ite +Ä j o +Ä r isk +cl us +l t +Ä in j +id ing +Ä S pe +Ä ch all +ir m +Ä 2 2 +itt ing +st r +Ä h y +L E +ke y +Ä be gan +at ur +ashing ton +l am +Ä D av +b it +Ä s ize +Ä P ar +3 8 +ourn al +f ace +Ä dec ision +Ä l arg +Ä j ud +re ct +Ä contin ue +Ä O ct +ove red +Ä I nt +==== ==== +Ä p arent +Ä W ill +Ä eas y +Ä d rug +ang er +Ä s ense +Ä d i +id ay +Ä ener gy +ist ic +Ä ass oci +ar ter +ob al +e ks +Ä E l +ur ch +Ä g irl +o e +it le +Ä 2 8 +Ä C he +Ä requ est +Ä so on +Ä h ost +k y +Ä st ates +om es +Ä m aterial +le x +Ä mom ent +Ä an sw +on se +Ä es pecially +Ä n orm +Ä serv ices +p ite +r an +Ä ro le +4 4 +) : +Ä c red +C l +____ ____ +Ä m at +Ä l og +Ä Cl inton +O U +Ä off ice +Ä 2 6 +Ä ch arg +Ä tr ack +m a +Ä he art +Ä b all +Ä person al +Ä build ing +n a +s et +b ody +Ä Bl ack +Ä incre ase +itt en +Ä need ed +3 6 +3 2 += " +Ä l ost +Ä bec ame +Ä grou ps +Ä M us +Ä w rote +Ä P e +Ä pro p +j oy +Ã Š +Ä Wh ite +Ä de ad +. ' +Ä htt p +Ä we bs +O S +Ä ins ide +Ä wr ong +Ä stat ement +Ä  ... +y l +Ä fil m +Ä mus ic +Ä sh are +ific ation +Ä re lease +Ä for ward +Ä st ay +Ä comp ut +it te +s er +Ä orig inal +Ä c ard +Ä c and +Ä d iv +at ural +Ä fav or +O M +Ä c ases +us es +Ä se ction +Ä le ave +g ing +ov ed +Ä W ashington +3 9 +Ä G l +Ä requ ired +act ion +ap an +o or +it er +Ä K ing +Ä count ries +Ä G erman +ll ing +Ä 2 7 +3 4 +Ä quest ions +Ä pr im +Ä c ell +Ä sh oot +Ä any one +Ä W est +Ä aff ect +ep end +Ä on line +Ä Is rael +Ä Sept ember +Ä ab ility +Ä cont ent +is es +Ä re ve +Ä l aun +Ä ind ic +Ä for ce +c ast +Ä so ld +av ing +f l +Ä so ft +Ä compan ies +ce ed +Ä art icle +Ä a ud +Ä re v +Ä ed uc +Ä play ing +0 5 +Ä he ld +ct or +Ä rele ased +Ä f ederal +3 7 +Ä ad minist +Ä inter view +Ä inst all +Ä rece ived +Ä s ource +u k +P h +Ä ser ious +Ä cre ated +Ä c ause +Ä im medi +Ä def in +u el +Ä Dep artment +ct ions +Ä C our +Ä N ow +z e +it es +it ution +Ä l ate +Ä spe ak +n ers +Ä leg al +ar i +Ä C or +Ä we eks +Ä mod el +Ä p red +Ä ex act +B C +Ä B y +IN G +os ing +Ä t akes +Ä reg ard +Ä opp ortun +Ä pr ice +Ä 19 8 +Ä A pr +f ully +Ä or d +Ä proble ms +ru ction +h am +Ä C ount +le ge +Ä lead ers +E T +le v +Ä de ep +olog ical +es e +h aps +Ä S ome +Ä p ers +Ä cont ract +Ä relations hip +s p +ou d +Ä b ase +4 8 +m it +A d +anc ial +Ä cons um +Ä pot ential +Ä l angu +re m +et h +Ä rel ig +ress ed +6 6 +Ä l ink +Ä l ower +ay er +Ä J une +Ä f em +un t +er c +ur d +Ä cont act +Ä  ill +Ä m other +Ä est ab +h tt +Ä M arch +Ä B ro +Ä Ch ina +Ä 2 9 +Ä s qu +Ä prov ided +Ä a verage +as ons +Ä 201 1 +Ä ex am +l in +5 5 +n ed +Ä per fect +Ä t ou +al se +u x +Ä bu y +Ä sh ot +Ä col lect +Ä ph ot +Ä play ed +Ä sur pr +Ä official s +Ä sim ple +av y +Ä indust ry +Ä hand s +g round +Ä p ull +Ä r ound +Ä us er +Ä r ange +u ary +Ä priv ate +op s +e es +Ä w ays +Ä M ich +Ä ve h +Ä ex cept +Ä ter ms +im um +pp er +I ON +ore s +Ä Dr agon +ou l +Ä d en +Ä perform ance +Ä b ill +c il +4 7 +Ä en vironment +Ä ex c +ad d +Ä wor th +Ä p ict +Ä ch ance +Ä 201 8 +b or +Ä spe ed +ict ion +Ä al leg +Ä J apan +at ory +re et +Ä m atch +Ä I I +Ä st ru +ord er +Ä st e +Ä l iving +Ä st ruct +in o +Ä se par +her n +Ä resp onse +Ä en joy +Ä v ia +A D +um ents +ace book +Ä mem ber +ib r +iz ing +Ä to ol +Ä M on +Ä Wh ile +h ood +Ä A ng +Ä D ef +Ä off er +T r +a ur +Ä turn ed +Ä J uly +d own +an ced +Ä rec ently +Ä E ar +Ä c e +Ä St ar +Ä C ong +rough t +Ä bl ood +Ä hop e +Ä com ment +ain t +Ä ar ri +il es +Ä partic ip +ough t +ri ption +0 8 +4 9 +Ä g ave +Ä se lect +Ä kill ed +sy ch +Ä go es +i j +Ä c oll +Ä imp act +at ives +Ä S er +0 9 +Ä Aug ust +Ä b oy +d e +Ä D es +Ä f elt +U S +Ä expect ed +Ä im age +Ä M ark +cc ording +o ice +E C +Ä M ag +en ed +h old +Ä P ost +Ä pre vent +N o +Ä invol ved +Ä ey es +Ä quick ly +A t +un k +Ä beh av +Ä  ur +Ä l ed +c ome +e y +Ä cand id +Ä ear lier +Ä foc us +et y +P ro +led ge +ix ed +ill ed +Ä pop ular +A P +Ä set t +l ight +Ä var ious +in ks +Ä level s +Ä ro ad +ell ig +ab les +he l +itte e +Ä G ener +y pe +Ä he ard +ic les +Ä m is +Ä us ers +Ä S an +Ä impro ve +Ä f ather +Ä se arch +The y +v il +Ä prof ess +Ä kn ew +Ä l oss +Ä ev ents +6 5 +Ä b illion +0 7 +0 2 +Ä New s +Ä A M +Ä co ver +w here +ens ion +Ä b ott +Ä are as +en ces +op e +Ä Tw itter +a el +Ä get s +Ä Go ogle +Ä s n +i ant +Ä v ote +Ä near ly +Ä includ ed +Ä rec ogn +z z +m m +al ed +Ä happen ed +0 4 +Ä h ot +Ä who se +Ä c ivil +Ä su ff +o es +it iz +Ä Sy ri +Ä resp ond +Ä h on +Ä feat ures +Ä econom ic +Ä Apr il +r im +Ä techn ology +Ä o ption +ag ing +Ä pur ch +R e +Ä l at +ch ie +is l +Ä rec omm +u f +Ä tr aining +Ä effect s +Ä f ast +Ä 201 0 +Ä occ ur +Ä webs ite +Ä em ail +Ä s ens +e ch +Ä o il +Ä inf lu +Ä current ly +Ä S ch +Ä Ad d +Ä go al +Ä sc ient +Ä con v +1 00 +em y +Ä dec ided +Ä tra vel +Ä m ention +L L +0 3 +Ä e lection +Ä ph one +Ä look s +Ä sit uation +Ä c y +Ä h or +b ed +Ä Cour t +a ily +av es +Ä qu ality +Ä Com p +w ise +Ä t able +Ä st aff +Ä W ind +et t +Ä tri ed +ide red +Ä add ition +Ä b ox +Ä l ack +ar ily +Ä w ide +Ä m id +Ä bo ard +ys is +Ä ant i +h a +Ä d ig +en ing +Ä d ro +C on +6 8 +Ä sl ow +b ased +se qu +Ä p ath +E x +ak er +Ä work ed +Ä p en +Ä eng ine +Ä look ed +Ä Su per +Ä S erv +Ä vict im +U n +Ä proper ty +Ä int rodu +Ä exec ut +Ä P M +L e +Ä col or +Ä M ore +Ä 6 0 +Ä net work +Ä d ate +c ul +id ge +Ä ext ra +3 1 +Ä s le +6 7 +Ä w ond +Ä report s +j ust +Ä Aust ral +Ä cap ital +Ä en s +Ä comm and +Ä allow ed +Ä pre p +Ä ca pt +h ib +Ä num bers +ch an +Ä f air +m p +om s +Ä re ach +W ith +t ain +Ä bro ad +Ä cou ple +ec ause +ly ing +Ä F eb +Ä sc reen +Ä l ives +Ä pri or +Ä Cong ress +A r +Ä appro ach +Ä e mer +ar ies +Ä D is +s erv +Ä N e +Ä bu ilt +c ies +Ä re pe +Ä rul es +for ce +Ä P al +Ä fin ancial +Ä cons idered +Ä Ch ar +n ces +Ä I S +Ä b rought +Ä b i +i ers +Ä S im +O P +Ä product s +Ä vis it +Ä doc ument +Ä con duct +Ä complete ly +in ing +Ä Cal if +ib ly +Ä wr itten +Ä T V +em ents +Ä d raw +O ne +Ä pub lished +Ä sec ret +r ain +he t +Ä F acebook +ond ay +Ä U p +Ä sex ual +Ä th ous +Ä P at +Ä  ess +Ä stand ard +Ä ar m +g es +ect ion +Ä f ell +Ä fore ign +an i +Ä Fr iday +Ä reg ular +in ary +Ä incre ased +Ä us ually +Ä dem on +Ä d ark +Ä add itional +ro l +Ä O f +Ä produ ction +! ! +und red +Ä intern ational +id ents +Ä F ree +rou p +Ä r ace +Ä m ach +Ä h uge +A ll +le ar +ove mber +Ä to wn +Ä att ention +Ä O ff +y ond +Ä The n +f ield +Ä ter ror +ra z +Ä B o +Ä meet ing +Ä P ark +Ä ar rest +Ä f ear +Ä a w +Ä V al +or ing +' , +Ä ext reme +ar r +Ä work ers +A fter +Ä 3 1 +n et +am ent +Ä direct ly +Ä pop ulation +ub e +Ä Oct ober +Ä I N +Ä Jan uary +5 9 +Ä Dav id +Ä c ross +ce mber +Ä F irst +Ä mess age +ir it +Ä n ation +Ä p oll +is ions +Ä answ er +n y +is ode +Ä car ry +Ä Russ ia +Ä he ar +eng th +ro y +Ä n atural +in ally +Ä do g +m itted +Ä tr ade +Ä sub st +Ä mult iple +Ä Af ric +Ä f ans +Ä s ort +Ä gl obal +ic ation +Ä W ed +ar a +Ä a chie +Ä langu age +ve y +Ä t al +Ä necess ary +Ä det ails +Ä s en +Ä S und +Ä Re g +Ä R ec +0 6 +Ä s il +ress ive +Ä med ical +un ch +orn ia +Ä u nd +f ort +oc ks +Ä M onday +ues day +c raft +7 7 +ur t +Ä  ver +Ä H ill +Ä rece ive +Ä mor ning +es tern +Ä b ank +Ä s at +ir th +Ä H igh +Ä dev ice +Ä TH E +Ä Cent er +Ä saf e +Ä p le +Ä Canad a +Ä system s +Ä ass ist +Ä sur v +Ä b attle +Ä S oc +vert is +S he +Ä p aper +Ä grow th +Ä c ast +S c +Ä pl ans +ll ed +Ä part s +Ä w all +Ä move ment +Ä pract ice +im ately +Ä dis play +Ä somet imes +om p +Ä P aul +Ä Y es +k ing +5 8 +o ly +Ä s on +Ä av oid +ok es +Ä J ew +Ä to wards +as c +Ä  // +Ä K ore +Ä talk ing +Ä cor rect +Ä sp ent +ic ks +i able +e ared +Ä ter m +Ä want s +om ing +Ä  ut +Ä dou b +Ä for ces +Ä p lease +6 9 +Ä N ovember +at form +ond on +Ä on es +Ä immedi ately +Ä Russ ian +Ä M et +Ä de g +Ä parent s +C H +Ä Americ ans +al y +Ä M od +Ä sh own +Ä cond itions +Ä st uff +Ä re b +Ä Y our +Ä includ es +n own +Ä S am +Ä exper ien +m ission +Ä E ven +augh t +Ä announ ced +Ä Republic an +Ä deter min +Ä describ ed +Ä Count y +( ) +Ä do or +Ä chang ed +Ä ne igh +Ä H ere +Ä cle an +Ä p an +Ä De cember +Ä Europe an +ir ing +ap ter +Ä cl ub +Ä T uesday +Ä p aid +Ä N et +Ä attack s +Ä charact ers +Ä al one +Ä direct or +d om +Ä 3 5 +Ä l oad +Ä r out +Ä Calif ornia +Ä fin ally +Ä r ac +Ä cont r +Ä exact ly +res h +p ri +Ä Is lam +Ä n ature +Ä care er +Ä lat est +Ä con vers +Ä S l +p ose +ci ent +Ä In c +iv ity +8 8 +Ä A tt +Ä M or +nes day +Ä we ight +k en +Ä not e +Ä team s +Ä  \ +air s +Ä G reen +Ä h undred +on ent +Ä stre ng +Ä cons ist +ic ated +Ä reg ul +Ä l ic +ast ic +Ä t en +urs day +ellig ence +ous ly +Ä U K +B I +Ä cost s +Ä ind epend +Ä A P +Ä norm al +Ä h om +Ä ob vious +Ä s we +Ä st ar +Ä read y +ac her +Ä imp lement +g est +Ä s ong +Ä G et +Ä L ab +Ä interest ing +us ing +Ä g iving +Ä Sund ay +Ä et c +Ä m iddle +Ä rem ember +r ight +os ition +ut ions +Ä m ax +4 6 +Ä your self +Ä dem and +Ä treat ment +Ä d anger +Ä C ons +Ä gu y +Ä Brit ish +Ä phys ical +Ä rel ated +Ä rem ain +Ä could n +Ä ref er +Ä c itiz +b ox +EN T +bo ard +Ä in n +I G +er o +Ä St reet +osp ital +ren ch +cher s +Ä st ra +O L +ag er +Ä A N +Ä eas ily +I A +en ge +in y +Ä cl os +ock ed +Ä us es +Ä C oun +I m +u ild +? ? +m ore +Ä an g +Ä wr ite +ol ute +5 7 +Ä lead er +Ä read ing +< / +Ä aut om +est s +4 3 +Ä leg isl +Ä G old +Ä design ed +Ä S T +Ä Le g +a res +Ä be aut +Ä T ex +Ä appear s +Ä stru gg +Ä R om +Ä  00 +Ä cho ice +Ä particular ly +Ä F rom +op er +Ä L ondon +ann ed +Ä allow s +ob ile +Ä differe nce +ÃĸÄĸ Âĸ +Ä V iew +Ä Wed nesday +Ä al though +Ä rel ative +Ä applic ation +ate ver +Ä are n +Ä my self +Ä im ag +Ä dis e +Ä soc iety +Ä fre qu +Ä Eng lish +Ä po or +Ä D ay +Ä writ ing +Ä se ven +Ä start ing +Ä b ud +Ä pr int +Ä Tr ans +uf act +Ä St ud +n ew +Ä cr im +Ä g ives +Ä co ol +a e +i ance +Ä Gener al +Ä think ing +Ä sa ve +Ä lim ited +Ä Part y +Ä mean ing +p en +ow ers +Ä J ack +E M +Ä n ice +ru pt +Ä g as +Ä e ight +Ä fe et +Ä eff ort +Ä  ign +ic it +B l +co in +Ä op in +Ä br ain +Wh ile +he st +Ä Th ursday +Ä would n +augh ter +Ä tou ch +le ments +Ä stud ies +Ä cent er +c ont +or ge +Ä comput er +Ä investig ation +P l +or ks +Ä 200 8 +Ä incre asing +Ä st ore +Ä com ments +Ä b al +m en +Ä do ll +Ä l iber +Ä w ife +Ä law s +atur day +it ness +Ä mod ern +Ä S k +Ä administ ration +Ä opportun ity +Ä s al +Ä power ful +M y +Ä claim s +Ä Ear th +ord s +Ä t itle +Ä es c +n ame +N ot +om en +Ä be yond +Ä c amer +Ä se ll +it ute +ear ch +Ä app l +im ent +4 2 +Ä Ar t +Ä un f +Ä viol ence +ur g +Ä E ast +Ä comp ared +Ä opt ions +Ä through out +Ä v s +ig r +. [ +ac hes +7 8 +Ä fil es +F L +E L +ar ian +Ä J ames +Ä A ir +an ch +Ä det ail +Ä pie ce +P S +Ä n amed +Ä educ ation +Ä dri ve +Ä item s +Ä stud ent +ic ed +: : +ic o +Ä th row +Ä sc ene +Ä comple x +Ä 200 9 +Ä pre c +Ä B re +7 9 +Ä con cept +Ä stat us +am ing +Ä d ied +Ä know ledge +Ä begin ning +O D +ru ary +Ä certain ly +Ä gu ys +Ä sl ight +in n +ound s +Ä f ine +Ä f at +ic ations +Ä per haps +Ä A nt +Ä inc ome +Ä htt ps +Ä major ity +port s +st on +Ä great er +Ä fe ed +ent ially +Ä saf ety +Ä un ique +and om +Ä g one +Ä show ed +Ä hist or +Ä coun ter +i us +id a +Ä lead ing +i pe +Ä s end +Ä Don ald +er ve +Ä def ense +ines e +Ä y es +Ä F ire +Ä Mus lim +ra q +Ä contin ued +os h +Ä prov ides +Ä pr ison +Ä P re +Ä happ y +Ä econom y +Ä tr ust +ag s +Ä G ame +Ä weap ons +um an +Ä C le +it ation +Ä anal ysis +Ä T imes +Ä sc ience +- > +Ä fig ure +Ä dis app +ent y +Ä soft ware +Ä u lt +Ä offic ers +N ew +I s +Ä rem ains +Ä Ind ia +Ä p sych +ri ef +Ä c at +es c +Ä ob serv +Ä st age +Ä D ark +Ä ent er +ch ange +Ä pass ed +Ä des pite +Ä O ut +Ä mov ie +r s +Ä v oice +m ine +Ä Pl ay +Ä to ward +Ä T er +Ä reg ion +Ä val ues +or ters +Ä m ount +Ä offic er +Ä O ther +b an +Ä h ous +w ood +ro om +I V +Ä S un +se e +Ä O ver +ro g +9 0 +Ä l ay +Ä T ur +a wn +Ä press ure +Ä S ub +Ä book s +ed om +Ä S and +A A +ag o +Ä re asons +f ord +Ä activ ity +U T +N ow +Ä Sen ate +ce ll +n ight +Ä call s +in ter +Ä let ter +Ä R ob +Ä J e +Ä cho ose +Ä L aw +G et +B e +Ä ro b +Ä typ es +Ä pl atform +Ä qu arter +R A +Ä T ime +Ä may be +Ä C r +9 5 +p re +Ä mov ing +Ä l if +Ä go ld +Ä s om +Ä pat ients +Ä tr uth +Ä K e +ur ance +ant ly +m ar +Ä char ge +Ä G reat +Ä ce le +---------------- ---------------- +Ä ro ck +ro id +an cy +Ä cred it +a ud +B y +Ä E very +Ä mov ed +ing er +rib ution +Ä n ames +Ä stra ight +Ä He alth +Ä W ell +Ä fe ature +Ä r ule +Ä sc he +in ated +Ä Mich ael +ber g +4 1 +il ed +b and +Ä cl ick +Ä Ang el +on ents +Â Ń +Ä I raq +Ä S aturday +Ä a ware +p art +Ä pat tern +O W +Ä L et +Ä gr ad +ign ed +Ä associ ated +Ä st yle +n o +i ation +a ith +il ies +Ä st ories +ur ation +Ä individual s +Ä ÃĸÄĸ ÂĻ +m iss +Ä Ass oci +ish ing +ab y +Ä sum mer +Ä B en +Ä 3 2 +Ä ar ch +ut y +Ä Tex as +h ol +Ä full y +Ä m ill +Ä follow ed +Ä B ill +Ä Ind ian +Ä Sec ret +Ä B el +Ä Feb ruary +Ä job s +Ä seem ed +Ä Go vern +i pped +Ä real ity +Ä l ines +Ä p ark +Ä meas ure +Ä O ur +I M +Ä bro ther +Ä grow ing +Ä b an +Ä est im +Ä c ry +Ä S chool +Ä me chan +Ä O F +Ä Wind ows +Ä r ates +Ä O h +Ä pos itive +Ä cult ure +ist ics +ic a +Ä h ar +y a +ite ly +i pp +Ä m ap +en cies +Ä Will iam +I I +ak ers +5 6 +Ä M art +Ä R em +Ä al tern +it ude +Ä co ach +row d +D on +Ä k ids +Ä j ournal +Ä cor por +Ä f alse +Ä we b +Ä sle ep +Ä cont ain +Ä st o +Ä b ed +iver se +Ä R ich +Ä Ch inese +Ä p un +Ä me ant +k nown +Ä not ice +Ä favor ite +a ven +Ä cond ition +Ä pur pose +) ) +Ä organ ization +Ä chall eng +Ä man ufact +Ä sus p +Ä A c +Ä crit ic +un es +uc lear +Ä m er +vent ion +Ä 8 0 +Ä m ist +Ä U s +Ä T or +htt p +ol f +Ä larg er +Ä adv ant +Ä rese ar +Ä act ions +m l +Ä ke pt +Ä a im +, ' +c ol +Ä benef its +if ying +Ä act ual +Ä Intern ational +Ä veh icle +Ä ch ief +Ä eff orts +Ä Le ague +Ä M ost +Ä wa it +Ä ad ult +Ä over all +Ä spe ech +Ä high ly +Ä fem ale +Ä er ror +Ä effect ive +5 4 +Ä enc our +w ell +Ä fail ed +Ä cons erv +Ä program s +Ä t rou +Ä a head +5 00 +vertis ement +I P +Ä F ound +p ir +Ä  % +Ä cr ime +and er +Ä loc ation +Ä I ran +Ä behav ior +az ing +Ä r are +Ä em b +Ä ca used +Ä sh ip +Ä act ive +Ä cont ribut +Ä g reen +Ä ac qu +Ä ref lect +ven ue +Ä f irm +Ä b irth +] . +Ä clear ly +Ä em ot +Ä ag ency +ri age +Ä mem ory +9 8 +S A +Ä Se e +ac ing +C C +Ä big gest +Ä r ap +Ä bas ic +Ä b and +e at +Ä sus pect +Ä M ac +Ä 9 0 +m ark +ist an +Ä sp read +am s +k i +as y +ra v +Ä R ober +Ä demon str +r ated +Ä abs olute +Ä pl aces +Ä im pl +ibr ary +Ä c ards +Ä dest roy +Ä v irt +ve re +Ä app eared +y an +p oint +Ä be g +Ä tem per +s pe +ant ed +ear s +Ä D irect +Ä l ength +Ä bl og +am b +Ä int eg +Ä res ources +ac c +if ul +Ä sp ot +Ä for ced +Ä thous ands +Ä Min ister +Ä qu al +Ä F rench +at ically +Ä gener ally +Ä dr ink +Ä th us +I L +od es +Ä appro pri +Ä Re ad +Ä wh om +Ä ey e +Ä col lege +Ä 4 5 +ire ction +Ä ens ure +Ä app arent +id ers +Ä relig ious +Ä min or +ol ic +Ä t ro +Ä Wh y +rib ute +m et +Ä prim ary +Ä develop ed +Ä pe ace +Ä sk in +st e +av a +Ä bl ue +Ä fam ilies +Ä  ir +Ä app ly +Ä in form +Ä Sm ith +C T +i i +Ä lim it +Ä res ist +........ ........ +um n +Ä conf lic +Ä tw e +ud d +Ä T om +Ä l iter +qu e +b on +Ä ha ir +Ä event ually +Ä p us +Ä help ed +Ä ag g +or ney +Ä App le +Ä f it +Ä S ur +Ä pre m +Ä s ales +Ä second s +Ä streng th +Ä feel ing +Âŋ ÂŊ +Ä t our +Ä know s +o om +Ä ex erc +Ä som ew +ï ÂŋÂŊ +> > +Ä sp okes +Ä ide as +Ä reg ist +so ft +Ä D el +Ä P C +Ä pro pos +Ä laun ch +Ä bott om +T H +Ä P lease +v est +it z +Ä In ter +Ä sc ript +Ä r at +ar ning +Ä  il +Ä J er +Ä A re +Ä wh atever +ok en +ci ence +Ä mod e +Ä ag ree +Ä s ources +Ä init ial +Ä rest rict +Ä wond er +us ion +## ## +Ä S il +vil le +Ä b urn +t w +as ion +ĠÂ ÂŖ +Ä n or +u ing +Ä re ached +Ä s un +Ä c ateg +ig ration +Ä c ook +Ä prom ot +Ä m ale +Ä cl imate +Ä f ix +Ä alleg ed +U R +all ed +Ä im ages +C ont +ot a +Ä school s +i os +Ä d rop +Ä st ream +Ä M o +Ä previous ly +al ing +Ä p et +Ä dou ble +Ä ( @ +ann el +Ä def ault +t ies +Ä r ank +Ä D ec +Ä Coun cil +Ä weap on +Ä st ock +Ä anal y +Ä St r +Ä pict ure +Ä Pol ice +f erence +Ä cent ury +Ä citiz ens +Ä on to +Ä exp and +Ä he ro +Ä S ol +Ä w ild +Ä upd ate +Ä custom ers +r ont +d ef +Ä l ik +Ä crim inal +Ä Christ ian +S P +7 6 +Ä le aving +Ä other wise +Ä D ist +Ä bas is +5 2 +5 3 +ic ip +Ä B er +Ä recomm end +Ä fl oor +Ä c rowd +ol es +Ä 7 0 +Ä cent ral +Ä E v +Ä d ream +Ä down load +Ä conf ir +Ä Th om +Ä wind ow +Ä happ ens +Ä un it +Ä t end +Ä s pl +Ä bec omes +Ä fight ing +Ä pred ict +Ä P ress +Ä P ower +Ä he avy +ak ed +Ä f an +or ter +ate gy +B A +iz es +Ä sp end +H ere +Ä 200 7 +Ä ad op +Ä H am +Ä foot ball +Ä P ort +od ay +5 1 +amp ions +Ä trans fer +h t +Ä 3 8 +ter m +ac ity +Ä b ur +] , +tern al +r ig +b ut +Ä there fore +Ä B ecause +res p +re y +Ä m ission +S ome +Ä not ed +Ä ass um +Ä dise ase +Ä ed it +Ä prog ress +r d +Ä B rown +oc al +Ä add ing +Ä ra ised +Ä An y +Ä t ick +Ä see ing +Ä Pe ople +Ä agre ement +Ä ser ver +Ä w at +Ä deb ate +Ä supp osed +il ing +Ä larg est +Ä success ful +Ä P ri +Ä Democr atic +Ä j ump +Ä Syri a +Ä own ers +Ä off ers +Ä shoot ing +Ä eff ic +se y +Ä ha ven +ver se +te red +Ä L ight +im al +Ä B ig +Ä def end +Ä be at +Ä record s +% ) +Ä sc en +Ä employ ees +Ä dev ices +he m +Ä com mer +Ä M ex +Ä benef it +Ä Pro f +Ä il leg +Ä sur face +Ä Al so +Ä h arm +ing ly +w ide +Ä A lex +Ä sh ut +Ä C ur +Ä l ose +p m +Ä chall enge +se mb +Ä st ation +Ä int elligence +Ä acc ur +Ä Fl or +Ä requ ires +Ä M al +b um +Ä h ospital +Ä sp irit +Ä off ered +Ä produ ce +Ä Comm un +Ä creat ing +Ä cr is +s pect +Ä end ed +Ä d aily +Ä vot ers +land s +i as +i h +on a +Ä sm art +Ä Off ice +Ä L ord +ri al +Ä Intern et +Ä circ um +Ä extreme ly +' . +Ä opin ion +Ä M il +Ä g ain +B S +Ä F in +y p +Ä use ful +Ä bud get +Ä com fort +is f +Ä back ground +el ine +Ä ep isode +Ä en emy +Ä tri al +Ä estab lish +d ate +Ä C ap +Ä contin ues +Ä show ing +Ä Un ion +w ith +Ä post ed +Ä Sy stem +Ä e at +ri an +Ä r ise +Ä German y +il s +Ä sign ed +Ä v ill +Ä gr and +m or +Ä Eng land +Ä project s +um ber +Ä conf erence +z a +Ä respons ible +Ä Ar ab +Ä learn ed +ÃĸÄĸÄļ ÃĸÄĸÄļ +i pping +Ä Ge orge +O C +Ä return ed +Ä Austral ia +Ä b rief +Q u +Ä br and +ill ing +ab led +Ä hig hest +Ä tr ain +Ä Comm ission +wh ile +Ä n om +cept ion +Ä m ut +Ä Bl ue +Ä inc ident +v ant +8 6 +Ä I D +Ä n uclear +7 4 +Ä L ike +Ä R E +Ä M icro +l i +m ail +Ä charg es +8 9 +Ä ad just +ad o +Ä ear th +N A +Ä pr ices +P A +Ä d raft +Ä run s +Ä candid ate +ens es +Ä manag ement +Ä Ph il +Ä M iss +Ä te ach +g ram +Ä understand ing +a it +ic ago +A dd +Ä E p +sec ut +Ä separ ate +Ä inst ance +Ä e th +Ä un less +**** **** +Ä F ore +in ate +Ä oper ations +S p +Ä f aith +g ar +Ä Ch urch +ron ic +Ä conf ig +os ure +Ä activ ities +Ä trad itional +Ä 3 6 +Ä d irection +Ä mach ine +Ä sur round +Ä p ush +un ction +Ä E U +Ä eas ier +Ä arg ument +G B +Ä m icro +Ä sp ending +iz ations +Ä the ory +ad ow +Ä call ing +Ä L ast +Ä d er +Ä influ ence +Ä comm it +Ä ph oto +Ä un c +ist ry +g n +ast e +ack s +Ä dis p +ad y +d o +Ä G ood +Ä  ` +Ä w ish +Ä reve aled +Âł Âł +l ig +Ä en force +Ä Comm ittee +Ä che m +Ä mil es +Ä interest ed +Ä sol ution +ic y +in ct +Ä - > +Ä D et +Ä rem oved +Ä comp ar +e ah +Ä pl ant +Ä S ince +Ä achie ve +Ä advant age +Ä slight ly +b ing +Ä pl aced +u nder +201 5 +Ä M ad +Ä t im +os es +Ä c ru +Ä R ock +Ä most ly +Ä neg ative +Ä set ting +Ä produ ced +Ä m ur +Ä connect ion +Ä M er +Ä dri ver +Ä execut ive +Ä ass ault +Ä b orn +Ä V er +t ained +Ä struct ure +Ä redu ce +Ä dec ades +Ä d ed +u ke +Ä M any +idd en +Ä le ague +S e +Ä jo in +Ä dis co +Ä d ie +c ks +act ions +Ä ass ess +ag n +Ä go als +our s +I R +Ä sen ior +ill er +m od +ip ment +oc ol +u y +Ä Q ue +Ä part ies +ir gin +Ä le arning +it able +Ä stre et +Ä camer a +A pp +Ä sk ills +b re +c ious +Ä cele br +Ä Fr anc +Ä exist ing +Ä will ing +l or +Ä  id +Ä Sp ace +Ä crit ical +Ä L a +ortun ately +Ä ser ve +Ä c old +Ä spec ies +T S +Ä anim als +Ä B ay +Ä old er +Ä U nder +est ic +Ä T re +Ä te acher +Ä pre fer +v is +Ä th read +Ä M att +Ä manag er +ÃŖÄĨ Âģ +Ä profess ional +Ä V ol +Ä not es +The se +ul a +Ä f resh +ent ed +u zz +ed y +clus ion +Ä R el +Ä doub t +E O +Ä open ed +Ä B it +Ad vertisement +Ä gu ess +Ä U N +Ä se qu +Ä expl ain +ott en +Ä att ract +ak s +Ä str ing +Ä cont ext +oss ible +Ä Republic ans +Ä sol id +Ä c ities +Ä ask ing +Ä r andom +u ps +ur ies +ar ant +dd en +g l +Ä Flor ida +Ä dep end +Ä Sc ott +Ä 3 3 +Ä i T +ic on +Ä mention ed +Ä 2 000 +Ä claim ed +Ä defin itely +ul f +Ä c ore +Ä open ing +Ä Con st +wh ich +Ä T ra +A G +7 2 +Ä belie ved +ad a +Ä 4 8 +Ä Sec urity +yr ight +Ä P et +Ä L ou +Ä hold ing +======== ======== +Ä  ice +Ä b row +Ä author ities +h ost +w ord +Ä sc ore +Ä D iv +Ä cell s +Ä trans l +Ä neigh bor +Ä rem ove +u ct +Ä dist rict +Ä A ccording +Ä wor se +Ä concern s +Ä president ial +Ä polic ies +Ä H all +7 3 +Ä h us +A Y +Ä 200 6 +Ä J ud +Ä independ ent +Ä Just ice +ili ar +pr int +igh ter +Ä protect ion +z en +Ä su dden +h ouse +Ä J es +P R +Ä In f +Ä b ul +Ä  _ +Ä Serv ice +Ä P R +Ä str ategy +ff ect +Ä girl s +Ä miss ing +oy al +Ä Te am +ul ated +Ä d at +Ä polit ics +ab or +A ccording +Ä spe ll +Ä g raph +ort hern +T C +A b +Ä lab or +is her +Ä k ick +Ä iT unes +Ä step s +pos es +Ä small er +E n +ber t +Ä ro ll +Ä resear chers +Ä cl osed +Ä trans port +Ä law y +________ ________ +Ä Ch icago +Ä as pect +Ä n one +Ä mar riage +9 6 +Ä e lements +Ä F re +Ä S al +Ä d ram +F C +t op +e qu +Ä he aring +Ä support ed +Ä test ing +co hol +Ä mass ive +Ä st ick +Ä gu ard +is co +ph one +F rom +How ever +Ä b order +Ä cop y +ograph y +l ist +7 1 +Ä own er +cl ass +ru it +r ate +Ä O nce +Ä dig ital +Ä t ask +ER S +Ä inc red +t es ++ + +Ä Fr ance +Ä b reat +ow l +Ä iss ued +Ä W estern +Ä det ect +Ä part ners +Ä sh ared +Ä C all +Ä can cer +ac he +rib e +Ä expl ained +Ä he at +{ " +Ä invest ment +Ä B ook +Ä w ood +Ä tool s +Ä Al though +Ä belie f +Ä cris is +Ä g e +Ä M P +Ä oper ation +ty pe +~ ~ +g a +Ä cont ains +ant a +Ä exp ress +Ä G roup +Ä J ournal +k a +Ä am b +Ä US A +Ä find ing +Ä fund ing +h ow +Ä estab lished +ide os +Ä deg ree +Ä danger ous +ang ing +Ä fre edom +pp ort +out hern +Ä ch urch +Ä c atch +Ä Tw o +Ä pres ence +Ä Gu ard +U p +Ä author ity +Ä Pro ject +Ä but ton +Ä con sequ +Ä val id +Ä we ak +Ä start s +Ä ref erence +Ä M em +" ) +U N +or age +Ä O pen +Ä col lection +y m +g ency +Ä beaut iful +ro s +Ä tell s +Ä wa iting +n el +Ä prov iding +Ä Democr ats +Ä d aughter +Ä m aster +Ä pur poses +Ä Japan ese +Ä equ al +Ä turn s +Ä doc uments +Ä watch ing +R es +Ä r an +201 4 +Ä re ject +Ä Kore a +Ä victim s +Le vel +ere nces +Ä w itness +Ä 3 4 +Ä re form +com ing +Ä occ up +Ä c aught +Ä tra ffic +ad ing +Ä mod els +ar io +Ä serv ed +Ä b atter +u ate +Ä Secret ary +Ä agre ed +Ä tr uly +yn am +Ä R et +Ä un its +Ä Res earch +h and +az ine +Ä M ike +Ä var iety +ot al +Ä am azing +Ä confir med +Ä entire ly +Ä purch ase +Ä e lement +Ä c ash +Ä deter mine +D e +Ä c ars +Ä W all +Ãĸ ĸ +Ä view s +Ä drug s +Ä dep artment +Ä St ep +u it +Ä 3 9 +as ure +Ä Cl ass +Ä c overed +Ä B ank +Ä me re +u ana +Ä mult i +Ä m ix +Ä un like +lev ision +Ä sto pped +Ä s em +Ä G al +ul es +Ä we l +Ä John son +l a +Ä sk ill +Ä bec oming +ri e +Ä appropri ate +f e +ell ow +Ä Pro t +ul ate +oc ation +Ä week end +od ies +Ä sit es +Ä anim al +Ä T im +Ä sc ale +Ä charg ed +Ä inst ruct +ill a +Ä method s +Ä c ert +Ä jud ge +Ä H el +Ä doll ars +Ä stand ing +Ä S qu +Ä deb t +l iam +Ä dri ving +Ä S um +Ä Ed ition +Ä al bum +and on +I F +Ä U k +6 3 +ad er +Ä commer cial +es h +Ä Govern ment +Ä disc overed +Ä out put +Ä Hill ary +Ä Car ol +Ä 200 5 +Ä ab use +anc ing +Ä sw itch +Ä ann ual +T w +Ä st ated +ag ement +in ner +Ä dem ocr +Ä res idents +Ä allow ing +Ä fact ors +od d +Ä f uck +em ies +Ä occur red +ot i +Ä n orth +Ä P ublic +Ä inj ury +Ä ins urance +C L +oll y +ÃŖ Äĸ +Ä repe ated +Ä ar ms +ang ed +Ä const ruction +Ä f le +P U +ic ians +Ä for ms +Ä Mc C +ant ic +Ä m ental +p ire +Ä equ ipment +Ä f ant +Ä discuss ion +Ä regard ing +k in +ar p +Ä ch air +og ue +Ä pro ceed +Ä I d +O ur +Ä mur der +M an +Ä 4 9 +as p +Ä supp ly +Ä in put +Ä we alth +liam ent +Ä pro ced +or ial +Ä St at +Ä N FL +hen s +Ä Inst itute +Ä put ting +ourn ament +et ic +Ä loc ated +Ä k id +er ia +r un +Ä pr inc +Ä  ! +go ing +Ä B et +Ä cl ot +Ä tell ing +Ä prop osed +i ot +or ry +Ä fund s +g ment +Ä L ife +Ä b aby +Ä B ack +Ä sp oke +Im age +Ä ear n +Ä A T +g u +Ä ex change +Ä L in +ov ing +Ä p air +M ore +az on +Ä arrest ed +Ä kill ing +c an +Ä C ard +y d +Ä ident ified +Ä m obile +Ä than ks +ony m +Ä F orm +Ä hundred s +Ä Ch ris +Ä C at +Ä tre nd +h at +Ä A v +om an +Ä elect ric +Ä W il +S E +O f +Ä rest aur +ot ed +Ä tr ig +Ä n ine +Ä b omb +Wh y + ¯ +Ä co verage +Ä app eal +Ä Rober t +Ä S up +Ä fin ished +Ä fl ow +Ä del iver +Ä cal cul +Ä phot os +Ä ph il +Ä pie ces +Ä app re +k es +Ä r ough +D o +Ä part ner +Ä concern ed +Ä 3 7 +Ä G en +C ol +ct ors +Ä = > +st ate +Ä suggest ed +Ä For ce +C E +Ä her self +Ä Pl an +w orks +o oth +ren cy +Ä cor ner +Ä hus band +Ä intern et +Ä A ut +em s +os en +Ä At l +g en +Ä bal ance +6 2 +Ä sound s +te xt +Ä ar r +ov es +Ä mill ions +Ä rad io +Ä sat isf +Ä D am +M r +G o +S pe +Ä comb at +r ant +Ä G ree +Ä f uel +Ä dist ance +Ä test s +Ä dec re +Ä E r +Ä man aged +D S +Ä t it +Ä meas ures +Ä L iber +Ä att end +as hed +Ä J ose +Ä N ight +d it +Ä N ov +Ä E nd +out s +Ä gener ation +Ä adv oc +y th +Ä convers ation +Ä S ky +act ive +ce l +ri er +Ä Fr ank +Ä g ender +Ä con cent +Ä car ried +and a +Ä V irgin +Ä arri ved +ic ide +ad ed +Ä fail ure +Ä min imum +le ts +Ä wor st +Ä keep ing +Ä int ended +Ä illeg al +Ä sub sc +Ä determin ed +Ä tri p +Y es +Ä ra ise +Ä  ~ +Ä feel s +Ä pack age +Ä J o +h i +201 6 +re al +Ä f ra +Ä sy mb +M e +uck y +p ret +Ä K h +Ä Ed it +Ä We b +em ic +Ä Col or +Ä just ice +I nt +Ä far m +ck now +" > +el ess +Ä redu ced +Ä 5 00 +x x +Ä R ad +Ä W ood +Ä cl in +Ä hy p +il er +ur a +k ins +8 5 +6 1 +Ä The ir +Ä M ary +Ä s an +Ä no vel +Ä Wh o +Ä cap acity +Ä imp ossible +Ä pl ays +Ä min ister +ij uana +ic ate +Ä S et +Ä f ram +Ä  ing +Ä commun ities +Ä F BI +it a +Ä b on +Ä str ateg +Ä interest s +l ock +g ers +m as +Ä AN D +Ä conflic t +Ä require ments +Ä s ac +Ä oper ating +in i +rel ated +Ä comm itted +Ä relative ly +Ä s outh +¯ ¯ +Ä aff ord +Ä ident ity +Ä dec isions +Ä acc used +pl ace +Ä vict ory +o ch +i at +N ame +C om +t ion +ed s +Ä see k +Ä t ight +Ä Im ages +Ä init i +Ä hum ans +Ä fam iliar +Ä aud ience +Ä intern al +vent ure +Ä s ides +Ä T O +Ä d im +Ä con clud +Ä app oint +Ä enforce ment +Ä J im +Ä Associ ation +Ä circum st +Ä Canad ian +Ä jo ined +Ä differe nces +Ä L os +Ä prot est +Ä tw ice +w in +Ä gl ass +ars h +Ä Ar my +Ä exp ression +Ä dec ide +Ä plan ning +an ia +Ä hand le +Ä Micro soft +Ä N or +Ä max imum +Ä Re v +Ä se a +Ä ev al +Ä hel ps +re f +Ä b ound +Ä m outh +Ä stand ards +Ä cl im +Ä C amp +Ä F ox +cl es +Ä ar my +Ä Te chn +ack ing +x y +S S +Ä 4 2 +Ä bu g +Ä Uk rain +Ä M ax +Ä J ones +Ä Sh ow +l o +Ä plan et +Ä 7 5 +Ä win ning +Ä f aster +Ä spe ct +Ä bro ken +T R +Ä def ined +Ä health y +Ä compet ition +htt ps +Ä Is land +Ä F e +Ä announ ce +Ä C up +Ä Inst ead +Ä cl ient +Ä poss ibly +se ction +ock et +l ook +Ä fin ish +Ä cre w +Ä res erv +Ä ed itor +Ä h ate +Ä s ale +Ä contro vers +Ä p ages +w ing +Ä num er +Ä opp osition +Ä 200 4 +Ä ref uge +Ä fl ight +Ä ap art +Ä L at +A meric +Ä Afric a +Ä applic ations +Ä Pal est +Ä B ur +Ä g ar +Ä Soc ial +Ä up gr +Ä sh ape +Ä spe aking +ans ion +a o +Ä S n +Ä wor ry +Ä Brit ain +P lease +rou d +Ä h un +Ä introdu ced +Ä d iet +I nd +Ä Sec ond +Ä fun ctions +ut s +Ä E ach +Ä Je ff +Ä st ress +Ä account s +Ä gu arant +Ä An n +ed ia +Ä hon est +Ä t ree +Ä Afric an +Ä B ush +} , +Ä s ch +Ä On ly +Ä f if +ig an +Ä exerc ise +Ä Ex p +Ä scient ists +Ä legisl ation +Ä W ork +Ä S pr +à Ĥ +Ä H uman +Ä  è +Ä sur vey +Ä r ich +ri p +Ä main tain +Ä fl o +Ä leaders hip +st ream +Ä Islam ic +Ä  01 +Ä Col lege +Ä mag ic +Ä Pr ime +Ä fig ures +201 7 +ind er +x ual +Ä De ad +Ä absolute ly +Ä four th +Ä present ed +resp ond +rib le +Ä al cohol +at o +Ä D E +por ary +Ä gr ab +Ä var i +Ä qu ant +Ä Ph oto +Ä pl us +r ick +ar ks +Ä altern ative +Ä p il +Ä appro x +th at +Ä object s +Ä R o +Ä And roid +Ä significant ly +Ä R oad +k ay +R ead +av or +Ä a cknow +Ä H D +Ä S ing +O r +Ä M ont +Ä un s +pro f +Ä neg oti +Ä Ar ch +ik i +Ä te levision +Ä Jew ish +Ä comm ittee +Ä mot or +Ä appear ance +Ä s itting +Ä stri ke +Ä D own +com p +Ä H ist +Ä f old +ac ement +Ä Lou is +Ä bel ong +Ä ÃĸÄĸ Âĸ +Ä m ort +Ä prep ared +Ä 6 4 +Ä M aster +Ä ind eed +Ä D en +Ä re nt +T A +our ney +ar c +S u +9 7 +Ä adv ice +Ä chang ing +Ä list ed +Ä laun ched +is ation +Ä P eter +is hes +Ä l ived +Ä M el +Ä Sup reme +Ä F ederal +Ä ) ; +ruct ure +Ä set s +Ä phil os +u ous +Ġ ł +Ä appl ied +Ä N OT +Ä hous ing +Ä M ount +Ä o dd +Ä su st +D A +ffic ient +Ä  ? +ol ved +Ä p owers +Ä th r +Ä rem aining +Ä W ater +L C +Ä ca uses +ÃŖÄŖ ÂŽ +Ä man ner +ad s +Ä suggest s +Ä end s +stand ing +f ig +Ä D un +id th +Ä g ay +Ä ter min +Ä Angel es +M S +Ä scient ific +Ä co al +ap ers +b ar +Ä Thom as +Ä sy m +Ä R un +th is +P C +igr ants +Ä min ute +Ä Dist rict +cell ent +Ä le aves +Ä comple ted +am in +Ä foc used +Ä mon itor +Ä veh icles +M A +Ä M ass +Ä Gr and +Ä affect ed +itution al +Ä const ruct +Ä follow s +Ä t on +re ens +Ä h omes +Ä E xt +Ä Le vel +r ast +Ä I r +Ä el im +Ä large ly +Ä J oe +Ä vot es +all s +Ä business es +Ä Found ation +Ä Cent ral +Ä y ards +Ä material s +ul ner +Ä gu ide +Ä clos er +um s +Ä sp orts +ed er +J ust +Ä tax es +8 4 +Ä O ld +Ä dec ade +ol a +Ä v ir +Ä dro pped +Ä del ay +it ect +Ä sec ure +ste in +le vel +Ä tre ated +Ä fil ed +ain e +Ä v an +Ä m ir +Ä col umn +ict ed +e per +Ä ro t +Ä cons ult +Ä ent ry +Ä mar ijuana +Ä D ou +Ä apparent ly +ok ing +clus ive +Ä incre ases +an o +Ä specific ally +Ä te le +ens ions +Ä relig ion +ab ilities +Ä fr ame +Ä N ote +Ä Le e +Ä help ing +Ä ed ge +ost on +Ä organ izations +à ÄĨ +Ä B oth +hip s +Ä big ger +Ä bo ost +Ä St and +Ä ro w +ul s +ab ase +Ä r id +L et +are n +ra ve +Ä st ret +P D +Ä v ision +Ä we aring +Ä appre ci +Ä a ward +Ä U se +Ä fact or +w ar +ul ations +) ( +Ä g od +Ä ter rit +Ä par am +ast s +8 7 +Ä en emies +Ä G ames +F F +Ä acc ident +W ell +Ä Mart in +T ER +Ä at h +Ä He ll +Ä for g +Ä ve ter +Ä Med ic +f ree +Ä st ars +Ä exp ensive +Ä ac ad +ra wn +Ä W he +Ä l ock +Ä form at +Ä sold iers +s m +Ä ag ent +Ä respons ibility +or a +Ä S cience +Ä rap id +Ä t ough +Ä Jes us +Ä belie ves +M L +Ä we ar +le te +ÃÄĨ ÃĤ +Ä D ri +Ä comm ission +Ä B ob +O h +ap ed +Ä war m +ÃÄĨÃĤ ÃÄĨÃĤ +Ä 200 3 +ort ion +Ä has n +ust er +Ä un ivers +Ä I ll +Ä k ing +olog ies +9 4 +Ä T em +Ä M os +Ä pat ient +Ä Mex ico +ce an +Ä De ath +Ä Sand ers +y ou +Ä C ast +Ä Comp any +pt y +Ä happen ing +F P +Ä B attle +Ä b ought +A m +M od +U s +ut ers +Ä C re +Ä Th ose +Ä 4 4 +is er +Ä s oul +Ä T op +Ä Har ry +Ä A w +Ä se at +ff ee +Ä rev olution +Ä ( " +Ä D uring +et te +Ä r ing +Ä off ensive +Ä return s +Ä v ideos +Ä dis cl +Ä fam ous +en ced +Ä S ign +Ä R iver +Ä 3 00 +P M +Ä B us +Ä C H +Ä candid ates +ard en +Ä percent age +Ä vis ual +Ä than k +Ä trou ble +ner gy +Ä 200 1 +Ä pro ve +ash ion +Ä en h +Ä L ong +U M +Ä connect ed +Ä poss ibility +O ver +Ä exper t +Ä l ibrary +art s +Ä Direct or +Ä fell ow +9 2 +ir ty +Ä d ry +Ä sign s +Ä L ove +Ä qu iet +f oot +Ä p ure +Ä H un +Ä f illed +ph as +Ä E lect +end ment +Ä Ex pl +Ä un able +n s +m o +Ä v ast +ob e +Ä ident ify +app ing +Ä Carol ina +g ress +Ä pro te +Ä f ish +Ä circumst ances +raz y +Ä Ph ot +Ä b odies +Ä M ur +Ä develop ing +Ä A R +Ä experien ced +Ä subst ant +Ä Bo ard +es ome +Ä dom estic +Ä comb ined +Ä P ut +Ä chem ical +Ä Ch ild +Ä po ol +Ä C y +Ä e gg +c ons +st ers +Ä h urt +Ä mark ets +Ä conserv ative +Ä supp orters +Ä ag encies +id el +O b +ur b +Ä 4 3 +Ä Def ense +y e +Ä A p +du le +Ä temper ature +Ä conduct ed +Ä Ch ief +Ä pull ed +Ä f ol +L ast +ont o +os is +V ER +D es +Ä P an +F irst +Ä adv ance +Ä lic ense +r ors +Ä J on +Ä imag ine +Ä he ll +Ä f ixed +Ä inc or +os ite +Ä L og +ick en +] : +Ä surpr ise +h ab +Ä c raft +ol t +Ä J ul +Ä d ial +Ä rele vant +Ä ent ered +Ä lead s +Ä A D +Ä Cle an +Ä pict ures +ess or +Ä al t +Ä pay ing +P er +Ä Mark et +Ä upd ates +am ily +Ä T ype +Ä H ome +Ä 5 5 +semb ly +rom e +8 3 +Ä great est +Ä he ight +Ä he av +ain ts +Ä list en +as er +Ä S H +Ä cap able +ac le +Ä pers pect +in ating +Ä off ering +ry pt +Ä De velop +ab in +r c +Ä br ight +al ty +ar row +Ä supp l +ind ing +ack ed +gy pt +Ä An other +p g +Ä Virgin ia +Ä L u +Ä pl anned +Ä p it +Ä swe et +T ype +Ä D i +Ä typ ically +Ä Franc isco +Ä pro spect +Ä D an +Ä te en +re es +Ä sc hed +Ä h ol +Ä sc r +Ä lot s +l ife +Ä news p +Ä for get +Ä N one +Ä M iddle +Ä R yan +ed d +Ä se vere +Ä su it +ll er +9 3 +Ä cor respond +Ä expl os +u ations +Ä fl ag +g ame +r id +Ä pr in +Ä D ata +Ä de ploy +Ä En ter +su it +gh an +Ä M en +Ä though ts +Ä mat ters +Ä ad apt +Ä A ri +Ä f ill +Ä for th +Ä s am +Ä 4 1 +Ä pay ment +Ä H or +Ä sp ring +du c +Ä l osing +Ä bring ing +F O +al a +Ä dist ribution +he red +b our +Ä Israel i +om a +Ä comb ination +Ä pl enty +V E +C an +Ä H aw +Ä per man +Ä Spe cial +Ä to w +Ä see king +Ä exam ples +Ä class es +c r +Ä be er +Ä mov es +Ä I P +Ä K n +Ä pan el +E ven +Ä proper ly +Ä r is +Ä pl ug +Ä estim ated +E very +Ä def ensive +ag raph +Ä pre gn +Ä inst it +Ä V ict +Ä vol ume +Ä pos itions +Ä l inks +Ä Pro gram +Ä We ek +ag ues +Ä trans form +k er +Ä C EO +Ä c as +Ä opp onent +Ä twe et +Ä C ode +Ä sh op +Ä f ly +Ä tal ks +Ä b ag +Ph one +Ä a id +Ä pl ants +Ä 6 5 +Ä att orney +ar ters +qu est +Ä Mag ic +Ä beg ins +Ä my ster +Ä environment al +Ä st orage +N N +Ä m arg +Ä s ke +Ä met al +ell y +Ä ord ered +Ä rem ained +Ä l oved +Ä prom pt +Ä upd ated +Ä exper ts +Ä walk ing +Ä an cient +Ä perform ed +AT E +Ä ne ither +i ency +Ä manufact ure +Ä P ak +Ä select ed +Ä m ine +Ä ult imately +Ä expl an +Ä lab el +Ä Serv ices +ribut ed +Tr ump +Ä sy n +Ä U lt +S C +Ä me at +Ä g iant +Ä W ars +Ä O N +Ä ad m +Ä inter pret +Ä even ing +Ä ev il +Ä B oston +Ä W ild +Ä  à +Ä Bit coin +Ä Am azon +D r +Ä In formation +Ä obvious ly +Ä adv anced +Ph oto +ol ar +Ä we ather +Ä symb ol +Ä so le +Ä pot entially +ost er +Ä orig inally +m un +3 00 +az e +ess ions +Ä de ck +Ä st ood +Ä you th +Ä B ern +R ep +Ä T est +Ä bas ically +ot ic +Ä invol ve +ol it +ly n +S ee +Ä air craft +Ä conf irm +E W +Ä mess ages +Ä Rich ard +Ä k it +Ä pro hib +Ä v ulner +is ters +Ä exist ence +Ä turn ing +Ä S P +Ä des ire +Ä fl at +Ä m ent +se ason +ang es +Ä neighbor hood +Ä L ake +AT ION +Ä point ed +b ur +Ä inn ov +uc ks +U L +Ä profess or +Ä exp ressed +A B +ic ious +Ä 200 2 +Ä De v +Ä s ession +Ä b are +s en +Ä dis s +Ä C ath +Ä P ass +Ä P oint +Ä do ctor +or row +ail ed +Ä R ub +Ä D C +Ä Char l +p erson +Ä writ er +igh ters +ure au +Ä ob lig +Ä record ed +Ä bro ke +Ä ord ers +il ty +Ä mot ion +in ity +l aw +ad ium +Ä imm igration +Ä contr ast +Ä b att +Ä ex cellent +Ä techn ical +am i +Ä t un +Ä cl oud +Ä Y ear +ge on +Ä cre ation +Ä str ange +Ä a uth +Ä for t +b orn +Ä ext ent +Ä T oday +Ä Cl ub +Ä r ain +Ä s ample +Ä accept ed +Ä t act +Ä f ired +Ä S on +Ä stand s +Ä b oot +Ä 4 7 +Ä stat ements +Ä vers ions +Ä se lling +ound ed +Ä 199 0 +Ä were n +Ä W atch +Ä exper iment +P ost +Ä ret ail +ul ed +In st +un te +ÃŖÄĨ Âŧ +Ä dep art +Ä b ond +i very +om pl +Ä re action +Ä Syri an +Ä P ac +app ed +ani el +D P +Ä res olution +Ä re act +Ä appro ved +on om +m ond +Ä O ffic +-- - +Ä repl ace +Ä t ack +Ä sp ort +Ä ch ain +Ä emer gency +r ad +Ä Palest in +Ä 4 6 +Ä autom atically +Ä rout e +Ä p al +Ä b anks +Ä Par is +Ä Med ia +ro ad +ic ing +i xt +ist ed +Ä g rew +Ä co ord +Ä W here +om in +Ä sub s +ïÂŋÂŊ ïÂŋÂŊ +Ġ ¹ +Ä corpor ate +Ä se lection +n oon +Ä Rep ort +c s +clud ing +ord ers +anc he +Ä It s +Ä slow ly +Ä E gypt +Ä A cc +Ä col le +iqu es +E X +Ä attempt s +ur l +Ä C ross +Ä find ings +Ä S C +Ä O R +Ä ind ex +ens ity +Ä W ay +Ä L and +Ä sh ock +d is +Ä d ynam +Ä c art +m osp +S ince +i est +Ä B oy +Ä st orm +Ä Cont in +201 3 +he w +il it +Ä ess ential +iqu id +O ther +ive red +Ä reason able +A ct +Ä sub sequ +Ä P ack +Ä F ort +Ä consider ing +Ä un iversity +l og +Ä mar ried +Ä ill ust +Ä Tr ue +ÂŖ Äą +Ä numer ous +rast ructure +Ä serious ly +Ä refer red +u a +Ä consist ent +on na +Ä Re al +ru ption +ci ples +Ä fact s +9 1 +ot es +er g +The n +Ä acc ompl +N ote +Ä re venue +Ä pass ing +Ä m al +e en +Ä Y et +Ä g ather +ter day +ew ork +Ä A uthor +P e +Ä opt im +Ä r ub +Ġè ÂŖÄą +Ä un known +st one +Ä un ion +ol ve +Ä opportun ities +Ä brow ser +Ä W al +Ä C ost +Ä report ing +st s +p et +Ä s and +Ä sudden ly +Ä surpr ising +Ä V R +Ä somew hat +Ä B as +ult ure +iz z +Ä C D +Ä challeng es +Ä sett ings +Ä experien ces +Ä F ull +Ä can n +Ä rece iving +ES T +Ä j oint +Ä cult ural +Ä a st +8 2 +as tern +ce ived +Ä C ru +Ä b ull +p ired +am m +Ä fac ing +p ower +Ä b oss +Ä H ol +Ä inst r +Ä increasing ly +Ä sh ift +Ä stre ets +Ä William s +ab b +Ä l ie +Ä l augh +Ä C a +P L +Ä adult s +Ä custom er +Ä ob tained +Ä support ing +ht ml +f ire +Ä detail ed +Ä pick ed +Ä R ight +ld er +E E +st ood +Ä K im +Ä w ire +Ä s ight +Ä develop ers +Ä pers ons +Ä s ad +Ä c up +Ä war ning +Ä boy s +l ong +Ä b ird +f o +Ä w al +Ä observ ed +Ä z one +iven ess +Ä ch annel +c ript +Ä ref used +Ä Ag ain +Ä su c +Ä spokes man +Ä Re f +r ite +ou ston +ÃŖÄĨ Âŗ +Ä S her +Ä act s +Ä N ame +Ä strugg le +ar ry +omet imes +Ä disc rim +H T +Ä categ ory +Ä real ize +Ä employ ee +Ä Af ghan +en ger +Ä gun s +Ä Ste ve +Ä M ot +Ä O l +ok ed +Ä th ick +Ä fair ly +ill y +Ä sur ve +Ä M at +we ight +Ãĸ Äļ +Ä tro ops +Ä ag ents +Ä batter y +Ä mot iv +Ã ÂĄ +S ec +d en +o very +L S +Ä fl u +Ä conf ident +Ä O per +Ä em pty +Ä p hen +Ä se ctor +Ä exc ited +Ä rem ote +ap h +o en +Ä destroy ed +Ä mor al +Ä H P +Ä R on +Ä d ress +Ä B at +Ä l it +Ä M S +Ä a f +H L +r um +is ms +Ä should n +Ä sym pt +Ä Tor onto +het ic +Ä car bon +Ä install ed +Ä viol ent +Ä sol ar +j a +Ä pract ices +Ä r ide +Ä P enn +Ä impro ved +Ä aud io +Ä behav i +Ä P S +Ä e ating +D ata +Ä Re view +p ass +cl aim +u ated +ang ers +c hen +Ä proper ties +Ä any where +An other +Ä bl ow +Ä Jack son +Ä p roud +Ä plan e +l ines +Ä squ are +Ä pro of +ans as +Ä talk ed +m akers +Ä s ister +Ä hold s +Ä res ident +Ä = = +Ä resist ance +Ä spl it +Ä pro secut +Ä conf idence +res ents +Ä cut s +Ä except ion +Ä z ero +Get ty +Ä cop yright +Ä tot ally +orm al +ific ations +Ä Austral ian +Ä s ick +Ä 1 50 +Ä house hold +Ä fe es +Ä dri vers +og en +Ä N Y +Ä necess arily +Ä regul ations +ear ing +s l +Ä perspect ive +c are +ic ial +H is +Ä esc ape +Ä surpr ised +Ä V an +ur rent +Ä v ac +8 1 +Ä Th us +Ä em phas +Ä Ch ampions +Ä I ce +Ä n arr +Ä head s +Ä ca using +b el +f ortunately +Ä M a +Ä targ ets +ci pl +Ä after noon +Ä add s +Ä May be +Ä F our +ess ed +ple te +Ä us ual +ch o +ing u +Ä with d +Ä E nergy +Ä E conom +O O +Ä art icles +Ä inj ured +Ä man age +Ä expl ains +Ä di agn +R ec +at ures +Ä link ed +Ä discuss ed +Ä expl o +Ä occ asion +ath an +Ä opp osite +Ä fac es +Ä den ied +Ä K night +Ä n ut +Ä approx imately +Ä disapp oint +onym ous +Ä B est +Ä L o +Ä H y +Ä A ff +Ä vot ing +an while +Ä II I +Ä instit utions +ag ram +Ä D aily +Ä dr ag +Ä near by +Ä gu ilty +Ä con ver +P re +s hip +Ä re ward +Ä philos oph +Ä S S +u gh +Ä app s +f riend +Ä u pper +Ä ad vert +Ä s now +Ä fr ust +Ä our selves +F r +Ä D ie +amp ion +Ä dis miss +Ä c ere +Ä sign al +f rom +Ä  ). +Ä 5 2 +Ä cr imes +it ors +est ival +use um +Ä coun cil +Ä S aud +M ay +Ä G un +ic ian +et her +Ä su fficient +Ä H en +so le +Ä histor ical +Ä F ar +Ä T urn +Ä p in +Ä suc ceed +m at +ly mp +Ä trad ition +Ä O k +Ä c ro +Ä desc ription +al le +Ä sk y +T e +Ä wide ly +Ä w ave +Ä defin ition +Ä Jew s +Ä cy cle +Ä ref ere +Ä br ings +us al +Ä al ive +Ä frequ ently +Ä int ention +Ä Cont rol +l v +y stem +Ä priv acy +g ent +ren ce +Ä Qu est +Ä Christ mas +Ä r ail +Ä co oper +Ä test ed +Ä C apt +as ks +Ä comfort able +Ä del ivered +sc ape +Ä dep th +Ä G OP +Ä writ es +Ä ass ets +Ä sa v +im ents +Ä trans ition +Ä art ist +Ä L ook +Ä l ob +Ä comp onents +ar ity +Ä walk ed +Ä ro ot +Ä particip ants +Ä not iced +Ä res c +Ä n av +Ä Ad minist +d a +ut ral +pl ate +Ä import ance +Ä ass ert +ious ly +c ription +Ä inj uries +Ä Che ck +Ä regist ered +Ä int ent +Ä miss ed +ograph ic +Ä sent ence +oun ter +Ä assist ance +ev in +Ä dat abase +Ä build ings +Ä class ic +Ä th inks +Ä Oh io +P r +ug g +Ä fe e +p an +Ä effect ively +Ä fac ility +Ä be ar +Ä ch apter +Ä dog s +Ä Col umb +Ä l atter +it ial +Ä ad mitted +T V +Ä Ge org +Ä post s +\ \ +Ä lawy er +Ä equ ival +Ä m and +Ä contro lled +Ä W alk +Ä And rew +Ä men u +am ental +Ä protect ed +v a +Ä administ r +or al +Ä re in +Ä S ar +Ä amount s +Ä n ative +Ä M oon +Ä rep resents +Ä ab andon +Ä carry ing +Ä t ank +m ary +Ä decl ared +T ube +Ä h at +Ä pun ish +el lect +m es +Ä un iverse +Ä R od +ph y +Ä inf rastructure +Ä 5 1 +Ä opp osed +ow nt +c a +Ä M ake +Ä hard ware +Ä co ffee +R el +b al +w orld +Ä S af +Ä Se a +in als +Ä own ed +Ä h all +ers ion +Ä describ e +Ä P ot +Ä port ion +Ä at mosp +Ä govern ments +Ä dep ending +Ä off ense +Ä tr ick +aw a +Ä L ine +Ä V is +Ä H ard +Ä Or ig +Ä Cl ick +Ä des k +Ä Val ley +Ä S ov +Ä mov ies +Ä rem ark +Ä m ail +Ä cons cious +Ä rul ing +Ä R ights +Ä med ic +he nt +Ä W omen +> < +Ä repl aced +Ä P rem +Ä Th anks +Ä re new +Ä B all +if orm +Ä sh ots +C omm +Ä ar med +Ä const ant +Ä t aste +Ä real ized +Ä bu ff +Ä m o +Ä effic ient +M ost +or ation +if ies +Ä commun ication +Ä fl ood +Ä consequ ences +Ä any way +ig g +Ä G M +Ä Th ank +Ä  iron +Ä ev olution +Ä C op +tw itter +Ä 9 5 +Ä relationship s +ad el +Ä You ng +Ä propos al +ay ers +uild ing +Ä H ot +OR E +c os +Ä coll abor +P G +ax y +Ä know ing +Ä support s +ow ed +Ä control s +Ä mere ly +um er +Ä ath let +Ä f ashion +p ath +Ä g ift +Ä er a +AN D +Ä kind s +Ä Kore an +Ä leg it +ul ous +Ä ess entially +Ä the rap +n ic +Ä suff ered +Ä h ur +Ä prom ise +Ä ex cess +Ä over w +Ä pr ime +Ä H ouston +er ry +Ä M s +R S +201 2 +Ä st ores +Ä O lymp +Ä j ourney +Al though +S ub +Ä E duc +Ä Ch apter +Ä request s +Ä consum ers +Ä t iny +Ä is ol +Ä F air +b a +Ä Y OU +Ä cr ash +ce ler +Ä emot ional +Ä good s +Ä elect ed +Ä mod er +Ä Lin ux +Ä bl ocks +Ä is land +Ä Soc iety +Ä elect ions +Ä broad cast +Ä che ap +Ä n ations +Ä se asons +4 00 +Ä was te +Ä S at +Ä field s +em ploy +Ä prof ile +Ä auth ors +AL L +Ä G ra +w est +Ä T y +Ä death s +Ä v acc +Ä for med +Ä d u +Ä on going +Ä Muslim s +el f +ig ure +Ä ass ume +Ä Ukrain e +w ater +Ä co ast +Ä vot ed +g or +Ä A S +Ä Mich igan +az a +Ä Ar m +i ro +Ä f lex +as ters +' ' +Ä wel come +ar l +Ä loc ations +ig ation +Ä F il +Ä bu ying +Ä arch itect +Ä hard er +Ä C ub +Ä inter face +Ä restaur ant +Ä disco ver +Ä ex ceed +Ä fav our +ger y +Ä d uty +Ä p itch +ad or +Ä M ach +b oy +Ä respond ed +Ä ext ended +her s +M any +ra id +if er +Ä In s +S er +Ä med ium +s he +Ä S ports +Ä mag azine +ut ation +Ä lim its +Ä G all +Ä ex ternal +raz il +Ä young er +t le +Ä rem ind +Ä C ON +Ä immedi ate +Ä h idden +Ä vol unte +Ä sim pl +od cast +Ä ph ase +d r +Ä pl ot +Ä exp osure +R I +og rap +v in +an ish +Ä Ac ad +Ä Eng ine +Ä exp ansion +Ä P ay +Y our +Ä pus hed +Ä E ll +Ä He ad +Ä market ing +Ä A C +k et +Ä h its +Ä g ro +Ä A ge +Ä Sc ot +] [ +Ä st im +Ä i Phone +ÄĒ Ä´ +Ä n arrow +Ä Get ty +Ä Tur key +Ä perfect ly +Ä en able +ut ch +Ä prec ise +Ä reg ime +Ä sh if +Ä comp ens +g un +d iv +Ä ch osen +Ä K en +An y +Ä tre es +Ä recomm ended +Ä R en +u able +Ä H T +F ollow +E G +Ä H and +Ä K enn +Ä arg uments +Ä ex ists +Ä b ike +Ä Cons erv +Ä bre aking +Ä G ar +Ä c razy +Ä virt ual +ay lor +ix el +Ä 19 80 +Ä per mission +Ä Ser ies +Ä consum er +Ä close ly +c alled +Ä 5 4 +Ä hop es +Ä ar ray +Ä W in +Ä Lab our +Ä sp ons +Ä I re +Ä p ow +Ä read ers +Ä employ ment +Ä creat ure +Ä result ing +Ä accur ate +Ä mom ents +Ä arg ued +Ä p ed +D uring +Ä 5 3 +Ä T al +Ä s ought +Ä suff ering +Ä  icon +le e +Ä ( $ +al ian + ° +Ä p ra +Ä bon us +( " +k o +Ä act ing +D E +f all +Ä compar ison +Ä sm ooth +Ä N AS +u pp +Ä Jose ph +ep ing +Ä T ake +Ä M id +Ä s ending +f ast +Ä F all +Ä deal ing +us er +Ä Or gan +C o +Ä att ached +Ä se es +% . +Ä typ ical +AR T +Ä find s +Ä As ia +um in +Ä C ore +Ä E nt +in ent +u ce +Ä Bl ood +Ä N ever +Ä em ails +Ä high light +Ä conf ront +at us +ut ed +Ä un us +Ä top ic +Ä Ad am +Ä b le +at i +Ä under stood +S et +st ruct +T P +Ä m ob +a a +Ä St art +pect ed +se ll +Ä ded icated +Ä C A +u an +Ä song s +esc ription +Ä te ch +Ä r ape +Ä as ide +Ä gr ant +Ä 5 6 +s ub +Ä arg ue +Ä cont aining +Ä sche dule +Ä liber al +Ä public ly +Ä heav ily +Ä U t +in er +Ä S ection +Ä C are +we et +l s +D is +ÃĸÄļ Äĸ +Ä F ollow +B ack +Ä I T +Ä b es +j i +Ä H it +est ed +Ä every body +Ä Sw ed +Ä fem in +Ä fac ilities +Ä con ven +C omp +Ä O S +c ore +Ä an x +Ä div ision +Ä C am +Ä St an +m ates +Ä expl ore +pl om +Ä sh ares +pl oad +an es +Ä ide al +et ers +Ä B ase +Ä pl astic +Ä dist inct +Ä Net work +Ä Se attle +Ä trad ing +ens us +int end +Ä ex hib +Ä init ially +Ä F ood +Ä thous and +Ä Bus iness +act er +Ä par agraph +Ä rough ly +Ä w ww +Ä creat ive +Ä Con f +Ä consum ption +Ä fil ms +ag an +Ä ob tain +Ä t all +Ä t or +Ä acknow led +Ä g rown +al o +K E +Ä 4 00 +end ers +t aining +U G +Ä su icide +Ä wat ched +Ä L ist +al i +re hens +Ä surround ing +Ä p ip +Ä f lying +Ä J ava +ord an +Ä serv ing +in ations +p ost +Ä sh o +A v +Ä j ail +z y +Ä 199 9 +Ä < / +Ä liter ally +Ä S ir +Ä exp osed +Ä l ies +st ar +Ä b at +Ä ear ned +Ä D ig +Ä spec ified +Ä Se ason +Ä deg rees +Don ald +Ä cent re +Ä sh aring +Ä win ter +Ä C O +C he +Ä  Î +M P +Ä un w +Ä few er +Ä M ir +Ä somew here +Ä K ey +Ä attack ed +Ä K ir +Ä dom ain +Ä strong er +Ä 9 9 +Ä pen alty +I d +Sc ript +Ä decl ined +Ä ne ck +Ä fra ud +Ä cur rency +Ä r ising +R C +ÃĸÄĸÂĻ ÃĸÄĸÂĻ +H z +Ä t ab +Ä tal ent +n am +Ä N BA +Ä vill age +Ä leg s +Ä N ext +E d +Ä ac id +Ä hy d +8 00 +Ä invol ving +Ä Im age +Ä Be fore +F l +Ä yes terday +S ource +Ä terror ist +Ä su p +Ä sy nt +Ä Saud i +Ä w est +Ä r u +b urg +Ä vis ible +Ä stru ck +r ison +Ä aw esome +Ä d rawn +Ä answ ers +Ä G irl +Ä R am +Ä threat s +Ä def eat +os it +Ä v ent +atur ally +Americ an +end a +Ä H oly +Ä r um +% , +c ase +Ä Hist ory +Ä You Tube +Ä sit uations +Ä D NA +S te +Ä sa ved +It em +Ä rec ip +olog ist +Ä fac ed +Ä el ig +O nce +Ä L i +u h +Ä mist ake +Ä Div ision +Ä B ell +Ä sympt oms + Ž +Ä dom in +Ä fall ing +Ä end ing +as hes +Ä mat ches +Ä On line +Ä explan ation +D ef +red it +Ä any more +Ä T otal +Ä F OR +us hed +Ä let ters +Ä ris ks +Ä O K +Ä reported ly +: \ +Ä pl ate +Ä subject s +Ä attempt ed +if ier +ian a +Ä unlike ly +Ä Th ough +um a +Ä In vest +Ä Pr in +ic an +Ä D ar +Ä Color ado +au g +Ä ve get +a os +ri a +Ä she l +Ä mark ed +Ä ( ) +Ä sp r +p o +Ä L ink +Ä def e +Ä J r +Ä them e +Ä pass ion +Ä P en +Ä inf o +iz er +Ä sh it +Ä C ivil +ap se +c re +Ä po ly +Ä comp onent +Ä Char les +Ä Ire land +Ä Pro v +Ä do ctors +Ä gr anted +Ä pain t +Ä hon or +Ä sm oke +Ä pay ments +Ä prim arily +Ä King dom +r ich +ate ll +Ä de als +Ä sched uled +Ä fund amental +Ä prote in +Ä newsp aper +Ä cl ients +yth on +Ä D ate +h us +Ä feed back +Ä stret ch +Ä c ock +Ä hot el +Ä Que en +Ä su gar +Ä j u +Ä mil k +Ä appro val +Ä L ive +Ä equival ent +ef ully +Ä ins ert +z ona +Ä ext ension +d ri +J ohn +Ä acc omp +S m +Ä F und +Ä const antly +Ä ` ` +Ä gener ated +Ä A ction +Ä P sych +Ä T ri +Ä recogn ize +Ä v ary +ph a +Ä R a +d f +et ch +Ä Sov iet +Tw o +Ä pattern s +Ä prof ession +an ing +T ime +Ä L im +Ä col ors +Ä A z +Ä T R +Ä inf ect +Ä phen omen +Ä she ll +Al so +Ä put s +Ä del ivery +Ä bro wn +Ä process ing +Ä light s +ess age +Ä Bro ok +Ä A ud +l ation +Ä indust rial +L ike +Ä B razil +rou s +ES S +Ä L uc +Ä some how +Ä 8 5 +Ä pro port +Ä polit icians +Ä indic ate +Ä h ole +Ä techn iques +Ä compet itive +Ä ph r +Ä v o +ist ent +Ä D ream +Ä camp us +Ä aspect s +Ä help ful +Ä sh ield +or se +Ä trig ger +m al +Ä 5 8 +Ä t ort +Ä person ally +Ä t ag +Ä keep s +Ä V ideo +Ä ben ch +Ä g ap +a ire +Ä e ast +Ä rec overy +per ial +Ä prof it +Ä M ic +Ä 5 7 +Ä col on +Ä strong ly +st yle +Ä alleg ations +h an +Ä rep orters +j o +r ine +arg et +and al +Ä 0 3 +Ä fl ash +tr ans +Ä str ict +Ä park ing +Ä Pak istan +Ä l i +Ä we ird +Ä E ric +Ä reg ions +Ä J un +Ä int ellect +Ä W H +od ing +rib utes +up id +Ä T it +Ä f inger +or ia +Ä e lev +Ä F ield +Ä con clusion +; ; +Ä feel ings +Ä ext ensive +Ä m ixed +Ä ne uro +v y +Ä har ass +Ä C irc +ou ch +Ä territ ory +Ä success fully +M ar +Ä ing red +Ä overw hel +Ä l ayer +V iew +Ä all ies +ill ance +Ä Th ree +Ä b unch +Ä norm ally +Ä net works +Ä sac r +Ä C IA +b les +Ä ch ose +Ä opp onents +Ä regard less +Ä fr anch +Ä pre f +Ä P o +Ä br idge +ann a +Ä Sil ver +Ä w age +p age +ri or +Ä rad ical +Ä L ittle +Ä man ip +Ä secret ary +Ä g ang +D R +F A +Ä dec ent +Ä Sp irit +Ä un cle +Ä Develop ment +Ä invest ors +Ä wall s +Ä pub lish +Ä gener ate +iss ions +c ar +Ä prom ote +Ä cut ting +Ä che st +Ä drink ing +Ä collect ed +Ä 7 2 +Ä hop ing +Ä em br +gor ith +Ä war ned +Ä instruct ions +O G +Ä D id +Ä Ag ency +Ä g ear +Ä critic ism +Ä F urther +Ä ut il +ann y +R ed +Ä coun sel +Ä As ian +Ä redu ction +p ool +Ä teach ing +Ä deep ly +i y +Ä estim ates +Ä cho ices +Ä perman ent +in em +ke l +Ä f asc +p se +f ile +Ä L ow +Ä P erson +Ä t ournament +st al +Ä m el +U ST +Ä R ay +az i +V al +Ä cont ained +Ä H olly +Ä w ake +Ä reve al +Ä process es +Ä IS IS +Ä 0 9 +Ä bl ind +Ä ste el +Ä B ad +Ä care fully +app y +ro it +Ä g aming +Ä hous es +Ä C oll +Ä tr uck +er m +Ä sc ored +Ä occ as +ret urn +b ound +v ar +Ä sh arp +Ä af raid +Ä E X +am ber +c ific +Ä sche me +N C +Ä Pol it +Ä decl ine +Ä 199 8 +Ä pus hing +Ä poss ession +Ä priv ile +Ä teacher s +Ä y ield +H A +Ä Dav is +it led +#### #### +Ä r ig +Ä D aniel +ac on +Ä h ide +ut en +Ä colle agues +Ä prin ciples +Ä l oud +Ä s in +Ä Dem on +Ä st one +Ä 0 2 +Ä t aught +Ä ter rible +Ä st uck +Ä Pol icy +te en +Ä implement ation +Ä B BC +Ä AP I +Ä whe el +all as +Ä ch ampions +ol ars +play er +Ä repeated ly +Ä St ill +Ä lik es +ast y +es ter +Ä Cath olic +R L +Ä b ath +Ä no ise +t itle +Ä n orthern +P art +Ä mag n +Ä f ab +Ä As h +Ä dis pl +Ä tick et +Ä m urd +Ä along side +Ä Mus ic +Ä r iver +Ä Ste el +Ä C L +Ä Pl ayer +Ä M ult +ow ing +re p +s ize +Ä t ur +Ä Georg ia +isc al +ra ction +Ä c able +Ä 5 9 +Ä w ins +Ä up coming +Ä surv ive +Ä ins pired +Ä Educ ation +Ä stat istics +Ä F oot +iam i +Ä y ellow +Ä P age +. - +Ä H as +Ä ur ban +Ä a x +es sel +\ " +Ä quarter back +Ä reg ister +Ä Lab or +Ä ab ilities +Ä F amily +Ä var iable +Ä Pr ice +Ä cont em +Ä th in +Ä E qu +d ata +Ä g otten +Ä const it +Ä as ks +Ä t ail +Ä exc iting +Ä E ffect +Ä Sp anish +Ä encour age +ins on +Ä A h +Ä commit ment +C S +Ä r ally +Ä : : +Ä subs id +Ä sp in +Ä capt ured +201 8 +Ä inn oc +Ä alleged ly +Ä C ome +Ä art ists +Ä N umber +Ä elect ronic +Ä reg ional +ap es +Ä w ra +Ä my th +pr ise +Ä M iller +Ä C reat +Ä Ep isode +b ell +Ä direct ed +Ä ext ract +Ä s orry +Ä v ice +ag ger +Ä Su pport +Ä 6 6 +Ä I ron +Ä wonder ful +Ä g ra +N et +ion e +E ng +Ä sh ips +ik es +Ä K evin +it ar +Ä activ ists +tr ue +Ä Ari zona +ent h +Ä Des pite +Ä S E +Ä ha bit +ern el +Ä in qu +Ä ab ortion +Ä v oid +Ä expl icit +Ä eng aged +Ä ang ry +Ä r ating +Ä fr ag +b ro +ick ing +d ev +Ä wor ried +Ä ob ser +Ä ap artment +Ä G T +Ä est ate +Ä Const itution +em on +Ä S now +Ä count y +Ä dis ag +Ä Step hen +Ä imm igrants +w ind +Ä N ations +Ä fol ks +O ut +Ä g all +Ä target ed +Ä st ead +Ä B on +Ä L ib +Ä inform ed +Ä 12 0 +ch ain +idel ines +or ough +Ä dri ven +Ä regular ly +Ä bas ket +Ä princ iple +oc ument +Ä st un +ib ilities +Ä Rom an +Ä Ab out +Ä al ert +Ä democr acy +Ä represent ed +H S +c ers +p arent +Ar t +p ack +Ä di plom +re ts +Ä N O +Ä capt ure +Ä Ad v +ÄĻ Âĸ +Ä announce ment +Ä L ear +Ä h ook +Ä pur s +Ä S uch +Ä C amer +Ä refuge es +Ä V e +P ol +Ä recogn ized +l ib +Ä had n +A ss +Ä pil ot +us hing +Ä return ing +Ä tra il +Ä St one +Ä rout ine +Ä cour ts +Ä des per +Ä friend ly +Ä It aly +Ä pl ed +Ä breat h +Ä stud io +N S +Ä imp ressive +Ä Afghan istan +Ä f ing +Ä d ownt +ink ing +Ä R og +i ary +col or +se x +ar on +Ä f ault +Ä N ick +D own +Ä R ose +Ä S outhern +X X +is odes +L ist +6 00 +Ä out come +er r +Ä else where +Ä ret ire +Ä p ounds +Ä Gl obal +Pe ople +Ä commun ications +Ä lo an +Ä rat io +Ä Em pire +Ä g onna +Ä inv ent +D F +Ä 19 70 +Ä Comm on +p at +Ä prom ised +Ä d inner +Ä H om +Ä creat es +Ä oper ate +ver ty +Ä J ordan +et ime +Ä sust ain +R eg +Ä incred ible +im a +Ä war rant +Ä m m +A tt +Ä law suit +Ä review s +it ure +Ä S ource +l ights +Ä F ord +Ä 6 3 +g roup +st ore +Ä feat ured +Ä fore ver +Ä po verty +Ä P op +Ä C NN +az z +ab is +ach ing +Ä l aid +Ä Su pp +Ä fil ter +en a +Ä Commun ity +Ä creat ures +u ction +Ä R oyal +Ä associ ation +Ä Con nect +Ä Br ad +Ãĸĸ ÄĒ +l ers +the re +Ä G i +Ä val uable +AC K +Ä T aylor +Ä l iquid +Ä Att orney +Ä Car l +Ä F inal +ag a +Ä Wil son +B ecause +Ä Prof essor +ak a +Ä incred ibly +r ance +! ) +R ef +s k +Ä sol utions +Ä atmosp here +Ä bl ame +um es +Ä N ob +C A +um ps +r ical +Ä Put in +Ä D est +or ic +Ä P A +Ä respect ively +w an +Ä fif th +Ãĸ ÄĻÂĸ +Ä C ry +Ä govern or +res ident +Ä purch ased +Ä h ack +Ä int ense +ob s +Ä orig in +Ä def ine +Ä care ful +** * +Ä should er +Cl ick +Ä t ied +Ä dest ruction +ou red +Ä no body +Ä h o +Ä Ex per +Ä t ip +" ; +Ä techn ique +Ä j ur +Ä P ok +b ow +Ä leg end +Ä acc ord +Ä bus y +Ä Int el +Ä h ang +ak i +. ] +ÃĸÄĸÄļÃĸÄĸÄļ ÃĸÄĸÄļÃĸÄĸÄļ +Ä sur gery +Ä rep rodu +Ä un iform +Ä scen es +c ode +Ä 6 2 +l isher +Ä H ave +ph ia +Ä cry pt +Ä rec on +Ä sc ream +Ä adop ted +Ä sc ores +N e +Ä It alian +in cluding +B O +Ä indic ated +Ä ent ertain +G u +T ext +i el +Ä tw enty +Ä eng age +off s +Ä Pac ific +Ä sm ile +Ä person nel +Ä to ler +Ä do ors +Ä t one +Ä mach ines +Ä ent ering +ten ance +C O +Ä Jer sey +Ä fore st +Ä hor se +Ä compl aint +Ä Spr ing +y o +Ä Pl us +ed ing +Ä Ret urn +qu arters +ial s +c ow +Ä acad emic +Ä f ruit +Ä 199 6 +og ether +Ä w ine +Ä pur su +Ä Ste ven +Ä lic ens +Wh o +Ä clot hes +re ction +Ä squ ad +Ä st able +Ä r aw +z ens +St ar +ut ies +anc er +Ä ke ys +Ä M u +Ä compl icated +ig er +Ä Te xt +Ä abs or +Ä 6 8 +Ä fun ny +Ä rel ief +Ä L ew +Ä C ook +Ä ch art +Ä draw ing +G E +Ä mod ule +Ä B ull +I LL +Ä s alt +0000 0000 +il le +Ä res ource +aw ay +adel phia +Ä B ru +Ä 6 7 +Ä some body +Ä particip ate +Ä ro se +we red +Ä mus cle +Ä cons ent +Ä contin uing +Ä Guard ian +Ä Or der +reg on +Ä re ar +Ä prov ision +Ä lik ed +ri ent +Ä b ra +Tr ans +Ä meet ings +Ä to x +Ä con vent +Ä aut o +Ä rec ording +Ä So ft +00 1 +Ä R oll +Ä program ming +Ä p ic +Ä prov ed +Ä st ab +Ä A st +Ä ca ption +ul ating +Ä Att ack +Ä new ly +Ä 199 7 +f r +Ä dis cipl +Ä Gree k +Ä ed ition +Ä Do es +Ä B ox +if le +ack et +Ä pass es +Ä gu est +Ä ac celer +it als +U D +Ä aut hent +Ä R est +ov al +t a +u ine +Ä arm or +Ä T own +Ä comp at +Ä inc hes +Des pite +Ä ass ign +he rent +Ä prep are +Ä M eg +oc key +Ä dep ends +Ä track s +w atch +Ä l ists +Ä N orthern +Ä al ter +re c +Ä E astern +Ä cond em +Ä every where +? ' +Ä aff ili +Ä f ought +": {" +Ä m ac +it arian +Ä sc ope +Ä A L +aw s +ar ms +Ä qu e +Ä enjoy ed +nes ota +Ä agg ressive +Ä St ory +Ä I V +Ä rec ipe +Ä rare ly +Ä Med ical +val ue +ang el +ay ing +omet hing +Ä sub section +Ä s outhern +Ä frequ ency +re te +roll ed +ult s +Ä N ic +Ä beh alf +Ä sequ ence +ab et +Ä controvers ial +Ä comp rom +Ä work er +Ä main ly +Ä al gorith +Ä M ajor +or ce +g ender +Ä organ ized +Ä f ake +Ä conclud ed +Ä E D +Ä Ex ec +r age +Ä ch ances +ber ry +Ä Tr ad +Ä config uration +Ä withd raw +Ä f ro +ud es +Ä Bro ther +Ä B rian +Ä tri es +Ä sam ples +Ä b id +Ä Gold en +Ä phot ograph +if est +Ä D O +Ä Par liament +******** ******** +R em +Ä cont est +Ä sign ing +p x +Ä Z eal +ÃĸÄļÄĸ ÃĸÄļÄĸ +E ar +Ä ex it +Be fore +Ä Cor por +n ull +mon th +Ä rac ial +ott ed +Ä V eg +Ä Re uters +Ä sw ord +ps on +Ä Rom ney +a ed +Ä t rib +Ä in ner +Ä prot ocol +Ä B i +Ä M iami +ever al +p ress +Ä sh ipping +Ä Am endment +Ä How ard +con nect +Ä D isc +Ä J ac +iam ond +Ä There fore +s es +Ä Prin cess +Ä US B +Ä An th +Ä surve illance +Ä ap olog +Ä 6 1 +ow a +Ä f ulf +j s +Ä l uck +ust ed +Ġ § +n i +Ä ant icip +em an +Ä win ner +Ä sil ver +ll a +ic ity +Ä unus ual +Ä cr ack +Ä t ies +e z +Ä pract ical +Ä prov ince +Ä Pl ace +Ä prior ity +IC E +Ä describ es +Ä br anch +F orm +ask a +miss ions +b i +Ä p orn +Ä Tur k +Ä ent hus +Ä f ighters +Ä 0 8 +Ä Det roit +Ä found ation +av id +A re +Ä jud gment +cl ing +Ä sol ve +Ä Des ign +W here +hes is +Ä T ro +a fter +Ä ne utral +Ä Palestin ian +Ä Holly wood +Ä adv is +Ä N on +y es +ol is +Ä rep utation +Ä sm ell +Ä b read +Ä B ul +Ä Be ach +Ä claim ing +Ä gen etic +Ä techn ologies +Ä upgr ade +row s +Ä develop er +Ä J osh +Ä Dis ney +erv ed +ip al +Ä un ex +Ä bare ly +t hen +Ä P ub +Ä ill ness +et ary +Ä B al +Ä p atch +Ä but t +Ä st upid +Ä D og +Ä D allas +f ront +ie ce +Ä prot ests +Ä ch at +oen ix +Ä w ing +Ä par liament +Ä 7 7 +ose xual +Ä re nder +pt ions +Ä Co ast +os a +Ä G reg +h op +Ä Man agement +Ä bit coin +Ä rec over +Ä incor por +or ne +Ä Us ing +Ä pre ced +Ä threat ened +Ä spirit ual +Ä E vent +Ä F red +Ä advert ising +Ä improve ments +Ä C ustom +Ä er rors +Ä sens itive +Ä N avy +Ä cre am +L ook +Ä ex clusive +Ä comp rehens +Ä de leg +Ä con ce +Ä rem em +Ä struct ures +Ä st ored +N D +Ä 1 000 +U P +Ä B udd +A F +w oman +Ä Acad emy +ð Ł +se a +Ä tem porary +Ab out +es ters +Ä tick ets +Ä poss ess +in ch +o z +Ä l a +Ä contract s +Ä un p +Ä c ig +Ä K at +ult ural +as m +Ä mount ain +Ä Capt ain +St ep +m aking +Ä Sp ain +Ä equ ally +Ä l ands +at ers +Ä reject ed +er a +im m +ri x +C D +Ä trans action +g ener +less ly +Ä | | +Ä c os +Ä Hen ry +Ä prov isions +Ä g ained +Ä direct ory +Ä ra ising +Ä S ep +ol en +ond er +Ä con sole +in st +Ä b om +Ä unc ertain +1 50 +ock ing +Ä meas ured +Ä pl ain +Ä se ats +Ä d ict +S L +af e +Ä est imate +iz on +at hered +Ä contribut ed +Ä ep isodes +omm od +G r +AN T +Ä 6 9 +G ener +Ä 2 50 +vious ly +rog en +Ä terror ism +Ä move ments +ent le +oun ce +Ä S oul +Ä pre v +Ä T able +act s +ri ors +t ab +Ä suff er +Ä n erv +Ä main stream +Ä W olf +Ä franch ise +b at +Ä dem ands +Ä ag enda +Ä do zen +Ä clin ical +iz ard +Ä O p +t d +Ä vis ited +Ä Per haps +Ä act or +Ä de lic +Ä cont ribute +Ä in ject +Ä E s +ac co +Ä list ening +Ä con gress +epend ent +Ä prem ium +Ä 7 6 +Ä Ir ish +Ä ass igned +Ä Ph ys +Ä world wide +Ä narr ative +ot ype +m ont +b ase +Ä B owl +Ä Administ ration +Ä rel ation +Ä E V +C P +Ä co vers +Ä 7 8 +Ä cert ific +Ä gr ass +Ä 0 4 +pir acy +ir a +Ä engine ering +Ä M ars +Ä un employ +Ä Fore ign +st ract +Ä v en +Ä st eal +Ä repl ied +Ä ult imate +Ä tit les +d ated +Ä j oy +a us +Ä hy per +ak u +Ä offic ially +Ä Pro duct +Ä difficult y +per or +Ä result ed +rib ed +l ink +wh o +~~ ~~ +Ä Spe ed +Ä V iet +W ind +Ä Bar ack +Ä restrict ions +Ä Sh are +Ä 199 5 +ition ally +Ä beaut y +op t +Ä m aps +Ä C R +Ä N ation +Ä Cru z +W ill +Ä electric ity +Ä or g +Ä b urd +Ä viol ation +Ä us age +Ä per mit +Ä Ch ron +Ä F ant +Ä n aturally +Ä 0 7 +Ä th rown +Ä Aw oken +Ä al ien +Ä Her o +Ä K ent +Ä R ick +ri ke +Ä p ace +}, {" +G L +Ä po ison +Ä T ower +Ä form al +al ysis +Ä gen uine +Ä k il +a ver +Ä proced ure +Ä Pro p +intend o +Ä M ain +as ant +Ä tr ained +G ame +Ä L oad +Ä M A +Ä cru cial +Ä le ts +Ä F R +Ä ch ampion +1 01 +Ä Con ference +Ä writ ers +Ä connect ions +Ä o kay +ir ms +Ä R and +Ä enc ounter +Ä B uff +Ä achie ved +Ä che cks +isc ons +Ä assist ant +Ä when ever +Ä A ccess +Ä U r +b in +Ä cl ock +is p +op her +Ä b orrow +Ä m ad +Ä person ality +on ly +IS T +ab ama +Ä g ains +Ä common ly +Ä ter r +Ä hyp ot +Ä re ly +Ä t iss +iscons in +Ä rid ic +f unction +Ä O regon +Ä un com +r ating +el and +Ä N C +Ä m oon +ann on +Ä vulner able +ut ive +³³ ³³ +Ä Rad io +Ä w estern +se ct +Ä T ony +Ä occ urs +Ä O s +Ä H on +Ã Ń +Ä v essel +Ä Scot land +Ä discrim ination +Ä subsequ ent +st ring +Ä fant asy +Ä Sh adow +Ä test im +W E +it i +r as +Ä bo at +Ä mar ks +Ä ord inary +Ä re n +Ä represent ative +Ä pet ition +Ä 7 3 +Ä ad venture +Ä ign ore +Ä Phil adelphia +Ä S av +V P +Ä fact ory +Ä t asks +Ä dep ression +z ed +................ ................ +Ä St orm +Ä c ogn +Ä elig ible +Ä redu cing +v ia +Ä 0 5 +Ä stri king +Ä doll ar +h o +O V +Ä instr ument +Ä philosoph y +Ä Mo ore +Ä A venue +Ä rul ed +Ä Fr ont +IN E +Ä M ah +Ä scen ario +Ä NAS A +Ä en orm +Ä deb ut +Ä te a +T oday +Ä abs ence +S im +Ä h am +le ep +Ä t ables +Ä He art +M I +K e +re qu +V D +m ap +Ä chair man +Ä p ump +Ä rapid ly +v i +Ä substant ial +E P +d es +ch ant +ili pp +Ä S anta +ri ers +anche ster +L oad +Ä C ase +Ä sa ving +Ä 7 4 +Ä A FP +er ning +oun ced +Ä Min nesota +Ä W as +Ä rec ru +Ä assess ment +Ä B ron +U E +Ä dynam ic +Ä f urn +ul ator +Ä prop ag +h igh +Ä acc ommod +Ä st ack +Ä S us +w rit +Ä re ven +Ä God d +Ä Zeal and +ab s +Ä br ut +Ä per pet +h ot +Ä hard ly +Ä B urn +ÃŖÄ¤ š +Ä st y +Ä trans actions +Ä g ate +Ä sc reens +Ä sub mitted +Ä 1 01 +Ä langu ages +ugh t +em en +Ä fall s +Ä c oc +Ĥ ÂŦ +Ä stri kes +p a +Ä del iber +Ä I M +Ä rel ax +ann els +Ä Sen ator +Ä ext rem +Ä } , +Ä De b +Ä be ll +Ä dis order +c ut +Ä i OS +Ä l ocked +Ä em issions +Ä short ly +" ] +Ä Jud ge +Ä S ometimes +Ä r ival +Ä d ust +Ä reach ing +F ile +¯¯ ¯¯ +ino is +Ä J ason +Ä s atell +are t +Ä st ations +Ä ag ric +Ä Techn ology +com es +Ä Un fortunately +Ä Child ren +Ä appl ies +ast ed +Ä an ger +ail ability +Ä Dam age +Ä comp are +Ä Stand ard +Ä aim ed +Ä B a +angu age +Ä reg ulation +Ä j ury +Ä air port +Ä se ctions +Ä Pr ince +em ed +Ä medic ine +Ä h itting +Ä sp ark +ol ves +Ä ad s +St ate +Ä food s +Ä repl acement +Ä ch icken +Ä low est +Ä mind s +Ä invol ves +u i +Ä arr ang +Ä proced ures +Ä Wh ich +ivers ary +Ä b ills +Ä improve ment +Ä in ev +Ä expect ations +Ä intellect ual +Ä sp aces +Ä mechan ism +2 50 +bre ak +Ä Z e +Ä T enn +Ä B alt +Ä bar rel +Ä stat ic +man n +Pol ice +Ä t ips +Ä hand ling +c us +od ed +il ton +ir y +Ä journal ists +our se +Ä com ic +Ä nom ine +IT Y +Ä vers us +Ä lo op +Ä sur f +Ä Ind ust +Ä Hun ter +Ä belief s +is an +Ä set up +Ä bre w +im age +Ä comput ers +f ol +} ," +Ä Med al +Ä tax p +Ä display ed +Ä g rav +Ä f iscal +M on +Ä Mos cow +Ä K ong +Ä Cent re +Ä camer as +Ä Mr s +Ä H ay +Ä a ver +Ä K elly +p y +Ä require ment +Ä ent itled +omb ie +Ä sh adow +ag ic +Ä A k +Ä el ite +Ä div ided +Ä head ing +Ä cop ies +Ä loss es +Ä v it +k ed +Ä B ry +Ä an s +Ä Ste am +Ä rep orter +he im +Ä It em +Ä super ior +d on +ere nt +à Âļ +Ä therap y +Ä pe ak +Ä Mod el +Ä l ying +Ä g am +z er +r itten +Ä respons es +Ä consider ation +Ä B ible +Ä l oyal +Ä inst ant +Ä p m +Ä Fore st +à Âŧ +Ä ext end +Ä conv icted +Ä found er +Ä conv in +Ä O ak +che ck +Ä sch olars +p ed +Ä over se +T op +c ount +Ä Ar k + ¡ +Ä 0 6 +Ä L A +m d +Ä Lat in +im ental +Ä C PU +Ä subst ance +Ä minor ity +Ä manufact uring +E r +ocol ate +Ä att ended +Ä Man ager +r ations +Ä appreci ate +om y +GB T +id ency +B L +Ä guarant ee +pos ition +Ä o cean +clud e +Ä head ed +Ä t ape +Ä lo ose +Ä log ic +Ä pro ven +Ä sp ir +Ä ad mit +is a +Ä investig ate +Ä 199 4 +sy lv +Ä L ost +c est +Ä 7 1 +Ä request ed +Ä wind ows +Ä Pok Ê +Ä With out +M et +Ä behavi our +Ä read er +Ä h ung +Ä Ke ep +Ä ro les +Ä implement ed +Ä bl ank +Ä serv es +Ä J ay +Ä c ited +Ä F riend +prof it +ap on +Ä rep air +it em +arr ass +Ä crit ics +ad i +Ä F ather +Ä sh out +Ä f ool +Ä 8 8 +Ä produ cing +Ä l ib +Ä round s +Ä circ le +Ä pre par +Ä sub mit +Ä n ic +mor row +ÃŖÄĨ ÂĢ +U nder +Ä v ital +ater n +Ä pass word +Ä public ation +Ä prom inent +Ä speak s +Ä b ars +Ä de eper +Ä M ill +port ed +Ä w id +Ä but ter +Ä sm oking +Ä indic ates +K ey +rop ri +Ä F ile +all ing +ast ing +Ä R us +Ä ad j +Ä 7 9 +av al +Ä pres um +bur gh +on ic +Ä f ur +Ä poll s +ik a +Ä second ary +Ä mon ster +ig s +Ä Cur rent +E vent +Ä owners hip +end ar +Ä arri ve +Ä T ax +Ä n ull +Ä Pri v +Ä th ro +Ä k iss +c at +Ä up set +ang le +it ches +ect or +olog ists +Ä Gal axy +Ä cor ruption +Ä h int +ent er +Ä H ospital +Ä great ly +Ä beg un +es y +Ä so il +Ä Ant on +Ä main tenance +ÃŖÄĨ Š +Ä do zens +Ä human ity +Ä Al abama +Ä r om +w orth +ap ing +sylv ania +l ah +Ä g athered +G A +Ä attack ing +f ound +Ä Squ are +Ä ar bit +ict ions +Ä W isconsin +Ä d ance +Ä S aint +arch y +Ä base ball +Ä contribut ions +Ä liter ature +Ä ex ha +per ty +t est +Ä b ab +Ä contain er +let ter +Ä fall en +Ä webs ites +Ä bott le +Ä S ac +Ä bre ast +Ä P L +Ä veter an +Ä interview s +Ä A le +Ä b anned +eng ers +Ä Rev olution +in th +Ä conc erning +IV E +Ä exp enses +Ä Matt hew +Ä Columb ia +d s +ist ance +Ä ent ity +.. ." +Ä rel iable +Ä par alle +Ä Christ ians +Ä opin ions +Ä in du +l ow +Ä compet e +Ä th orough +Ä employ ed +Ä establish ment +ig en +Ä C ro +Ä lawy ers +Ä St ation +T E +Ä L ind +Ä P ur +it ary +Ä effic iency +ÃĸÄĸ IJ +Ä L y +Ä m ask +Ä dis aster +Ä ag es +ER E +es is +Ä H old +Ä cas ual +b led +Ä en abled +Ä En vironment +Ä Int elligence +i per +Ä M ap +Ä B E +Ä emer ged +is dom +Ä c abin +Ä regist ration +Ä fing ers +Ä ro ster +Ä fram ework +Ä Do ctor +et ts +Ä transport ation +Ä aware ness +H er +Ä attempt ing +O ff +Ä St ore +ÃÄĨÃĤÃÄĨÃĤ ÃÄĨÃĤÃÄĨÃĤ +Ä K now +Ä def ence +Ä sc an +Ä T en +Ä Ch air +Ä P H +Ä Atl anta +Ä fuck ing +Ä ans wered +b n +Ä K ar +Ä categ ories +Ä r ational +Ä c ust +Ä rob ot +Ä correct ly +Ä g if +Ä graph ics +m ic +Ä ground s +Ä O pp +i ate +Ä dist ributed +Ä san ctions +Ä challeng ing +ut o +Ä ingred ients +Ä inv ited +Ä found ed +Ä Re qu +d ed +Ä b owl +Ä brother s +Ä H a +I O +Ä w ages +im ore +oc ial +Ä se ed +ative ly +Ä address es +Ä I owa +ab eth +Ä att itude +is d +ch ild +Ä m ole +Ä disco very +y ard +B r +Ä 8 2 +Ä suppl ies +ell ing +Ä dist ingu +C R +Ä re cept +Ä  vert +Ä sw im +b ec +d oor +Ä Y eah +Ä g al +Ä inter act +Ä E SP +Ä C S +amp s +Ä convin ced +Ä object ive +Ä dis h +Ä Phot os +l ad +Ä downt own +o il +in ction +Ä to morrow +Ä C OM +Ä surv ival +sh ot +Ä sett lement +C ons +Ä X box +int erest +Ä S M +arg o +en ess +Ä eth nic +b ered +M in +Ä T ok +Ä inc ent +Ä Comm and +Ä main tained +Ä break s +br idge +at ar +ag g +Ä F inally +un icip +Ä O nt +le ft +Ä recogn ition +Ä * / +Ä P ers +Ä we lf +Ä address ed +Ä K ansas +Ä vir us +Ä where as +Ä p apers +ram s +Ä Min istry +Ä ple asure +Ä acqu ired +Ä d uration +j pg +Ä cal m +Ä N HL +Ä burn ing +Ä fold er +ick ed +Ä P y +Ä Ill inois +Cl ass +Ä Godd ess +Ä perform ing +Ä welf are +j ar +In ter +Ä l in +Ä enh ance +Ä not ion +f are +yp es +Ä Are a +Ä cann abis +Ä Die go +f s +Ä M anchester +com m +in ite +Ä cover ing +Ä S ound +Ä 19 60 +Ä 8 4 +e lect +z ing +Ä citiz en +Ä ph ones +Ä r aid +Ä ign ored +Ä Ob ject +Ä u pload +c ard +Ä mod ified +Ä room s +ia h +r ange +he ast +ach us +Ä suggest ing +ÃĸÄĸ Ä­ +gr ade +E l +Ä clot hing +Ä r h +Ä H an +un ity +en cing +Ä Aust in +sec ution +t ra +d em +Ä Q ual +Ä he aven +Ä st ages +Ä w edd +pl us +ific ial +Ä Im m +Ä H o +iet ies +Ä phr ase +Ä br ill +act ory +Ä prov iders +Ä sil ence +Ä a er +Ä A I +Ä Ad venture +Ä platform s +Ä demonstr ated +Ä inter f +ing ton +Ä r aces +Ä gr ade +ult ane +Ä Th rough +f alse +Ä b ow +Ä A B +Ä fl avor +Ä histor ic +g ov +Ä col our +Ä view ed +Ä Em ail +el come +Ä inter vention +Ä d iversity +Ä period s +Ä re verse +Ä V ery +Ä qu ote +Ä Le ft +th rough +Ä sc rew +Ä land ing +Ä p ill +Ä w et +Ä prot esters +Ä repe at +av ed +er k +Ä sal ary +Ä Penn sylvania +St ill +Ä may or +Ä kit chen +Ä feat uring +Ä M useum +Ä T ournament +Ä F al +Ä ser vers +U C +Ä any body +im g +Ä Tr ade +ixt ure +the less +Ä fin ance +Ä cl osing +Ä Pat ri +i ac +ab el +Ä > > +or ous +Ä f irms +sc reen +un a +Ä emb arrass +ul se +Ä let ting +Ä th rew +ile y +Ä ch annels +l an +Ä Veg as +Ä se ar +Ä fant astic +ar re +uzz le +Ä D er +Th ose +Ä sw ing +Ä she et +ind ex +co ver +og an +Ä vari ables +Ä Te ch +Ä sp oken +ac hel +Ä D a +Ä Mount ain +Ä load ed +Ä foot age +vers ion +Ä un l +Ä Ph oenix +Ä throw ing +Ä f iring +Ä track ing +Ä w idth +Ä strugg ling +ro oms +ot ion +Ä month ly +Ä Ser ver +Ä egg s +op en +M C +Ä 199 3 +Ä h ired +Ä stay ed +Ä All en +Ä st ro +Ä 9 8 +st ep +Ä Turk ish +Ä fab ric +ist ing +Ä D om +Ä d ates +Ä pr on +Ä basket ball +Ä l ucky +Ä Arab ia +Ä assum ed +est y +Ä aff airs +Ä gl ad +Ä Ind eed +Ä F A +Ä W ord +Ä jo ining +if ice +p read +ir ts +Ä Se lect +Ä pop ulations +aw are +Ä n ose +Ä compl aints +st art +Ä sc oring +Th anks +Ä min ing +Ä visit ors +S H +Ä dam aged +Ä character istics +Ä P ent +D C +Ä 8 3 +Ä S ix +r ates +Ä fl ags +Ä B rew +d og +M ark +// // +Ä exec ution +Ä j oke +ph ones +Ä testim ony +Ä ob st +Q L +Ä C ut +Ä stud ied +Ä N intendo +ick et +Ä N BC +Ä l ad +Ä B ra +Ä M oh +Ä k ernel +Ä overwhel ming +Ä ag ed +Ä applic able +Ä C ond +Ä road s +Ä Bl ock +m ade +od ge +Ä comm ands +Ä off ices +vel and +Ä t ut +Ä rece iver +Ä F ro +Ä sho pping +Ä i P +Ä St re +Ä A BC +Ä entertain ment +Ä B ow +ort ed +M c +Ä read s +gr ad +Ä Col lect +Ä Ãĸ ÄĒÄ´ +Ä Cap ital +eder ation +Ä employ er +Ä involve ment +Ä anx iety +al ia +Ä ro of +Ä Am ong +Ä Democr at +Ä stat s +Ä V ill +Ä const itutional +Ä refer ring +itt y +Ä tack le +out ube +Ä back ed +Ä H ong +Ä Bro ad +Ä e le +Ä O tt +Ä 199 2 +h our +achus etts +C al +Ä defe ated +Ä 8 1 +es p +Ä seem ingly +w as +Ä J enn +Ä K urd +Ä g ene +Ä disc ount +R et +EC T +( ); +Ä club s +Ä s id +Ä M arsh +Che ck +Ä p p +Ä E ag +ides pread +Ä be ings +F T +Ä introdu ction +Ä Ch ange +AR D +Ä 1 10 +ad ows +ier ce +Ä me al +a uthor +Ä B ang +lah oma +Ä r anks +201 1 +?? ?? +m ax +Ä coll apse +Ä op ens +Ä e cho +Ä s oph +Ä rac ist +Ä enorm ous +Ä w aves +Ä t ap +Ä comprehens ive +. -- +Ä R oy +Ä farm ers +Rel ated +a ired +ron es +Ä C rim +Ä proport ion +Ä design s +Ä negoti ations +Ä virt ually +Ä Bat man +Ä war n +Ä legit imate +m ate +Ä con vention +, , +net ic +Ä S D +Ä consist ently +Ä compens ation +Ä punish ment +Ä y e +Ä t ie +Ä B ureau +ir lf +Ä B u +Ä A ren +Ä Ph ilipp +Ä kn ife +Ä mem ories +Ä R oss +Ä ang le +Ä 8 6 +Ä Th under +Ä re nd +Ä T our +Ä count s +s ung +Ä Im p +Ä educ ational +Ä access ible +C OM +Ä d rew +y er +G l +am ine +OR T +O B +I B +m aster +Ä tri als +og y +h ar +Ä Tr ust +Ä prefer red +irlf riend +Ä N ev +Ä b in +Ä c ow +P age +Ä sign ature +Ä B L +7 00 +Ä ret ired +Ä by tes +Ä neigh b +Ä Leg end +Ä dev ast +Ä suspect ed +is ons +Ä PokÊ mon +sc ale +Ä cap abilities +Ä re vel +Ä che ese +d y +igr ant +Ä fail ing +b its +Ä Her oes +Ä G host +Ä S cient +Ä appoint ed +ur i +Ä inst itution +Ä expand ed +g reg +Ä monitor ing +Ä p odcast +Ä coal ition +Ä 9 6 +J o +Ä st olen +Ä S ab +Ä stop s +Ä hol iday +Ä int r +C ar +Bl ack +Ä L GBT +Ä war ming +Ä And erson +Ä 8 9 +Ä produ cer +M ed +Ä accur acy +Ä Mar vel +iz abeth +Ä Pat rick +m ony +Ä min i +ac les +Ä over t +the y +Ä members hip +Ä V en +Ä ex ch +Ä rem oval +Ä D ave +T Y +m ad +Ä F ind +Ä ad equ +Ä e c +Ä te eth +Ä emot ion +Ä per m +Ä sole ly +d b +Ä extra ord +IG HT +c al +Ä gu idelines +Ä d ying +Ä susp ended +Ä Prem ier +Ä Anth ony +el ve +Ä d ad +Ä E th +Ä Foot ball +Ä abandon ed +Ä < < +Ä m arch +Ä hor ror +ÃĸÄĸÂĻ " +Ä child hood +Ä campaign s +Ä l unch +Ä Al bert +bl ock +ÃĸĸÄĒ ÃĸĸÄĒ +ound ing +Ä b one +or gan +ad ers +Ä Fl ash +Ä Dri ve +Ä ton ight +Ä w ars +Ä F L +Ä form ation +con st +New s +Ä com pe +or ious +Ä St aff +Ä discuss ions +Ä Prot ection +Ä J am +Ä crit eria +Ä install ation +Ä accompl ish +iz za +Ä pub lisher +Ä resc ue +Ä T ry +U LL +Ä S om +Ä H op +ore t +th s +ord on +Ä p ocket +Ä In v +Down load +Ä Cr ime +Ä b ene +Ä Gu ide +Ä As sembly +Ä param eters +I E +Ä Alex ander +Ä conc ert +Ä Sc he +Ä sh oes +Ä vis iting +Ä rec all +Ä b ub +Ä r ural +Ä conc rete +Ä R os +N ext +R uss +Ä lo ans +Ä Sh ield +Ä tre m +hem at +k g +Ä Har ris +is ition +Ä M ove +Ä F C +Ä f ate +Ä Ch o +Ä t ired +Ä princ ipal +h ist +ien ces +ath y +Ä se vent +Ä m ood +Ä strateg ic +Ä dise ases +Ä for um +Ä tem por +Ä head quarters +P ar +ig e +fl ix +Ä gu itar +Ä 9 4 +On ly +Ä rele ases +ro ph +================ ================ +Ä 6 00 +Ä Contin ue +ig ate +Ä C rit +sy stem +Ä dis abled +Ä unex pected +ith ub +Ä uncle ar +Ä E st +Ä contr ad +Ä strateg ies +vent ures +Ä pass age +AM E +Ä impro ving +Ä reve als +Ä decre ase +ov a +Ä ann oy +Ä Sh ort +Ä L ibrary +Ä cy ber +n ell +Ä H ur +Ä C B +Ä phot ograp +U I +Ä s ed +G e +Ä 8 7 +Ä d iverse +Ä encour aged +Ä cons piracy +Ä bird s +Ä oper ator +Ä hand ful +Ä class ified +? ) +Ä dram atic +Ä investig ators +it o +Ä w idespread +Ä R oom +-------------------------------- -------------------------------- +Ä collect ive +Ä journal ist +St ring +Ä temper atures +il a +Ä gu id +Ä ins pect +Ä miss ile +Ä May or +Ä man ual +Ä sim ultane +Ä rat ings +Ä su ck +Ä 9 7 +Ä univers al +Ä ph arm +Ä dis rupt +ian o +A V +Ä f t +Ä stat ist +old s +Ä Walk er +ph p +Ä under t +Ä L as +ish op +nt il +res hold +Ä Whe ther +M s +Ä den y +Ä Cl oud +Ä prov ider +Ä surv iv +Ä Up date +h as +Ä mist akes +ch arge +pl ed +r ity +Ä n ode +Ä Mass achusetts +ool s +lic ation +Ä f ails +em ale +or i +back s +Ä sh irt +Ä ' ' +Ä N AT +Ä wat ers +els on +Ä e ase +Ä sc ar +Ä cont ents +m ind +Ä cont ribution +Ä sh r +Ä hand ed +Ä st ability +Ä tra ve +E m +Ä mir ror +12 3 +Ä we igh +Ä f iction +ou ver +ist ant +r ition +Ä F ed +Ä phys ically +Ä st ake +Ä Art icle +Ä Ar c +Ä Lew is +Ä M ind +Ä demonstr ate +Ä prof its +v ision +om ic +ol id +Ä batt les +Ä dri ves +Ä eas tern +Ä S ony +!! ! +ar ation +v ard +Ä G L +port ation +Ä 9 2 +Ä law makers +Ä protect ing +Ä E PA +Ä y eah +Ä sh ame +ol ph +e ven +x it +Ä att ach +Ä represent ing +Ä ob s +Ä Ut ah +iff s +Ä Fre edom +Ã Âŗ +A K +Ä inc idents +it age +Ä view ers +c d +Ä m ouse +Ä cl ar +Ä accord ance +Ä b ot +c or +Ä Sum mer +he ld +Ä innoc ent +Ä initi ative +ol s +________________ ________________ +Ä sp ots +p ace +Ä convent ional +Ä corpor ations +Ä block ed +H D +at tered +Ä ref ers +Ä bu ck +Ä Dig ital +12 0 +Ä top ics +T F +Ä ÄŖ +br id +re ement +Ä under lying +Ä M ember +Ä investig ating +Ä pregn ancy +Ä touch down +Ä B and +Ä Call er +Ä inst ances +P P +w a +G ood +Ä 199 1 +Ä C old +Ä fear s +Ä rem arks +Ĩ Ä´ +at al +Ä m it +Ä exper iments +i pt +Col or +ind u +Up date +Ä 9 3 +A g +Ä  ÃĨ +anc ouver +B oth +Ä jud ges +Ob ject +Ä st ere +umb n +Ä particip ation +Ä St ars +Ä J ere +Ä week ly +Ä B an +Ä convers ations +Ä P itt +u z +Ä Indian a +Ä K ick +Ä inf ection +Ä hero es +Ä sett led +Ä stri p +Ä h al +Ä d ump +Ä S ci +Ä l es +Ä ref erences +Ä U RL +Ä Br idge +Ä want ing +For ce +Ä ex clus +Me anwhile +m n +Ä g entle +m aker +sen al +Ä G ro +ou ri +Ä R ain +Ä All iance +Ä l ift +el a +S D +Ä Cle veland +Ä rank ed +Ä st adium +Ä dead ly +ä ¸ +Ä r iding +ar ia +Ä Ar mor +Ä document ation +Ä Gree ce +ree k +Ä l ens +Ä S a +Ä g ross +Ä E mer +ag ers +Ä D ub +Ä R h +Ä AM D +Ä arri val +Ä des ert +Ä supp lement +Ä Res p +Ä kn ee +Ä marg in +f ont +og g +201 0 +Ä P ir +Ä P rom +iv als +Ä int ake +Ä different ly +ug s +Ä b its +clud ed +Ä search ing +Ä D u +um ble +Ä function al +Ä Balt imore +Ä C ould +Ä des ired +Ä circ uit +Ä L yn +Ä G O +Ä F alse +re pre +' : +alt ies +Ä min im +Ä dro ve +Ä Sh ould +Ä h ip +Ä pro s +Ä ut ility +Ä N ature +Ä M ode +P resident +o pp +r at +form ance +Ä concent ration +Ä f ont +Ä B ud +Ä am id +Ä re vers +Ä M L +B ar +Ä inter action +Ä jur isd +Ä spell s +d ep +f il +Ä civil ians +ut ter +Ä Co oper +Ä Bel ow +Ä ent rance +Ä con vert +Ä controvers y +ow ered +Ä contr ary +Ä ar c +Ä Exec utive +Ä Offic er +Ä pack ages +Ä prog ressive +w idth +Ä reserv ed +v ol +Ä Sam sung +Ä print ed +Ä cent ers +Ä introdu ce +Ä Kenn edy +Ä odd s +Ä sure ly +Ä independ ence +Ä pass engers +repre ne +Ä Be h +Ä l oves +Ä ESP N +Ä fac ilit +Ä ident ical +Ä do ct +Ä partners hip +con f +Ä H ide +Ä conf used +Ä C ow +M en +Ä w rest +Ä Iraq i +Ä h oles +Ä Stud ies +Ä pregn ant +h ard +Ä sign als +I X +Ä pull ing +Ä grad uate +Ä nomine e +D ate +Ä per mitted +Ä Ãĸ ĤÂŦ +Ä Ok lahoma +St art +Ä author ized +Ä al arm +Ä C os +v an +Ä gener ations +c ular +Ä dr agon +Ä Soft ware +Ä Ed ward +Ä contro ller +S en +ge red +Ä V ik +Ä appro ached +Th ank +Ä can ce +Ä form ula +Ä Sm all +Ä weak ness +Ä r amp +it udes +j ud +Ä brill iant +Ä acc us +s ource +Ä 8 00 +Ä E vil +S w +Ä hom eless +we ek +i ens +r ics +Ä Th ird +T O +Ä organ ic +Ä present ation +ag h +Ä Down load +v ation +Ä as sembly +or able +hold ers +Ä Bern ie +Ä Hel p +Ä t ong +Ä F ight +Ä be ach +B ook +Ä L ic +Ä r ush +Ä R ound +ou p +Ä Mar x +Ä calcul ated +Ä De vil +Ä Sar ah +Ä occasion ally +Ä bul let +Av ailable +g ate +Ä 9 1 +Ä h osp +Ä prom ises +Ä H IV +Ä St adium +Ä St ock +Ä Corpor ation +g age +N G +Ä C redit +Ä s ne +ib l +Ä acc um +s uch +Ä terror ists +Ä conscious ness +Ä Z h +Ä dram a +ool a +pir ation +Ä lab our +Ä N in +Ä ut ter +Ä democr atic +Ä ass ass +il ation +Ä g est +Ä ab road +Ä met ab +Ä s orts +Ä fl av +U B +Ä m g +Ä Not hing +Ä O d +Ä mus ical +200 9 +Ä dro ps +oc ated +ater al +0000 00 +Ä g re +Ä equ ality +Ä burd en +Ä v ig +Ä Le ader +-------- ---- +Ä cere mony +Ä f ighter +Ä act ors +Ä  ÃĻ +am an +F i +Ä al ign +put er +Ä e lder +Ä N SA +Ä represent ation +Ä Ont ario +IT H +usal em +Ä harass ment +itz er +Ä sy mp +Ä box es +Ä D R +Ä man ifest +at re +Ä  ^ +Ä d ies +le ton +Ä miss ions +et he +Ä res olve +Ä follow ers +Ä as c +Ä k m +l ord +am med +Ä sil ent +Ä Associ ated +Ä tim ing +Ä prison ers +Ä K ings +Ä F ive +Ä tow er +Ä appro aches +Ä precise ly +Ä b ureau +Ä M other +Ä I ss +Ä key board +it ual +Ä fund ed +Ä stay ing +Ä psych ological +Ä m ile +Ä Le on +Ä Bar b +w ill +Ä w ider +Ä Atl antic +Ä t ill +Ä R ome +ro t +Ä accomp an +Ä fl our +ac o +W orld +Ä Exp ress +Ä Y u +C or +Ä ple ased +part y +Ä point ing +Ä inf lation +Ä ro y +Ä  ), +ain er +Ä wedd ing +orm on +Ä requ iring +Ä qual ified +Ä se gment +EN D +Ä s izes +e als +Ä cor rupt +ass ador +Ä cele b +Ä dream s +Ä M ess +Ä check ing +Ä V ersion +Ä prep aring +Ä act ively +Ä D iff +Ä l ux +Ä W inter +act eria +Ä N E +Ä dep uty +Ä trans gender +Ä sum mary +Ä in her +er ies +ch ar +Ä Y an +Ä kn ock +Ä P ath +Ä l ip +roll er +Ä imp ression +Ä celebr ate +Ä sl ide +Ä gu ests +Ä cl ip +F S +Ä sav ings +Ä capt ain +Ä leg acy +Ä Den ver +Ä w ounded +tab oola +AC T +Ä purs ue +Ä o xy +Ä  q +Ä sem i +Ä N eed +Ä Aff airs +Ä ob sc +Ä check ed +Ä d ual +C ode +Ä M D +le m +ult y +ĠÂ Š +Ä El izabeth +Ä cent uries +ard ed +s rc +Ä ev ident +enn is +at in +Ä unemploy ment +Ä Mar io +Ä int im +Ch rist +Ä bi ological +Ä sold ier +Ä Add ed +Ä m ath +Ä G il +Ä bi as +Ä d ating +Ä O cean +Ä m ice +M us +h ire +Ä T es +Ser ver +lim ited +S ize +Ä met ers +Ä rock et +es see +Ä certific ate +Ä Iran ian +AS S +Ä gr id +D ec +Ä ro lling +com mun +Ä Swed en +b ury +Ä tiss ue +Ä rac ism +Ä L ocal +Ä myster y +Ä exam ine +Ä st em +Ä s its +Ä hop ed +ot ing +Ä dial ogue +Ä pers u +W atch +l ay +M AN +Ä ch ronic +Ä Port land +mark et +Ä S EC +Ä paralle l +Ä sc andal +Ä car ries +Ä phenomen on +h uman +ack er +Ä O x +Ä retire ment +tain ment +ov ie +Ä G ear +Ä d uties +Ä do se +Ä sc roll +M B +in f +Ä sa uce +Ä land scape +red dit +Ä Champions hip +Ä Red dit +al id +Ä co in +Ä over s +Ä post ing +ab out +Ä f el +and y +Ä b old +Ä focus ing +e ffect +G R +Ä de emed +Ä recommend ations +Ä ste pped +Ä vot er +Ä De ep +Ä Inst agram +Ä moder ate +Ä Mary land +Ä restrict ed +Ä M B +Ä Ch all +Ä to b +Ä c ir +Ä O cc +Ä E ver +Ä coll aps +IN FO += - +Ä P ict +Ä Acc ount +n c +Ä o ught +Ä ex port +Ä dr unk +( ' +Ä w ise +Ä M ort +ne cess +Ä an cest +Ä Inc re +Ä frequ ent +m ir +Ä interpret ation +Ä depend ent +Ä co ins +Ä B ol +V ideo +Ä Just in +Ä fat al +Ä cook ing +Ä conf usion +ip her +Ä cust ody +Ä Mor gan +om ach +Ä Govern or +Ä restaur ants +el ing +Ä acknowled ged +Ä the r +Ä gen es +ch ing +He y +Ä tact ics +Ä Mex ican +Ä v end +Ä he s +qu er +Ä not ing +Ä Camer on +Ä target ing +ro ck +Ä cred its +Ä emot ions +Ä represent atives +new s +Ä legisl ative +Ä rem oving +Ä tweet ed +Ä Car ter +Ä F ixed +Ä for cing +Ä speak er +Ä m ales +Ä Viet nam +l ined +Ä concept s +Ä vo ices +o ir +Ä T rib +W he +Ä Jer usalem +Ä S ant +Ä c ul +Ä l ady +Ä Haw ai +Ä ar ts +Ä In n +Ä Mach ine +Ä Em peror +Ä sl ot +g ly +Ä Pro cess +II I +Ä athlet es +Ä Tem ple +Ä Rep resent +Ä pres c +Ä t ons +Ä gold en +Ä p unch +Ä G R +iver pool +Ä en act +Ä lob by +Ä m os +Ä pick ing +Ä lif etime +Ä cogn itive +E ach +z o +Ä d ub +Ä cons ists +ol n +Ä f estival +am ous +Ä int ellig +w ords +Ä Sm art +Ä de le +Ä l apt +Ä mag ical +Ä S in +b us +ur ities +igh th +Ä Rub y +Ä S ure +ol ving +Ä j un +O ST +Ä imp osed +Ä ast ron +Ä cor rel +Ä N S +Ä K it +Ä F uture +b urn +Ä imm une +oc us +Ä cour ses +Ä St ring +Ä le an +Ä g host +Ä out comes +Ä exp ense +Ä every day +Ä accept able +A h +Ä equ ipped +Ä or ange +F R +Ä D utch +Th ough +Ä R ank +Q U +Ä Rober ts +wh at +re nd +Ä disapp ear +Ä sp awn +Ä L am +o is +Ä des erve +Ä min imal +Ä nerv ous +Ä W ould +Ä ro ok +Ä V ancouver +Ä res ign +sh ire +Ä W orks +Ä B uild +Ä afford able +Ä G ary +Ä Aren a +Ä h anging +Ä impl ications +Ä S ong +Ä main taining +Ä gu ards +C ON +Ä der ived +Ä execut ed +Ä the ories +Ä qu oted +Ä And re +og a +sel ess +in fo +Ä Bel g +Ä t ears +Ä Sur v +Ä birth day +ig ious +im mer +Ä spect rum +Ä architect ure +Ä rec ruit +arm a +T able +Ä mon sters +Ä G ov +Ä dest ination +Ä attract ive +Ä f oss +Ä More over +Ä pres ents +TH E +Ä rep ly +pt on +Ä c um +Ä del ight +Ä affect s +Ä don ations +Ä T oy +Ä H im +M ENT +Ä over come +it ched +Ä Fant asy +Ä H at +Ä Be ast +b ott +Ä investig ations +R un +Ä hun ting +d i +f und +Ä s essions +est yle +Ä port ray +oid s +Y eah +Ä commun icate +Ä com edy +Ä Y ang +Ä bel t +Ä Mar ine +Ä predict ed +Pl ay +Ä important ly +Ä remark able +Ä elim inate +D avid +Ä b ind +V ID +Ä advoc ates +Ä G aza +im p +D B +Ä N a +Ä Sim ilar +I ES +Ä char ity +v as +m ath +Ä Ãĸ ĸ +ok er +nd um +Ä cap s +Ä H al +2 000 +e an +Ä fle et +Ä rec re +R ight +Ä sleep ing +ij ing +k ind +Ä design ated +à ¤ +Ä anim ation +ke e +Ä Int rodu +Ä / > +Ä delay ed +Ä trem end +Ä cur ious +U se +Ä le ct +d am +Ä innov ation +Ä Point s +Ä load ing +Ä disp ute +ct ic +ird s +Ä B Y +Ä n urs +Ä Val ue +ION S +Ä H um +Ä tem plate +m ers +Ä appear ances +Ä Enter tainment +Ä transl ation +Ä sa ke +Ä bene ath +Ä in hib +Ä e uro +abet es +Ä stud ying +Ä M as +Ä per ceived +Ä exam ined +Ä e ager +Ä co aches +Ä im per +ch i +Ä produ ces +" ). +Ä Every one +Ä m unicip +Ä g irlfriend +Ä h ire +Ä V ice +Ä su itable +op y +Ä in equ +Ä D uke +f ish +f irst +Ä O bs +Ä inter ior +Ä Bru ce +Ä R y +Ä anal ys +Ä consider able +Ä fore cast +Ä f ert +ors hip +Ä D rug +Ä A LL +: " +th ur +Ä M ail +Ä ball ot +Ä inst antly +Ä Ch annel +Ä p icks +Ä 198 9 +Ä t ent +ol i +Ä civil ian +b ling +ell o +b u +Ä in ch +Ä log o +Ä cooper ation +Ä wal ks +Ä invest ments +Ä imp rison +Ä F estival +Ä K y +Ä leg ally +Ä g ri +ch arg +S l +Ä threat ening +du ction +fl ow +Ä dismiss ed +ibr aries +c ap +e le +Ä Mc G +Ä Har vard +Ä Conserv ative +Ä C BS +p ng +Ä ro ots +Ä H aving +umb led +Ä F un +\ / +Ä S earch +ple x +Ä discuss ing +Ä contin u +Ä T ai +Ä W ik +F ree +f it +Ä ref use +Ä manag ing +Ä sy nd +ip edia +w alk +Ä profession als +Ä guid ance +Ä univers ities +Ä as semb +unt u +F inally +AS E +Ä Aut o +Ä H ad +Ä ann iversary +L D +Ä D ur +Ä Ult imate +ih ad +pro duct +Ä trans it +Ä rest ore +Ä expl aining +Ä ass et +Ä transfer red +Ä bur st +ap olis +Ä Mag azine +Ä C ra +Ä B R +gg ed +Ä H E +M ich +b et +Ä L ady +yl um +erv es +Ä me ets +wh ite +L og +Ä correspond ing +Ä ins isted +G G +Ä surround ed +Ä t ens +Ä l ane +Ä co inc +h ome +Ä exist ed +ect ed +Ä Dou ble +lam m +Ä ske pt +ex p +Ä per ception +ie v +Ä Be ing +o ft +Ä adop t +. : +] ; +Wind ows +Ä satell ite +AS H +Ä inf ant +d escription +Ä Me anwhile +c m +oc a +Ä T reat +act or +Ä tob acco +Ä N orm +em ption +Ä fl esh +Ä j e +o op +Ä He aven +Ä be ating +an im +Ä gather ing +Ä cult iv +G O +ab e +Ä Jon athan +Ä Saf ety +Ä bad ly +pro t +Ä cho osing +Ä contact ed +Ä qu it +Ä dist ur +Ä st ir +Ä to ken +D et +Ä P a +Ä function ality +00 3 +s ome +Ä limit ations +Ä met h +b uild +con fig +N T +re ll +ble m +Ä M om +Ä veter ans +Ä H u +Ä trend s +are r +Ä G iven +Ä Ca ption +m ay +AS T +Ä wond ering +Ä Cl ark +n ormal +Ä separ ated +Ä des p +st ic +b rew +Ä rel ating +Ä N ik +Ä F arm +Ä enthus i +g ood +d eb +Ä activ ist +Ä m art +Ä explos ion +Ä Econom ic +L ink +Ä ins ight +Ä conven ient +Ä counter part +su pport +Ä V irt +ag en +Ä Tenn essee +Ä Sim on +Ä A ward +OC K +Ä F igure +Ä overse as +Ä pr ide +Ä C as +n ote +m g +C urrent +Ä displ ays +cont ent +Ä travel ing +Ä hosp itals +Ä Fin ancial +Ä P ast +Ä defend ant +Ä stream ing +m ble +Ä Ber lin +uk i +Ä dist ribut +Ä ant ib +Ä ch ocolate +Ä Cast le +Ä inter rupt +Ä R ow +Ä convers ion +Ä bug s +Ä R ather +li est +L Y +Ä Je an +com mon +ak h +Ä 1 30 +ot ton +Ä De an +Ä am endment +Ä game play +Ä War ren +od a +Ä high lights +Ä ir re +Ä NAT O +Ä ball s +Ä demand ing +U RE +Ä L uke +F igure +st op +on ia +z one +iz ers +Ä W R +Ä award ed +Ä regul atory +Ä H art +Ä S N +pl ing +Ä s our +Ä P ixel +us ive +Ä f et +Ä S ent +Ä autom atic +Ä f er +vern ment +Ä Kh an +T ON +f ather +Ä extraord inary +th rop +Ä P ython +Ä G PU +Ä sex ually +Ä desk top +it ivity +Ä Anton io +Ä o rient +Ä e ars +ob by +ous es +vertis ements +Ä manufacture rs +ic ient +min ute +Ä conv iction +Ä g arden +p ublic +Ä satisf ied +f old +O K +Ä in hab +Ä Th ink +Ä program me +Ä st omach +Ä coord in +Ä h oly +Ä th reshold +Ä r het +Ä ser ial +Ä employ ers +Ä Every thing +ra h +Ä b other +Ä br ands +Val ue +Ä T ed +Ä Plan et +Ä p ink +Ä Further more +s a +P E +re ck +Ä US D +ot te +Ä & & +Ä land ed +g ets +Ä produ cers +Ä health care +Ä domin ant +Ä dest ro +Ä am ended +ch ron +Ä f its +Ä Sy d +Ä Author ity +AT CH +Ä fight s +Ä L LC +Ä -- - +Ä Cor p +Ä tox ic +spe cific +Ä C orn +Ä Che l +Ä tele phone +Ä P ant +Ä myster ious +aun ch +od ox +med ia +Ä witness es +ag u +Ä question ed +Ä Bre xit +Ä Rem ember +ene z +Ä end orse +iat ric +Ä Id ent +Ä ridic ulous +1 10 +Ä pr ayer +Ä scient ist +Ä 19 50 +Ä A qu +Ä under ground +Ä U FC +m are +Ä L ater +w ich +Ä subsc rib +Ä host s +Ä er r +Ä gr ants +ant om +Ä sum mon +ear ly +Ä C lear +Ä Pr im +Ä susp ension +Ä guarant eed +app er +Ä r ice +Ä Se an +Ä Sh in +Ä refere ndum +Ä fl ed +r ust +Ä 3 60 +ter y +Ä sh ocked +B R +Ä O il +Ä All ah +Ä part ly +Ä ign or +Ä trans mission +Ä hom osexual +ivers al +Ä hop efully +ÃŖÄ¤ ¤ +Ä less on +L eg +Ä  .. +Y et +t able +app ropri +re tt +Ä bo ards +Ä incor rect +Ä b acteria +ar u +am ac +Ä sn ap +.' " +Ä par ad +t em +he art +Ä av ailability +Ä w isdom +Ä ( + +Ä pri est +ĠÂł ĠÂł +O pen +Ä sp an +Ä param eter +Ä conv ince +Ä ( %) +r ac +Ä f o +Ä safe ly +Ä conver ted +Ä Olymp ic +Ä res erve +Ä he aling +Ä M ine +M ax +Ä in herent +Ä Gra ham +Ä integ rated +D em +Ä pip eline +Ä app lying +Ä em bed +Ä Charl ie +Ä c ave +200 8 +Ä cons ensus +Ä re wards +P al +Ä HT ML +Ä popular ity +look ing +Ä Sw ord +Ä Ar ts +' ) +Ä elect ron +clus ions +Ä integ rity +Ä exclus ively +Ä gr ace +Ä tort ure +Ä burn ed +tw o +Ä 18 0 +P rodu +Ä ent reprene +raph ics +Ä g ym +ric ane +Ä T am +Ä administr ative +Ä manufacture r +Ä  vel +Ä N i +Ä isol ated +Ä Medic ine +Ä back up +Ä promot ing +Ä command er +Ä fle e +Ä Rus sell +Ä forg otten +Ä Miss ouri +Ä res idence +m ons +Ä rese mb +Ä w and +Ä meaning ful +P T +Ä b ol +Ä he lic +Ä wealth y +Ä r ifle +str ong +row ing +pl an +as ury +ÃĸÄĸÂĻ . +Ä expand ing +Ä Ham ilton +Ä rece ives +S I +eat ures +Ä An im +RE E +P ut +Ä brief ly +ri ve +Ä stim ul +Ä `` ( +Ä  __ +Ä ch ip +Ä ha z +Ä pri ze +Ä Th ings +AC E +ul in +d ict +ok u +Ä associ ate +ock ets +y outube +St ory +ateg ory +Ä m ild +ail ing +Ä Y e +O rig +Ä K a +or ig +Ä propag anda +Ä an onymous +Ä strugg led +Ä out rage +AT ED +Ä Be ijing +r ary +Ä le ather +Ä world s +Ä broad er +12 5 +id al +Ä Bet ter +Ä t ear +E xt +Ä propos als +Ä it er +Ä Squ ad +Ä vol unt +m i +D id +Ä P u +p in +Ä speak ers +Ä b orders +Ä fig ured += ' +Ä simultane ously +aed a +Ä charg ing +Ä ur ged +Ä con j +25 6 +Ä G ordon +mer ce +Ä document ary +Sh are +it ol +ON E +Ä G arden +h att +Ä Thom pson +ane ous +ap ore +Ä t anks +Ä less ons +tr ack +Ä out standing +Ä volunte ers +Ä sp ray +Ä manag ers +l arge +Ä camp s +Ä art ificial +Ä R u +Ä b ags +th al +Ä compat ible +Ä Bl ade +Ä f ed +Ä arg ues +F I +Ä unf air +Ä cor n +Ä off set +Ä direct ions +Ä disappoint ed +Ä Con vention +Ä view ing +M E +oc ity +Ä town s +Ä lay ers +Ä ro lled +Ä jump ed +Ä att ribute +Ä un necess +inc oln +Ä supp ose +Ä Net her +ch a +Ä bur ied +Ä six th +B en +ress ing +OU R +Ä w ound +Ä cy cl +Ä mechan isms +Ä congress ional +Ä E lement +Ä agre ements +Ä dec or +Ä clos est +Ä M it +Go ogle +} } +Ä m ixture +Ä flu id +S ign +Ä Sch olar +Ä p ist +ask et +ab ling +Ä rac ing +he ro +ri el +ass y +Ä che aper +b en +Ä vert ical +amac are +Ä Read ing +g ments +Ä helic op +Ä sacr ifice +ay a +p aren +V A +Ä L es +Ä Stud io +Ä viol ations +Ä An na +ac er +Ê ž +Ä R at +Ä Be ck +Ä D ick +Ä A CT +Ä comp osition +Ä text ure +Ä O wn +Ä smart phone +Ä N A +Ä for b +im port +Ä def ending +il st +re r +Ä o h +Ä Jere my +Ä bank ing +cept ions +Ä respect ive +/ . +Ä dr inks +Ä W i +Ä b ands +Ä L iverpool +Ä g rip +Ä B uy +Ä open ly +Ä review ed +per t +Ä ver ify +Ä Co le +Ä W ales +M O +Ä un pre +Ä shel ter +Ä Im perial +Ä gu i +Ä D ak +Ä suggest ions +Ä explicit ly +Ä sl ave +Ä block chain +Ä compet ing +Ä prom ising +S ON +Ä soc cer +Ä const itution +4 29 +Ä dist ract +Ä U ser +es ides +Ä Met hod +Ä Tok yo +Ä accompan ied +Cl ient +s ur +al og +Ä ident ification +Ä inv asion +as ma +Ä indust ries +pp ers +Ä sub tle +Ä Un it +n atural +Ä surv ived +Ä fl aw +Äē ħ +Ä H oll +Ä def icit +Ä tut orial +Ä Ch ance +Ä arg uing +Ä contem porary +Ä integ ration +for ward +Ä t um +it is +Ä h iding +Ä D omin +Ä T an +Ä B uilding +Ä V in +Ä spokes person +Ä Not es +Ä emer ging +Ä prepar ation +Ä pro st +Ä suspect s +Ä aut onom +D escription +Ä deal t +Ä P ear +Ä stead y +Ä decre ased +Ä so vere +Ä Cl in +Ä grad ually +ors es +Ä W AR +S erv +ÃŖÄ¤ Âĸ +h r +Ä d irty +Ä B arn +Ä B C +Ä d il +Ä cal endar +Ä compl iance +Ä ch amber +b b +Ä pass enger +ate ful +Ä T itle +Ä Syd ney +Ä G ot +Ä dark ness +Ä def ect +Ä pack ed +ass ion +Ä god s +Ä h arsh +IC K +le ans +Ä algorith m +Ä oxy gen +Ä vis its +Ä bl ade +Ä kil omet +Ä Kent ucky +Ä kill er +P ack +enn y +Ä div ine +Ä nom ination +be ing +Ä eng ines +Ä c ats +Ä buff er +Ä Ph ill +Ä tra ff +AG E +Ä tong ue +Ä rad iation +ere r +m em +Ä Expl icit +ʞ į +Ä cou ples +Ä phys ics +Ä Mc K +Ä polit ically +aw ks +Ä Bl oom +Ä wor ship +e ger +ut er +Ä F O +Ä mat hemat +Ä sent enced +Ä dis k +Ä M arg +Ä / * +P I +Ä option al +Ä bab ies +Ä se eds +Ä Scott ish +Ä th y +] ] +Ä Hit ler +P H +ng th +Ä rec overed +ing e +Ä pow der +Ä l ips +Ä design er +Ä dis orders +Ä cour age +Ä ch aos +" },{" +Ä car rier +b ably +H igh +Ä R T +es ity +l en +Ä rout es +u ating +F il +N OT +w all +s burgh +Ä eng aging +Ä Java Script +ore r +li hood +Ä un ions +Ä F ederation +Ä Tes la +Ä comple tion +Ä T a +Ä privile ge +Ä Or ange +Ä ne ur +paren cy +Ä b ones +Ä tit led +Ä prosecut ors +Ä M E +Ä engine er +Ä Un iverse +Ä H ig +n ie +o ard +Ä heart s +Ä G re +uss ion +Ä min istry +Ä pen et +Ä N ut +Ä O w +Ä X P +in stein +Ä bul k +S ystem +ic ism +Ä Market able +Ä pre val +Ä post er +Ä att ending +ur able +Ä licens ed +Ä G h +et ry +Ä Trad able +Ä bl ast +à ¤ +Ä Tit an +ell ed +d ie +H ave +Ä Fl ame +Ä prof ound +Ä particip ating +Ä an ime +Ä E ss +Ä spec ify +Ä regard ed +Ä Spe ll +Ä s ons +own ed +Ä m erc +Ä exper imental +land o +h s +Ä Dun geon +in os +Ä comp ly +Ä System s +ar th +Ä se ized +l ocal +Ä Girl s +ud o +on ed +Ä F le +Ä construct ed +Ä host ed +Ä sc ared +act ic +Ä Is lands +Ä M ORE +Ä bl ess +Ä block ing +Ä ch ips +Ä ev ac +P s +Ä corpor ation +Ä o x +Ä light ing +Ä neighb ors +Ä U b +ar o +Ä be ef +Ä U ber +F acebook +ar med +it ate +Ä R ating +Ä Qu ick +Ä occup ied +Ä aim s +Ä Add itionally +Ä Int erest +Ä dram atically +Ä he al +Ä pain ting +Ä engine ers +M M +Ä M ust +Ä quant ity +P aul +Ä earn ings +Ä Post s +st ra +ÃŖÄĨÂŧ ÃŖÄĨ +Ä st ance +Ä dro pping +sc ript +Ä d ressed +M ake +Ä just ify +Ä L td +Ä prompt ed +Ä scr ut +Ä speed s +Ä Gi ants +om er +Ä Ed itor +Ä describ ing +Ä L ie +ment ed +Ä now here +oc aly +Ä inst ruction +fort able +Ä ent ities +Ä c m +Ä N atural +Ä inqu iry +Ä press ed +iz ont +for ced +Ä ra ises +Ä Net flix +Ä S ide +Ä out er +Ä among st +im s +ows ki +Ä clim b +ne ver +Ä comb ine +d ing +Ä comp r +Ä signific ance +Ä remem bered +Ä Nev ada +Ä T el +Ä Sc ar +Ä War riors +Ä J ane +Ä cou p +b as +Ä termin al +, - +O H +Ä t ension +Ä w ings +Ä My ster +ïÂŋÂŊïÂŋÂŊ ïÂŋÂŊïÂŋÂŊ +Ä Un like +val id +viron ments +Ä Al i +Ä n aked +book s +Ä M un +Ä G ulf +Ä d ensity +Ä dim in +Ä desper ate +Ä pres idency +Ä 198 6 +h y +IN D +Ä un lock +im ens +Ä hand led +Ä E b +Ä disapp eared +Ä gen re +Ä 198 8 +Ä determin ation +St ream +ik o +ap ters +Ä acknow ledge +J an +Ä capital ism +P at +Ä 20 20 +Ä pain ful +Ä cur ve +Ä bom bs +st orm +Ä Met al +en cer +Ä F ig +Ä A aron +anc hes +Ä ins piration +Ä exha ust +t ains +ash i +Ä desc ript +Ä r itual +Ä Chel sea +Ä promot ion +Ä H ung +Ä W ard +iv a +Ä E T +Ä to ss +all ow +Ä Franc is +D ep +Ä happ iness +Ä Gl ass +Ä bet a +Ä streng then +N E +o a +Ä butt ons +Ä Mur ray +Ä kick ed +Qu est +Ä T alk +Ä S everal +Ä Z ero +Ä dr one +ul k +Ä c am +Ä M obile +Ä prevent ing +Ä ret ro +Ä A x +Ä cru el +Ä flo at +. ), +Ä fil ing +Ä Gr ant +Ä B or +Ä r ib +Ä champions hip +Ä M erc +Ä sty les +Ä c ake +Ä build s +Ä S elf +io x +Ä ep ic +oy d +B el +Ä St ew +. ( +ah u +Ä Be yond +Ä out s +Ä sol o +Ä T ree +Ä pres erve +Ä t ub +AR E +ro c +Ä Im pro +Ä W right +Ä bu nd +Ä tr aged +Ä occas ional +b ian +Sec ond +r ons +Ä inter actions +form ed +s ing +Ä own s +Ä h ockey +Gener al +Ä log ical +Ä exp end +Ä esc al +Ä Gr iff +Ä C rown +Ä Res erve +Ä sto pping +Ä exc use +sec ond +Ä oper ated +Ä re aches +Ä Mal ays +Ä poll ution +Ä Brook lyn +Ä de lete +Ä has h +Bl ock +ah a +ÃĸÄĸ Âŗ +Ä sh orter +p iece +> >> +Ä M ormon +t or +Ä partic les +Ä B art +ry ption +Ä ad min +Ä squ ee +VID IA +Ä creat or +iam eter +ic ular +N BC +Ä grab bed +Ä n odd +Ä r ated +Ä rot ation +Ä gr asp +Ä excess ive +Ä E C +Ä Wh it +Ä invent ory +ault s +Ä F B +Ä e cosystem +Ä bill ions +Ä vent ure +n amed +Ä def ender +out e +Inst ead +ir able +W ar +Ä assum ption +Ä b ite +Ä earth qu +t ail +sp ace +Ä gif ts +boy s +Ä inev itable +Ä struct ural +Ä benef icial +Ä compe lling +h ole +erv ation +Ä co at +o j +inc arn +Ä Y ears +Ä determin ing +Ä rhet oric +Ä bound aries +Ä wh ites +A nt +add y +) - +ra ham +eter min +Ä har vest +Ä Con c +Ä lapt op +Ä M atch +Ä enjoy ing +cc a +oll ar +Ä tri ps +Ä add iction +Ä S ak +Ä pow ered +Ä c ous +Ä Russ ians +ie re +Ä ret rie +qu ality +Ä diff er +Ä king dom +Ä L aur +Ä Cap itol +Ä con clusions +Ä Al tern +Ä N av +Ä trans parent +B ER +G roup +Ä Com plete +Ä inf er +Ä int rig +Ä ins ane +R O +oph ob +is en +qu al +Mich ael +Ä m useum +Ä P ope +Ä res et +r ative +f ive +Ä agg reg +itte es +osit ory +Ä car b +Ä Rec ord +Ä dec ides +Ä F ix +Ä except ions +Ä Commission er +un s +Ä Environment al +Ä legend ary +ist ence +Ä tun nel +k m +Ä ins ult +Ä t roll +Ä sh ake +Ä det ention +qu es +Ä Ch rome +Ä F iles +Ä sub t +Ä prospect s +Ä pro l +re nder +pro of +Ä perform ances +St r +Ä h ref +ern ame +Ä achieve ment +Ä f ut +F ull +Ä Le ban +go ogle +ÃŖÄĨ ÄĒ +amp a +May be +Ä project ed +Ä E mb +Ä col leg +Ä a wards +Ä Ãĸ Äļ +G old +Ä Bl ake +Ä R aj +if ting +Ä p ending +Ä inst inct +Ä develop ments +Con nect +Ä M and +Ä W ITH +Ä Philipp ines +prof ile +Ä alt ogether +Ä B und +Ä T D +oo oo +amp ed +ip h +Ä ste am +Ä old est +Ä det ection +ul pt +Ä  ç +Ä Way ne +200 6 +f a +Ä cir cles +Ä F u +Ä don ors +appropri ate +Ä Dak ota +j amin +Ä motiv ated +Ä purch ases +Ä Louis iana +Ä S pl +Ä gl obe +Ä 10 5 +z ip +c all +Ä depart ments +Ä sustain able +10 5 +Ä O P +if iers +Ä prevent ed +Ä inc omp +Ä Comm ander +Ä dom inated +Ġ Âģ +Ä invest ed +Ä complex ity +Ä in cl +Ä ens uring +Ä real m +yn c +Ä Ind ependent +r ained +Ä J en +Ä Fl ight +Ä at he +Ä spec ulation +Ä T E +oc ate +t ic +Ä pl aint +her ry +Ä to y +Ä 1 11 +Ä pl ates +st atus +Ä Is a +Ä dev oted +C op +Ä E S +25 5 +ur rency +M ain +Ä sl aves +Ä pe pper +Ä qu otes +Ä ce iling +Ä F ish +Ä trans formation +Ä fra ction +Ä advant ages +Ä to ile +Ä stun ning +Ä mo ist +bre aking +s i +Ä L ocation +Ä Med ium +Ä text s +Ä u gly +Ä b io +. ÃĸÄĸÄļ +Ä B ased +Ä tr ains +Ä W ing +Ä An cient +Ä Rec ords +Ä H ope +Spe cial +ades h +ob i +[ / +Ä tempor arily +V er +h u +os er +Ä over night +Ä m amm +Ä Tre asury +Ä V enezuel +Ä Meg a +Ä t ar +Ä expect s +bl ack +or ph +\\ \\ +Ä accept ance +Ä rad ar +s is +Ä jun ior +Ä fram es +Ä observ ation +ac ies +P ower +Ä Adv anced +M ag +olog ically +Ä Me chan +Ä sent ences +Ä analy sts +augh ters +force ment +Ä v ague +Ä cl ause +Ä direct ors +Ä eval uate +Ä cabin et +M att +Ä Class ic +A ng +Ä cl er +Ä B uck +Ä resear cher +Ä 16 0 +Ä poor ly +Ä experien cing +Ä P ed +Ä Man hattan +Ä fre ed +Ä them es +ad vant +Ä n in +Ä pra ise +10 4 +Ä Lib ya +b est +Ä trust ed +Ä ce ase +Ä d ign +D irect +Ä bomb ing +Ä m igration +Ä Sci ences +Ä municip al +Ä A verage +Ä gl ory +Ä reve aling +Ä are na +Ä uncertain ty +Ä battle field +ia o +G od +Ä c inem +ra pe +el le +ap ons +Ä list ing +Ä wa ited +Ä sp otted +ke ley +Ä Aud io +e or +ard ing +idd ing +ig ma +Ä N eg +Ä l one +Ä  ---- +ex e +d eg +Ä trans f +Ä was h +Ä sl avery +Ä expl oring +Ä W W +ats on +Ä en cl +l ies +Ä C reek +Ä wood en +Man ager +Ä Br and +um my +Ä Ar thur +Ä bureau cr +Ä bl end +ar ians +F urther +Ä supposed ly +Ä wind s +Ä 19 79 +Ä grav ity +Ä analys es +Ä Tra vel +Ä V eter +Ä d umb +Ä altern ate +g al +Ä consum ed +Ä effect iveness +.' ' +Ä path s +ond a +L A +Ä Str ong +Ä en ables +Ä esc aped +Ä " " +Ä 1 12 +Ä 198 3 +Ä sm iled +Ä tend ency +F ire +Ä p ars +Ä R oc +Ä l ake +Ä f itness +Ä A th +Ä H orn +Ä h ier +Ä imp ose +m other +Ä p ension +ic ut +bor ne +ic iary +. _ +Ä S U +Ä pol ar +is y +eng u +itial ized +AT A +w rite +Ä exerc ises +Ä D iamond +ot ypes +Ä harm ful +on z +Ä print ing +st ory +Ä expert ise +Ä G er +Ä traged y +Ä F ly +Ä d ivid +amp ire +st ock +M em +Ä re ign +Ä un ve +Ä am end +Ä Prop het +Ä mut ual +Ä F ac +Ä repl acing +H ar +Ä Circ uit +Ä thro at +Ä Sh ot +Ä batter ies +Ä to ll +Ä address ing +Ä Medic aid +Ä p upp +Ä N ar +ol k +Ä equ ity +M R +Ä His pan +Ä L arge +m id +D ev +Ä exp ed +Ä dem o +Ä Marsh all +erg us +Ä f iber +Ä div orce +Ä Cre ate +Ä sl ower +Ä Park er +Ä Stud ent +Ä Tr aining +Ret urn +Ä T ru +Ä c ub +Ä Re ached +Ä pan ic +Ä qu arters +Ä re ct +Ä treat ing +Ä r ats +Ä Christian ity +ol er +Ä sac red +Ä decl are +ul ative +et ing +Ä deliver ing +est one +Ä t el +Ä L arry +Ä met a +ac cept +art z +Ä Rog er +hand ed +Ä head er +Ä tra pped +Ä Cent ury +Ä kn ocked +Ä Ox ford +Ä surviv ors +b ot +Ä demon stration +Ä d irt +Ä ass ists +OM E +Ä D raft +ortun ate +fol io +pe red +ust ers +g t +Ä L ock +Ä jud icial +ver ted +Ä sec ured +out ing +Ä Book s +Ä host ing +Ä lif ted +l ength +Ä j er +Ä whe els +Ä R ange +umbn ails +Ä diagn osis +te ch +Ä Stew art +Ä P ract +Ä nation wide +Ä de ar +Ä oblig ations +Ä grow s +Ä mand atory +Ä susp icious +! ' +A pr +G reat +Ä mort gage +Ä prosecut or +Ä editor ial +Ä K r +Ä process ed +ung le +Ä flex ibility +Ear lier +Ä C art +Ä S ug +Ä foc uses +Ä start up +Ä bre ach +Ä T ob +cy cle +ÃŖÄĸ ÄŽ +ro se +Ä b izarre +ÃŖÄĸ į +Ä veget ables +$ $ +Ä ret reat +osh i +Ä Sh op +Ä G round +Ä St op +Ä Hawai i +Ä A y +Per haps +Ä Be aut +uff er +enn a +Ä product ivity +F ixed +cont rol +Ä abs ent +Ä Camp aign +G reen +Ä ident ifying +Ä reg ret +Ä promot ed +Ä Se ven +Ä er u +ne ath +aug hed +Ä P in +Ä L iving +C ost +om atic +me ga +Ä N ig +oc y +Ä in box +Ä em pire +Ä hor izont +Ä br anches +Ä met aph +Act ive +ed i +Ä Fil m +Ä S omething +Ä mod s +inc ial +Ä Orig inal +G en +Ä spir its +Ä ear ning +H ist +Ä r iders +Ä sacr ific +M T +Ä V A +Ä S alt +Ä occup ation +Ä M i +Ä dis g +lic t +Ä n it +Ä n odes +e em +Ä P ier +Ä hat red +ps y +ÃŖÄĨ ÄĢ +Ä the ater +Ä sophistic ated +Ä def ended +Ä bes ides +Ä thorough ly +Ä Medic are +Ä bl amed +arent ly +Ä cry ing +F OR +pri v +Ä sing ing +Ä I l +Ä c ute +o ided +olit ical +Ä Ne uro +ÃĨ ¤ +Ä don ation +Ä Eag les +Ä G ive +T om +Ä substant ially +Ä Lic ense +Ä J a +Ä g rey +Ä An imal +Ä E R +Ä U nd +Ä ke en +Ä conclud e +Ä Mississ ippi +Eng ine +Ä Stud ios +P ress +o vers +ll ers +Ä 3 50 +Ä R angers +Ä r ou +ert o +E p +iss a +iv an +Ä se al +Ä Reg ist +dis play +Ä we aken +u um +Ä Comm ons +Ä S ay +Ä cult ures +Ä l aughed +Ä sl ip +Ä treat ments +iz able +m art +Ä R ice +Ä be ast +Ä ob esity +Ä La ure +ig a +Wh ich +hold er +Ä elder ly +Ä p ays +Ä compl ained +Ä c rop +Ä pro c +Ä explos ive +Ä F an +Ä Ar senal +A uthor +ef ul +Ä me als +Ä ( - +id ays +Ä imag ination +Ä ann ually +Ä m s +as ures +H ead +ik h +m atic +Ä boy friend +Ä Com puter +Ä b ump +Ä sur ge +Ä Cra ig +Ä Kir k +D el +medi ate +Ä scen arios +Ä M ut +Ä St ream +Ä compet itors +Ù ÄĻ +Ä Stan ford +Ä Res ources +az ed +b age +Ä organ is +Ä Re lease +Ä separ ately +Ä ha bits +Ä measure ments +Ä Cl ose +Ä accomp any +Ä g ly +Ä t ang +Ä R ou +Ä plug in +Ä con vey +Ä Chall enge +oot s +j an +Ä cur s +Ä Rel ations +ke eper +Ä approach ing +p ing +Spe aking +Ä arrang ement +Ä V I +are ttes +Ä affect ing +Ä perm its +b ecause +Ä u seless +Ä H us +!! !! +Ä destro ying +Un fortunately +Ä fasc inating +S em +Ä elect oral +Ä trans parency +Ä Ch aos +Ä volunte er +Ä statist ical +Ä activ ated +ro x +We b +H E +Ä Hamp shire +is ive +M ap +Ä tr ash +Ä Law rence +st ick +C r +Ä r ings +EX T +Ä oper ational +op es +D oes +Ä Ev ans +Ä witness ed +P ort +Ä launch ing +ec onom +w ear +Ä Part icip +um m +cul es +Ä R AM +Ä T un +Ä ass ured +Ä b inary +Ä bet ray +Ä expl oration +Ä F el +Ä ad mission +it ated +S y +Ä av oided +Ä Sim ulator +Ä celebr ated +Ä Elect ric +ÂĨ ŀ +Ä cl uster +itzer land +he alth +L ine +Ä N ash +at on +Ä sp are +Ä enter prise +Ä D IS +clud es +Ä fl ights +Ä reg ards +Ġà Ě +h alf +Ä tr ucks +Ä contact s +Ä unc ons +Ä Cl imate +Ä imm ense +N EW +oc c +ect ive +Ä emb od +Ä pat rol +Ä bes ide +Ä v iable +Ä cre ep +Ä trig gered +ver ning +Ä compar able +q l +Ä g aining +ass es +Ä ( ); +Ä G rey +Ä M LS +s ized +Ä pros per +" ? +Ä poll ing +Ä sh ar +Ä R C +Ä fire arm +or ient +Ä f ence +Ä vari ations +g iving +Ä P i +osp el +Ä pled ge +Ä c ure +Ä sp y +Ä viol ated +Ä r ushed +Ä stro ke +Ä Bl og +sel s +Ä E c +,' ' +Ä p ale +Ä Coll ins +ter ror +Ä Canad ians +Ä t une +Ä labor atory +Ä n ons +t arian +Ä dis ability +Ä G am +Ä sing er +al g +Ä Sen ior +Ä trad ed +Ä War rior +Ä inf ring +Ä Frank lin +Ä str ain +Ä Swed ish +Ä sevent h +Ä B enn +Ä T ell +Ä synd rome +Ä wond ered +id en +++ ++ +ig o +Ä pur ple +Ä journal ism +Ä reb el +Ä f u +bl og +Ä inv ite +ren cies +Ä Cont act +Is rael +Ä Cont ent +Ä che er +Ä bed room +Ä Engine ering +Ä Que ens +Ä d well +Ä Play Station +Ä D im +Ä Col on +l r +Ä oper ates +Ä motiv ation +US A +ast ered +C ore +Ä Tr uth +ol o +OS E +Ä Mem ory +Ä pred ec +Ä an arch +Ä 19 20 +Ä Y am +à ¨ +b id +Ä gr ateful +Ä exc itement +Ä tre asure +Ä long est +ct ive +Ä des erves +Ä reserv es +Ä cop s +Ä Ott awa +Ä Egypt ian +ank ed +Ä art if +Ä hypot hesis +: / +Ä purch asing +Ä love ly +H P +Ä div ide +Ä strict ly +Ä question ing +Ä taxp ayers +Ä J oy +Ä roll s +Ä He avy +Ä p orts +Ä mag netic +Ä inf lamm +Ä br ush +t ics +Ãĸ ÄĒÄ´ +Ä bott les +pp y +Ä p add +ÃŖÄ¤ ¯ +m illion +Ä devast ating +Ä comp iled +Ä med ication +Ä tw elve +Ä Per ry +Sp ace +im b +y our +Ä le aked +Ä T ar +Ä un ity +Ä infect ed +Ä travel ed +ID E +Ä Mc Donald +t xt +Ä Pr inc +Ä inter ven +Ä Tai wan +Ä P ow +Ä be aring +Ä Th read +Ä z ones +iz ards +un ks +Ch apter +ll or +Ġ ¡ +Ä w ounds +Ä disc retion +Ä succeed ed +ik ing +Ä icon ic +C all +Ä screen ing +Ä M is +ict s +Ä min isters +Ä separ ation +Pl ayer +Ä b ip +Ä bel oved +Ä count ing +Ä E ye +ar ound +ing ing +Ä table t +Ä off ence +in ance +h ave +Ä Inf o +Ä Nin ja +Ä protect ive +Ä C ass +M ac +Ä Qual ity +N orth +Ä  ic +Ä Cub a +Ä Chron icle +Ä Pro perty +Ä fast est +ot os +Ä G erm +OW N +Ä bo om +Ä Stan ley +ergus on +Ä cle ver +Ä ent ers +m ode +ter ior +Ä S ens +Ä lin ear +AR K +Ä comp aring +Ä pure ly +Ä saf er +Ä Pot ter +Ä c ups +R T +Ä gl uc +Ä att ributed +Ä du pl +Ä P ap +Ä prec ious +Ä p a +iction ary +Ä T ig +Ä To o +ol utions +st an +Ä rob ots +Ä lob b +Ä stat ute +Ä prevent ion +w estern +16 0 +Ä Act ive +Ä Mar ia +h al +N one +ell ar +Ä K B +Ä Part ners +Ä Sing le +Ä Follow ing +ang o +ac ious +Ä th ou +Ä k g +Ä influ ential +Ä Friend s +S ur +ain ted +Ä for ums +Ä st arter +Ä citizens hip +Ä E lection +on ge +ot ation +os ph +;; ;; +ut ical +p ur +ere n +Ä accus ations +bit ious +ab bit +Ä Or d +Post ed +ir k +Ä sens itivity +ic he +Ä Am y +Ä F ab +Ä sum mit +Ä ped est +Ä rub ber +Ä agric ultural +Ä can cel +A E +Ä in aug +Ä cont am +Ä firm ly +i w +st age +Ä K an +Ä t ier +Ä inv ention +Ä transl ated +Ä R ules +B ox +Tw itter +ID S +Ä p izza +Ä deb ug +Ä D rop +v s +Ä h orses +b ig +Ä b oring +Ä h ood +Ä McC ain +at ched +Ä Bro s +Ä sk ip +Ä ess ay +st at +Ä Leg ends +Ä am munition +au c +Ä shoot er +Ä un h +Ä suppl ied +Ä gener ic +Ä S K +ib an +yr ics +Ä 25 5 +Ä clim bing +Form er +Ä fl ip +Ä jump ing +Ä frust ration +Ä Ter ry +Ä neighborhood s +Ä med ian +be an +Ä br ains +Follow ing +Ä sh aped +Ä draw s +Ä al tered +J ack +Ä recip es +Ä sk illed +we alth +ach i +e lection +Ä behavi ors +de als +Ä U ntil +F e +Ä decl aration +mar ks +Ä Bet ween +cel ona +Ä res on +Ä bub ble +Am ong +Ä im perial +G S +Ä femin ist +200 5 +Ä K yle +Ä account ing +Ä Te le +Ä T yr +Ä connect ing +Ä re hab +Ä P red +s im +Ä meant ime +Ä phys ician +M W +Ä Camp bell +Ä Br andon +Ä contribut ing +Ä R ule +Ä We ight +Ä N ap +Ä inter active +Ä v ag +Ä hel met +Ä Com b +f our +Ä sh ipped +Ä comple ting +Ä P D +PD ATE +Ä spread ing +Ä sc ary +erv ing +Ä G as +Ä fr ank +s chool +Ä rom antic +Ä stab il +R ob +Ä accur ately +Ä ac ute +Ä H ann +Ä symbol s +Ä civil ization +Ä A W +Ä light ning +Ä cons iders +Ä ven ue +Ä  × +Ä o ven +Ä S F +h is +Ä n u +Ä Lear n +Ä pe oples +Ä st d +Ä sle e +Ä s lic +Ä Stat istics +Ä cor ners +Ä B aker +Ä : ) +ment ation +ol ver +Ä laugh ing +Ä T odd +ond e +Ä H ills +Ä n uts +Ä W oman +pl ane +Ä l iver +Ä In side +S orry +Ä agre es +Ä fund ament +Ä F isher +Ä a uction +Ä thread s +gl as +Ä Bas ic +Ä N at +Ä lack ing +Ä celeb ration +j u +Ä s illy +E uro +Ä t att +ight y +cont rolled +T est +Ä Sing h +Ä r age +Ä rh yth +o ffic +Ä Ph antom +Ä head lines +Ä respond ing +Ä Mor ning +Ä vit amin +Ä boot s +Ä S ite +al in +p i +Ä vir al +Ä U C +D ER +Ä Se x +Ä st ocks +c urrent +Ä ch urches +Ä R are +Ä Mur phy +Ä den ial +Ä G aming +Ä tou g +Ä n ick +Ä m akers +Ä Ron ald +Ä gener ous +Ä D oc +Ä Mor ris +Ä transform ed +Ä N ormal +Ä 10 4 +Ä Kick starter +Ä Up on +On line +Ä I RS +Ä w rap +Ä l oving +Ä arri ves +Ä D ue +Ä he ter +Ä M ade +Ä rent al +Ä belong s +Ä att orneys +Ä cro ps +Ä mat ched +ul um +ol ine +10 9 +Ä dis par +Ä buy ers +Ä Cam bridge +Ä eth ics +rou ps +Ä just ified +Ä marg inal +Ä respect ed +win ning +Ä nodd ed +Ä Ser ge +Ä Form er +C raft +######## ######## +Ä War ner +Ä d ash +et e +Ä ent ert +Ä E scape +out heast +Ä kn ees +Ä B omb +Ä r ug +P ass +Ä att itudes +go vernment +Ä Pri or +Ä qual ities +Ä not ification +Ä Ph one +l ie +Ä anticip ated +Ä Com bat +Ä Bar ry +Ä 198 2 +Us ers +on er +Ä comput ing +Ä Connect icut +Ä less er +Ä pe ers +Ä C u +Ä techn ically +Ä sub mission +Ä Un iversal +Ä man ually +our ge +Ä respond ents +Ä B TC +Ä H ost +Ä f are +Ä B ird +Ä rece ipt +al so +Ä j ack +Ä agric ulture +Ä sk ull +Ä ! = +Ä pass ive +Ä C I +Ä soc ieties +Ä remind ed +Ä inter ference +B uy +Ä Ãĸ Äž +g on +Ä scrut iny +Ä W itch +Ä conduct ing +Ä  ÃŖÄĨ +Ä exch anges +Ä Mit chell +Ä inhab it +Ä tw ist +B D +Ä where ver +group on +Ä j okes +Ä Ben jamin +Ä R andom +fr ame +Ä L ions +Ä highlight ed +Ä Ark ansas +E nt +Ä p ile +Ä pre lim +g s +mind ed +Ä fel ony +Ä G A +Ä L uck +Ä pract ically +Ä B os +Ä act ress +D am +Ä B ou +Ä vis a +Ä embed ded +Ä hy brid +Ä ear liest +Ä soon er +s ocial +Ä H A +Ä ste ep +Ä dis advant +Ä explo it +Ä E gg +Ä Ult ra +Ä necess ity +L ocal +ie ge +Ä d ated +Ä mass es +Ä subsc ription +pl ess +Ä an onym +Ä presum ably +Bl ue +The ir +asket ball +Ä Phil ip +Ä com ed +load ed +r ane +Ä ref lection +Ch ina +Ä ext ends +Ä form ing +Ä und ers +200 1 +Ä gr at +Ä concent rations +Ä ins ulin +Ä sec ular +Ä wh ilst +Ä win ners +Ad vertisements +Ä deliber ately +Ä Work ing +Ä s ink +et ics +d ale +Ä mand ate +Ä g ram +Ä vac ation +Ä warn ings +ri pp +Ä TH AT +Ä comment ary +Ä int u +Ä a est +Ä reason ing +Ä break down +Ä Z ombie +Ä -- > +Ä Polit ical +c ott +Ä thr ust +Ä techn ological +Ä dec iding +Ä traff icking +L ong +W elcome +pr ising +Ä Commun ications +Ä end ors +Ä sw ift +Ä metab ol +co ins +res a +Ä HT TP +Ä en roll +Ä H appy +us r +int age +Ä [ " +u ably +Ä M aterial +Ä repe al +Se pt +k h +Ä Mod i +Ä under neath +Ä I L +sh ore +Ä diagn osed +ace utical +Ä sh ower +au x +Ä Sw itch +Ä Stre ngth +Ä j ihad +n ational +Ä tra uma +uss y +on i +Ä cons olid +Ä cal ories +Ä F lynn +ag ged +16 8 +Ä P ink +Ä fulf ill +Ä ch ains +Ä not ably +Ä A V +L ife +Ä Ch uck +m us +Ä Ur ban +Ä H end +Ä dep osit +Ä S ad +Ä aff air +OR K +ie val +Ä F DA +Ä t rop +Ä Over all +Ä virt ue +Ä satisf action +au nd +Ä l un +Ä Sw itzerland +Ä Oper ation +pro cess +Ä sh ook +Ä count ies +le ased +Ä Charl otte +1 12 +Ä trans cript +Ä re dd +p ush +Ä He y +Ä An alysis +[ " +Ä altern atives +ard less +Ä ele ph +Ä pre jud +Ä Le af +H aving +Ä H ub +Ä express ions +Ä Vol ume +Ä shock ing +Ä Red s +Ä read ily +Ä plan ets +ad ata +Ä collaps ed +Ä Mad rid +Ä ir rit +i pper +Ä En c +Ä W ire +Ä bu zz +Ä G P +ash a +Ä accident ally +ur u +Ä frust rated +Ä S A +Ä hung ry +Ä H uff +Ä lab els +ant o +Ä E P +Ä bar riers +) | +Ä Ber keley +Ä J ets +Ä p airs +Ä L an +J ames +Ä B ear +Ä hum or +Ä Liber ty +Ä magn itude +Ä ag ing +Ä M ason +Ä friends hip +umb ling +Ä emer ge +Ä newsp apers +Ä am bitious +Ä Rich ards +atern al +Ä 198 1 +Ä cook ies +Ä sc ulpt +Ä pur suit +L ocation +Ä script s +p c +Ä arrang ements +Ä d iameter +Ä l oses +am ation +Ä l iqu +Ä J ake +aret te +Ä understand s +Ä Z en +v m +Ä appro ve +Ä w ip +Ä ult ra +Ä int end +Ä D I +asc ular +Ä st ays +Ä K or +Ä K l +Ä invest ing +L a +Ä belie ving +b ad +m outh +Ä taxp ayer +ÃŖÄĨ ÄĨ +Ä Que bec +Ä l ap +Ä Sw iss +d rop +Ä dr ain +ir i +et c +ft en +Ä N ex +Ä st raw +Ä scream ing +Ä count ed +Ä dam aging +Ä amb assador +cent ury +Ä pro x +Ä arrest s +u v +il ateral +Ä Ch arg +Ä presc ribed +Ä independ ently +Ä f ierce +Ä B aby +Ä b rave +Ä su its += > +Ä bas eline +Ä R ate +Ä is lands +Ä ( ( +g reen +ix els +Ä name ly +Ä Vill age +th an +am y +V ersion +g mail +ential s +Ä S ud +Ä Mel bourne +Ä arri ving +Ä quant um +e ff +rop olitan +T ri +Ä fun eral +Ä I R +ÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤ ÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤ +Ä C ob +it ably +Ä t urb +Ä comb o +Re view +Ä deploy ment +u ity +Ä B ott +Ä inv isible +Ä render ing +Ä unl ocked +Ä a qu +Ä Vlad imir +Ä p ad +Ä Br ain +Ä Leg acy +dr agon +Ä Kurd ish +Ä sound ed +Ä det ained +Ä D M +g ary +Ä d aughters +Ä distur bing +uk a +Ä Par ad +Ä t ast +Ä unf ortunate +Ä u l +em in +Ä attend ance +tr l +Ä par ks +Ä Mem orial +Ä Al ice +oth y +gu ard +Ä D ise +Ä Sh an +Ä For um +R ich +Ä shif ted +ue z +Ä l ighter +Ä Mag n +Ä c od +S ch +ham mad +P ub +3 50 +Ä P okemon +Ä prot otype +Ä un re +B ase +Ä Stud ents +Ä Rep ly +Ä Commun ist +Ä g au +Ä Ty ler +I Z +Ä particip ated +Ä sup rem +Ä Det ails +Ä vessel s +ro d +Ä t ribe +ke ep +Ä assum ptions +Ä p ound +Ä cr ude +Ä Av ailable +Ä swim ming +Ä in clusion +Ä adv ances +c ulation +Ä conserv ation +Ä over d +Ä Buff alo +Art icle +ed ge +Ä aw a +Ä Mad ison +Ä sid ew +Ä cat ast +Ä K rist +uc le +Ä High way +Ä Ter ror +Ä activ ation +Ä uncons cious +Ä Sat an +Ä Sus an +ill ery +Ä arr anged +i op +Ä rum ors +ur ring +th ink +Ä Ke ith +Ä K ind +Ä avoid ing +by n +n ut +Ä Spe aker +r us +n ames +Ä gu ilt +Ä Olymp ics +Ä sa il +Ä M es +lev ant +Ä Columb us +a ft +C ity +S outh +Ä Har vey +Ä P un +S everal +Ä ment ally +Ä imp ress +m ount +Ä Ub untu +ÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļ ÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļ +Ä Super man +Ä MP s +Ä intent ions +Ä R acing +Ä like lihood +Ä 2 40 +T otal +Ä to ys +Ä W atson +Ä ur ge +L ear +Ä P aper +Ä occur ring +Ä B eng +Ä C ert +Ä st ones +T im +Ä Tw in +z b +Ä D ynam +Ä polit ician +k ens +Ä Enter prise +UT ERS +Ä ab ol +Ä ref resh +Ä arbit rary +pe ction +Ä trou bles +Ä } ); +t v +Ä pil ots +Ä dist ribute +Ä aud it +Ä p ause +orig inal +Ä r ivals +Â ÂŖ +F ig +T L +ab il +ry ing +L in +ion ed +l on +Ä f ancy +Ä cr ashed +Ä t ract +Ä she d +Ä cons ume +B ased +down load +in it +Ä volt age +Int rodu +Ä condem ned +Ä Fin ance +res pect +Ä ex cluded +Ä establish ing +her ic +Ä her itage +Ä spect acular +Ä un st +Ä Snow den +Ä L ane +S an +Ä protect ions +st ruction +inc inn +Ä mac ro +C ustom +ios ity +Ä es p +Ä function ing +Ä m ush +Ä p uzzle +Ä eth ical +M al +Ä go verning +Ä F erguson +Ä rest ored +Ä st ressed +Ä Coun ter +Ä K as +cl ip +AN S +Ä se iz +U K +by ss +old own +ap i +Ä perman ently +oun ters +W est +Th rough +L ight +at oes +Ä ne at +Ä c ord +ure r +Ä severe ly +Ä A ven +Ä inter rog +Ä tri ple +G iven +N umber +Ä ar ise +Ä s her +pl ant +Ä fl ower +Ä C ou +Ä at e +Ä new er +b ul +Ä mean while +Ä L air +Ä adjust ment +Ä Cop yright +Ä d ivers +i ological +Ä gam ers +o at +Ä histor ically +Ä anal og +Ä long time +Ä pres cription +Ä M ist +Ä Hy per +Ä M aine +Ä De ity +Ä multi pl +Ä Re incarn +Ä H yd +Ä P ic +S il +r ants +Ä C ris +. ; +( { +epend ence +Ä rec y +ate ur +Ä qu ad +Ä gl ob +Ä con ced +te am +Ä capital ist +Ä L ot +Ä roy al +Ä Cy ber +Ä black s +met ic +ri v +Ä D anny +Ä sp o +Ä R O +Ä anim ated +rypt ed +Ä Dep uty +Ä rend ered +F E +Ä stre ak +Ä cloud s +Ä Dou g +~~~~ ~~~~ +Ä disc our +Ä Ve h +Ä psych ology +Ä J ourney +Ä cry stal +Ä Fro st +Ä suspic ion +Ä rel ate +or us +Ä C rypt +Ä N VIDIA +com ed +ut ing +incinn ati +Ä vulner ability +ost ic +Ä isol ation +Ä cool ing +Ä Coal ition +Ä 1 19 +F our +Ä De al +Ä Ãĸ ÄĢ +se mble +ram ent +Ä Bar celona +Ä 10 2 +Ä coc aine +ocaly pse +F eb +ogen ic +Ä mut ation +Ä crypt oc +Ä K el +Ä G it +a is +Ä s isters +AN K +Ä activ ate +T er +Ä d read +yl on +Ä prop ri +A ust +Ä Def ault +Ä out door +Ä she er +ce ive +Ä g ently +Ð ž +Pro gram +Ä Ãĸ ĨĴ +Ä ve gan +Ä Cr us +Ä respons ibilities +Ä H R +OL D +Ä prev ents +Ä st iff +Ä W ere +Ä athlet ic +Ä Sc ore +Ä ) : +Ä column s +Ä L oc +av ailable +Ä F ram +Ä S essions +Ä compan ion +Ä pack s +14 0 +Ä Kn ights +Ä f art +Ä stream s +Ä sh ore +Ä app eals +Ä Per formance +h aul +Ä St ra +Ä N ag +10 3 +Ä Trans portation +B B +E v +z an +P ublic +Ä tw in +uls ion +M ult +Ä elect ro +Ä stat ue +ation ally +Ä N ort +Ä ins pection +/ * +ig ue +Ä comp assion +Ä T ales +Ä Ste in +Ä Sc reen +Ä B ug +Ä L ion +g irl +Ä withdraw al +Ä object ives +Ä blood y +Ä prelim inary +Ä j acket +Ä dim ensions +Ä C ool +Ä Occ up +Ä w reck +Ä doub led +ank ing +Ä 19 75 +Ä glass es +Ä W ang +pro v +P ath +connect ed +Ä Mult i +Ä Nor way +agon ist +Ä fe ared +Ä touch ing +Ä arg uably +¯¯¯¯ ¯¯¯¯ +Ä NC AA +che m +Ä sp at +Ä W WE +Ä C el +ig ger +Ä attack er +Ä Jo in +ob ject +ett a +Ä elim inated +d et +Ä dest ruct +Ä Luc as +ct uary +18 0 +Ä Br ady +Ä Bl ues +B ay +au kee +Ä tim eline +Ä deleg ates +w ritten +uff icient +Ä sh apes +Cop yright +ou ble +serv ice +Ä p ione +Ä colleg es +Ä row s +Ä sp ite +Ä assess ed +3 60 +Ä le ase +Ä confident ial +ck er +Ä Man ning +Ä V oice +Ä se aled +Ä calcul ate +N O +Ä Ass istant +Ä teen ager +ul ent +ather ine +Ä m ock +Ä d iamond +Ä f est +Ä sw itched +Ä res ume +Ä Pu erto +Ä l anes +ir ation +Ä Similar ly +Ä ro d +Ä S el +Ä Pal ace +Ä Lim ited +e ous +Ä var iant +Ä w ard +Ä ) ) +Sh ow +OO K +A lex +Ä N ep +br is +Ä Wik ipedia +Ä except ional +Ä man ages +Ä D raw +Ag ain +Ä co pper +ut t +Ä ex ports +Ä port folio +Ä elev ated +R ated +Ä Other wise +Ä T act +Ä She l +Ä T X +" ÃĸÄĸÄļ +Ä res ur +Ä W a +ven ant +Ä mon etary +pe ople +E mail +Ä fif ty +Ä S weet +Ä Malays ia +Ä conf using +Ä R io +ud a +uten ant +" ); +Ä pra ised +Ä vol umes +t urn +Ä m ature +Ä non profit +Ä passion ate +Ä Priv ate +Ä 10 3 +Ä desc end +ç ÂĨŀ +uff y +head ed +Whe ther +ri en +ze ch +be it +Ä ch rom +Ä Mc M +Ä d ancing +Ä e leg +Ä Not iced +11 5 +Ä advoc acy +ENT S +amb ling +Ä Min or +Ä F inn +Ä prior ities +Ä there of +Ä St age +Ä Rog ers +Ä subst itute +Ä J ar +Ä Jeff erson +Ä light ly +10 2 +Ä L isa +u its +ys ical +Ä shif ts +Ä d rones +Ä work place +Ä res id +ens ed +ah n +Ä pref erences +ser ver +Ä deb ates +d oc +Ä God s +Ä helicop ter +Ä hon our +Ä consider ably +ed ed +Ä F emale +Ä An ne +Ä re un +Ä F ace +Ä Hall ow +Ä Bud get +Ä condem n +Ä t ender +Pro f +ocr atic +Ä Turn er +Ä Ag ric +Ä 19 76 +Ä a pt +d isc +Ä F ighter +Ä A ur +Ä gar bage +in put +Ä K arl +Ä Ol iver +Ä L anguage +k n +N on +Ä Cl ar +Ä trad itions +Ä ad vertisement +Ä S or +Ä arch ive +Ä vill ages +7 50 +Ä implement ing +w aukee +Ä diet ary +Ä switch ing +Rep ublic +Ä vel ocity +Ä c it +Ä A wards +Ä fin ancing +Ä last ed +) ] +Ä rem inder +P erson +Ä prec ision +Ä design ers +Ä F ried +Ä B order +Ä tr agic +Ä w ield +Ä initi atives +Ä T ank +w er +Ä jo ins +R o +in ery +Ä ar row +Ä gener ating +found er +Ä sear ches +Ä random ly +A ccess +Ä b atch +Ä p osed +l at +Ä pursu ing +as a +Ä test ified +form ing +Ä Sh ar +w iki +Ä E ither +S ometimes +Ä sen ators +Ä John ny +Ä Tal iban +Ä G PS +":" / +ÃŖÄŖÂŽ ÃĨ +Ä analy zed +Ä Rub io +Ä Move ment +op ard +ii i +St and +f ight +Ä ign oring +i ang +Ä G N +so ever +Ä ST AT +Ä ref using +Ä swe at +Ä b ay +P ORT +ir med +ak y +Ä dis pro +Ä label ed +Ä 10 8 +H ello +Ä ple asant +ab a +Ä tri umph +Ä ab oard +Ä inc om +Ä C row +le tt +Ä fol k +Ä ch ase +` ` +Ä Br us +Ä te ens +c ue +Ä ter rain +h yd +il ight +OR Y +Su pport +ew s +ll i +rain ts +Ä C and +Ä ab used +ach ment +l arg +B as +Ä C ancer +Ä 19 78 +Ä supp orter +ac cess +Ä Ter min +Ä T ampa +Ä AN Y +Ä new est +Ä Crim inal +ed u +Ä 19 30 +Ä adm its +Ä end e +Ä fail ures +ur ate +ful ness +cy cl +Ä Sub ject +Ä inf inite +th ree +W A +p it +Ä Inst all +R ad +ili ation +G M +Ä contin ent +Ä accommod ate +Ä Cl ay +Ä p up +Ä F unction +Ä ham mer +Ä Albert a +Ä rev ised +Ä minor ities +Ä measure ment +Con nell +Ä dis able +Ä M ix +In cre +Ä for k +Ä R osen +Ä impl ies +umb lr +AN G +Ä prote ins +Ä agg ression +Ä facilit ate +S N +Ä illeg ally +u er +Ä acad em +Ä p uzz +Ä Sh ift +p ay +oll o +Ä aud iences +B uild +Ä no ble +Ä synt ax +Ãĸ Äēħ +Ä be am +Ä B ed +Ä A ld +Ä orig ins +v ideo +Ä 19 77 +Ä Ass ault +Ä gar age +Te am +Ä ver dict +Ä d war +Ä Virt ual +e vent +Ke ep +Ä sent iment +Ä wild life +sh irt +Ä b urg +Ä recommend ation +rep resent +Ä gall ery +own ers +Ä sch olar +Ä conven ience +Ä Sw ift +Ä conv inc +C ap +Ä war fare +Ä Vis ual +Ä const itute +Ä ab ort +Ä We ather +Ä Look ing +Ä H em +Ä mart ial +Ä inc oming +et ition +Ä toler ance +Ä Cre ated +Ä fl ows +Ä E lder +Ä soul s +Ä f oul +Ä P ain +Ä C AN +Ä 2 20 +b c +he nd +Ä gen ius +R eal +Ä W r +omet er +p ad +Ä lim iting +Ä S i +Ä L ore +Ä Ad ventures +Ä var ied +D isc +f in +Ä Person al +Ch ris +Ä inv ented +Ä d ive +Ä R ise +Ä o z +Ä Com ics +Ä exp ose +Ä Re b +let ters +s ite +im ated +Ä h acking +Ä educ ated +Ä Nob ody +Ä dep ri +Ä incent ive +ÃŖÄ¤ ¡ +Ä overs ight +Ä trib es +Ä Belg ium +Ä licens ing +our t +Produ ct +ah l +Ä G em +Ä special ist +Ä c ra +ann ers +Ä Cor byn +Ä 19 73 +RE AD +Ä sum mar +Ä over look +Ä App lication +Ä in appropriate +Ä download ed +Q ue +Ä B ears +Ä th umb +Ä Char acter +Ä Reincarn ated +Ä S id +Ä demonstr ates +s ky +Ä Bloom berg +Ä Ar ray +Ä Res ults +Ä Four th +Ä ED T +Ä O scar +c end +Ä 10 6 +Ä N ULL +Ä H ERE +m atch +Ä Br un +Ä gluc ose +ie g +eg u +Ä cert ified +Ä rel ie +Ä human itarian +Ä pr ayers +K ing +Ä n an +h ou +10 8 +ul u +Ä renew able +Ä distingu ish +Ä d ense +Ä V ent +Ä Pack age +Ä B oss +Ä edit ors +Ä m igr +T ra +Ä Pet ers +Ä Ar ctic +200 4 +Ä C ape +Ä loc ally +Ä last ing +Ä hand y +. ). +P an +Ä R ES +Ind ex +Ä t ensions +Ä former ly +Ä ide ological +Ä sens ors +Ä deal ers +Ä def ines +S k +Ä proceed s +Ä pro xy +az ines +Ä B ash +Ä P ad +Ä C raft +eal ous +Ä she ets +omet ry +J une +cl ock +T T +Ä The atre +Ä B uzz +Ä ch apters +Ä mill enn +Ä d ough +Ä Congress ional +Ä imag ined +av ior +Ä clin ic +Ä 19 45 +Ä hold er +ro ot +oles ter +Ä rest art +B N +Ä Ham as +Ä J ob +Ä or b +Ä r am +Ä discl ose +Ä transl ate +Ä imm igrant +Ä annoy ing +Ä treat y +an ium +Ä Te a +Ä Leg ion +Ä crowd s +Ä B ec +Ä A er +oh yd +B ro +Look ing +Ä l bs +Ä agg ress +Ä se am +Ä inter cept +Ä M I +mer cial +act iv +Ä C it +Ä dim ension +Ä consist ency +Ä r ushing +Ä Dou glas +Ä tr im +Inst all +ick er +Ä sh y +10 6 +Ä ment ions +pe lled +Ä T ak +c ost +Ä class room +Ä fort une +dri ven +Ä un le +Ä Whe el +Ä invest or +Ä M asters +k it +Ä associ ations +Ä Ev olution +op ing +us cript +Ä prov incial +Ä Wal ter +av i +S O +Ä un limited +Eng lish +Ä C ards +Ä Eb ola +ne red +Ä reven ge +Ä out right +um per +Ä f itting +Ä Sol id +Ä form ally +Ä problem atic +Ä haz ard +Ä enc ryption +Ä straight forward +Ä A K +Ä p se +Ä Or b +Ä Ch amber +Ä M ak +Cont ents +Ä loyal ty +Ä l yrics +Ä Sy m +Ä wel comed +Ä cook ed +Ä mon op +Ä n urse +Ä mis leading +Ä e ternal +Ä shif ting +Ä + = +V is +Ä inst itutional +ill ary +Ä p ant +VER T +Ä A CC +Ä En h +Ä inc on +Ä RE UTERS +Ä don ated +ÃĸÄĸÂĻÃĸÄĸÂĻ ÃĸÄĸÂĻÃĸÄĸÂĻ +In tern +Ä exhib it +Ä t ire +Ä R ic +Ä Ch ampion +Ä Mu hammad +N ING +Ä Soc cer +Ä mob ility +Ä vary ing +Ä M ovie +Ä l ord +o ak +F ield +Ä ve ctor +us ions +Ä sc rap +Ä en abling +m ake +T or +. * +| | +Ä We bsite +Ä N PC +Ä social ist +Ä Bill y +Ä Add itional +Ä c argo +Ä far ms +Ä So on +Ä Pri ze +Ä mid night +Ä 9 00 +se en +Ä Sp ot +Ä she ep +Ä spons ored +Ä H i +Ä J ump +Ä 19 67 +Micro soft +Ä Ag ent +Ä ch arts +d ir +Ä adj acent +Ä tr icks +Ä man ga +Ä ex agger +/ > +foot ball +Ä F CC +G C +Ä T ier +and ra +OU ND +% ), +Ä fru its +V C +Ä A A +R ober +Ä mid st +Ãĸ Äš +ank a +Ä legisl ature +Ä Ne il +Ä tour ists +" " +Ä War ning +Ä Never theless +Ä Offic ial +Ä Wh atever +Ä m old +Ä draft ed +Ä subst ances +Ä bre ed +Ä t ags +Ä T ask +Ä ver b +Ä manufact ured +com ments +Ä Pol ish +Pro v +Ä determin es +Ob ama +k ers +Ä utter ly +Ä se ct +sc he +Ä G ates +Ä Ch ap +Ä al uminum +Ä z ombie +Ä T ouch +Ä U P +Ä satisf y +Ä pred omin +asc ript +Ä elabor ate +Ä 19 68 +Ä meas uring +Ä V ari +any ahu +Ä s ir +ul ates +id ges +ick ets +Ä Sp encer +T M +oub ted +Ä pre y +Ä install ing +Ä C ab +re ed +re ated +Su pp +Ä wr ist +Ä K erry +10 7 +Ä K le +Ä R achel +Ä c otton +Ä A RE +Ä E le +Cont rol +Ä load s +Ä D od +an as +b one +Ä class ical +Ä Reg ional +Ä Int eg +V M +Ä des ires +Ä aut ism +support ed +Ä M essage +Ä comp act +writ er +Ä 10 9 +Ä Hur ricane +c ision +Ä cy cles +Ä dr ill +Ä colle ague +Ä m aker +G erman +Ä mist aken +S un +Ä G ay +Ä what soever +Ä sell s +Ä A irl +l iv +Ä O ption +Ä sol ved +Ä se ctors +Ä horizont al +Ä equ ation +Ä Sk ill +Ä B io +g ement +Ä Sn ap +Ä Leg al +Ä tradem ark +Ä make up +Ä assemb led +Ä sa ves +Ä Hallow een +Ä Ver mont +Ä FR OM +Ä far ming +Ä P odcast +accept able +Ä Hig her +Ä as leep +ull ivan +Ä refere n +Ä Le v +Ä bul lets +ok o +H C +Ä st airs +Ä main tains +Ä L ower +Ä V i +Ä mar ine +Ä ac res +Ä coordin ator +Ä J oh +Ä counterpart s +Ä Brother s +Ä ind ict +b ra +Ä ch unk +Ä c ents +H ome +Ä Mon th +Ä according ly +if les +Ä Germ ans +Ä Sy n +H ub +Ä ey eb +ÃĸÄļÄĸÃĸÄļÄĸ ÃĸÄļÄĸÃĸÄļÄĸ +Ä r anges +Ä Holl and +Ä Rob ot +f c +M ike +Ä pl asma +Ä sw ap +Ä ath lete +Ä R ams +,' " +Ä infect ions +Ä cor rid +Ä v ib +Ä pat ches +Ä tradition ally +Ä revel ation +Ä swe ep +Ä gl ance +Ä in ex +200 3 +Ä R aw +work ing +os ures +Ä D at +Ä Lyn ch +Ä le verage +Ä Re id +Ä correl ation +ian ces +av ascript +Ä rep ository +ret ty +Ä 19 72 +24 0 +Ä o un +p ol +Ä Re ed +Ä tact ical +is ite +App le +Ä Qu inn +Ä rap ed +ill o +Euro pe +Ä algorith ms +Ä Rod rig +i u +Ä ill um +Ä f ame +Ä introdu cing +Ä del ays +Ä Raid ers +Ä wh istle +Ä novel s +Ä Re ally +Ä der iv +Ä public ations +Ä Ne ither +Ä Com merce +Ä a ston +l anguage +Not es +Ä R oth +Ä F ear +Ä m ate +Ä par ade +Ä Q B +Ä man eu +Ä C incinnati +m itting +Ä wa ist +Ä R ew +Ä disc ont +Ð ° +Ä st aring +Ä al ias +Ä sec urities +Ä toile t +Ä J edi +Ä un law +v ised +//// //// +] ( +Ä We iss +Ä pre st +Ä Comp an +Ä mem o +Ä Gr ace +J uly +Ä El ite +cent er +Ä St ay +Ä gal axy +Ä to oth +Ä S ettings +Ä subject ed +ÃŖÄ¤ ÂĻ +Ä line back +Ä retail ers +Ä W ant +Ä d angers +A ir +Ä volunt ary +ew ay +Ä interpret ed +ot ine +à § +Ä p el +Serv ice +Ä Event ually +Ä care ers +Ä threat en +Ä mem or +Ä Brad ley +anc ies +s n +Ä Un known +N ational +Ä sh adows +ail and +Ä D ash +Every one +izz ard +M arch += ( +Ä pull s +Ä str anger +Ä back wards +Ä Bern ard +imens ional +Ä ch ron +Ä theoret ical +k top +Ä w are +Ä Invest ig +Ä In iti +Ä Oper ations +o ven +oc ide +* / +Ä fl ames +Ä C ash +sh it +Ä c ab +Ä An aly +Ä Se ah +Ä defin ing +Ä order ing +Ä imm un +Ä pers istent +AC H +Russ ian +m ans +Ä h ind +Ä phot ography +Â Š +Ä h ug +Ä 10 7 +Ä H ence +i ots +ude au +Ä subsid ies +Ä routine ly +Ä Dev ice +it ic +Ä disg ust +land er +Ä 19 40 +Ä assign ment +Ä B esides +w ick +Ä D ust +us c +struct ed +11 1 +de velop +Ä f ond +Ä inter section +Ä dign ity +Ä commission er +With out +re ach +Ä cart oon +Ä sc ales +ÃŖÄĨ Ń +F IG +Ä surve ys +Ä Indones ia +Ä art work +Ä un ch +Ä cy cling +un ct +au er +or ate +Ä Ob viously +Ä character ized +fe ld +Ä aff irm +Ä inn ings +Ä  Ê +Ä al iens +Ä cl oth +et ooth +Ä C ertain + § +Ä dig est +k now +Ä X L +Ä predict ions +Ä d in +W AR +Ä after math +Ex ample +Ä Su ccess +Ä Th r +IG N +Ä min er +B us +Ä cl arity +heim er +Ä O UT +Ä S end +Ä Circ le +Ä D iet +Ä pron ounced +Ä creat ors +Ä earthqu ake +atter y +ge ons +Ä o d +Ä lay ing +or p +U lt +pro ject +Ä under min +Ä sequ el +S am +Ä Dark ness +Ä re ception +b ull +Y S +Ä V ir +Ä sequ ences +Ä Co in +Ä out fit +Ä W ait +1 19 +Ä del ivers +.... .. +Ä bl own +Ä E sc +Ä M ath +per m +Ä U l +Ä gl im +Ä fac ial +Ä green house +Ä to kens +/ - +Ä Ann ual +Ä ON E +Ä teen age +Ä Phys ical +Ä L ang +Ä C elt +Ä su ed +ivid ually +Ä pat ience +ch air +reg ular +Ä a ug +in v +ex cept +Ä L il +Ä n est +f d +s um +Ä Ch ase +Russ ia +Ä Jenn ifer +Ä off season +Over all +F ore +Ä r iot +A ud +form er +Ä defend ers +Ä C T +iot ic +rib ly +Ä autom ated +Ä pen is +Ä ins ist +Ä di agram +Ä S QL +Ä G arc +Ä w itch +cl ient +ier ra +am bers +Ä rec ount +f ar +V ery +oster one +Ä appreci ated +Ä Per fect +S ection +Ä d oses +oca ust +Ä cost ly +Ä g rams +Ä Sh i +Ä wrest ling +Ä 19 71 +Ä tro phy +Ä n erve +Ä K az +Ä Exper ience +Ä pled ged +Ä play back +Ä creat ivity +by e +Ä attack ers +Ä hold ers +Ä Co ach +Ä Ph D +Ä transf ers +Ä col ored +Ä H indu +Ä d rown +Ä list ened +Ä W A +ias m +P O +Ä appeal ing +Ä discl osed +Ä Ch icken +ag ging +Ä ple aded +Ä nav igation +Ä Return s +Ä [ [ +R OR +E A +Ä photograp her +Ä R ider +ipp ers +Ä sl ice +Ä e rect +Ä he d +iss ance +Ä Vik ings +ur ious +Ä app et +oubted ly +Ch ild +Ä authent ic +o os +Ä M aking +Ä announ cing +Ä b od +Ä met er +Ä N ine +Ä R ogue +Ä work force +Ä renew ed +Ä organis ations +ac s +P LE +Sh ort +Ä comp ounds +Ä Vis it +Ä en velop +ear th +Ä support ive +gg le +Ä Brus sels +Ä Gu ild +Cre ate +RE L +Ä aver aged +Ä 19 69 +ri ages +Ä length y +Ä forg ot +O kay +Ä E rd +Ä deal er +Ä rec ession +D D +Ä desper ately +Ä hun ger +Ä st icks +Ä m ph +Ä F aith +Ä intention ally +Ä dem ol +ue ller +Ä S ale +Ä de bris +s pring +Ä le ap +>> >> +Ä contain ers +se lling +rane an +atter ing +Ä comment ed +Ä C M +on ut +Ä wood s +es pecially +Ä organ ize +iv ic +Ä Wood s +ang a +s qu +Ä m aj +am on +Ä ax is +Ä 19 74 +Ä Den mark +Ä war rior +Ä P and +Ä out lined +Ä B O +ins ula +z illa +eb ook +Ä d are +Ä sear ched +Ä nav igate +S n +writ ing +Ä un ited +J apan +Ä He brew +Ä fl ame +Ä rel ies +Ä catch ing +Ä Sh o +Ä imprison ment +Ä p ockets +Ä clos ure +Ä F am +t im +ade qu +Act ivity +Ä recru iting +Ä W ATCH +Ä Argent ina +d est +Ä apolog ize +or o +Ä lack s +Ä tun ed +Ä Griff in +Ä inf amous +Ä celebr ity +ss on +Ä  ---------------------------------------------------------------- +Ä Is is +Ä Dis play +Ä cred ibility +Ä econom ies +Ä head line +Ä Cow boys +Ä ind ef +Ä l ately +Ä incent ives +but ton +Ä M ob +A ut +Ä res igned +Ä O m +c amp +Ä prof iles +Ä sche mes +olph ins +ay ed +Cl inton +en h +Ä Y ahoo +Ä ab st +Ä an k +su its +Ä w ished +Ä Mar co +udd en +Ä sp here +Ä B ishop +Ä incorpor ated +Ä Pl ant +11 4 +Ä h ated +p ic +Ä don ate +Ä l ined +Ä be ans +Ä steal ing +Ä cost ume +Ä sher iff +Ä for ty +Ä int act +Ä adapt ed +Ä trave lling +b art +Ä nice ly +Ä dri ed +Ä sc al +os ity +NOT E +Ä B h +Ä Bron cos +Ä I gn +Ä int imate +Ä chem istry +Ä opt imal +D eb +Ä Gener ation +Ä ] , +ich i +Ä W ii +Ä YOU R +vent ions +W rite +Ä pop ul +un ning +Ä W or +V ol +Ä qu een +head s +K K +Ä analy ze +op ic +ear chers +Ä d ot +leg raph +ast ically +Ä upgr ades +Ä ca res +Ä ext ending +Ä free ze +Ä in ability +Ä org ans +Ä pret end +Ä out let +11 3 +ol an +Ä M all +ul ing +t alk +Ä express ing +Ä Al ways +Ä Be gin +f iles +Ä lic enses +% % +Ä M itt +Ä fil ters +Ä Mil waukee +G N +Ä unf old +M o +Ä nut rition +pp o +B o +Ä found ing +Ä under mine +Ä eas iest +Ä C zech +Ä M ack +Ä sexual ity +Ä N ixon +W in +Ä Ar n +Ä K in +ÃŖÄ¤ ÂŖ +ic er +Ä fort un +Ä surf aces +agh d +Ä car riers +Ä P ART +Ä T ib +Ä inter val +Ä frust rating +Ä Sh ip +Ä Ar med +ff e +Ä bo ats +Ä Ab raham +in is +Ä su ited +th read +i ov +ab ul +Ä Venezuel a +Ä to m +su per +Ä cast le +alth ough +iox ide +ec hes +Ä evolution ary +Ä negoti ate +Ä confront ed +Rem ember +Ä 17 0 +S uch +Ä 9 11 +m ult +Ä A byss +ur ry +ke es +spe c +Ä Barb ara +Ä belong ing +Ä vill ain +ist ani +Ä account able +Ä port ions +Ä De cl +U r +Ä K ate +g re +Ä mag azines +UC K +Ä regul ate +om on +Ä Al most +Ä over view +Ä sc ram +Ä l oot +Ä F itz +Ä character istic +Ä Sn ake +s ay +Ä R ico +Ä tra it +Ä Jo ined +au cus +Ä adapt ation +Ä Airl ines +Ä arch ae +Ä I de +Ä b ikes +Ä liter ary +Ä influ ences +Ä Us ed +C reat +Ä ple a +Ä Def ence +Ä Ass ass +Ä p ond +UL T +) " +Ä eval uated +Ä ob taining +Ä dem ographic +Ä vig il +ale y +Ä sp ouse +Ä Seah awks +resp ons +Ä B elt +um atic +Ä r ises +run ner +Ä Michel le +Ä pot ent +r ace +Ä P AC +F ind +olester ol +IS S +Ä Introdu ced +ress es +ign ment +O s +Ä T u +Ä De x +ic ides +Ä spark ed +Ä Laur a +Ä Bry ant +Ä sm iling +Ä Nex us +Ä defend ants +Ä Cat al +Ä dis hes +sh aped +Ä pro long +m t +( $ +ÃŖÄĸ Ĥ +Ä calcul ations +Ä S ame +Ä p iv +H H +Ä cance lled +Ä gr in +Ä territ ories +ist ically +C ome +Ä P arent +Pro ject +Ä neg lig +Ä Priv acy +Ä am mo +LE CT +olute ly +Ä Ep ic +Ä mis under +w al +Apr il +m os +path y +Ä C arson +Ä album s +Ä E asy +Ä pist ol +< < +Ä \ ( +t arget +hel p +Ä inter pre +cons cious +Ä H ousing +Ä J oint +12 7 +Ä be ers +s cience +Ä Fire fox +effect ive +Ä C abin +Ä O kay +Ä App lic +Ä space craft +Ä S R +ve t +Ä Str ange +S B +Ä cor ps +iber al +e fficient +Ä preval ence +Ä econom ists +11 8 +Th read +ord able +OD E +Ä C ant +=- =- +if iable +Ä A round +Ä po le +Ä willing ness +CL A +Ä K id +Ä comple ment +Ä sc attered +Ä in mates +Ä ble eding +e very +Ä que ue +Ä Tr ain +Ä h ij +Ä me lee +ple ted +Ä dig it +Ä g em +offic ial +Ä lif ting +Ð Âĩ +Re qu +it utes +Ä pack aging +Ä Work ers +h ran +Ä Leban on +ol esc +Ä pun ished +Ä J uan +Ä j am +Ä D ocument +Ä m apping +ic ates +Ä inev itably +Ä van illa +Ä T on +Ä wat ches +Ä le agues +Ä initi ated +deg ree +port ion +Ä rec alls +Ä ru in +Ä m elt +I AN +Ä he m +Ex p +Ä b aking +Ä Col omb +at ible +Ä rad ius +pl ug +Ä I F +et ically +Ä f ict +H ER +Ä T ap +atin um +Ä in k +Ä co h +Ä W izard +b oth +te x +Ä sp ends +Ä Current ly +Ä P it +Ä neur ons +ig nt +Ä r all +Ä bus es +b uilding +Ä adjust ments +Ä c ried +ibl ical +att ed +Ä Z ion +Ä M atter +Ä med itation +Ä D ennis +Ä our s +Ä T ab +Ä rank ings +ort al +Ä ad vers +Ä sur render +Ä G ob +ci um +om as +im eter +Ä multi player +Ä hero in +Ä optim istic +Ä indic ator +Ä Br ig +Ä gro cery +Ä applic ant +Ä Rock et +v id +Ex ception +p ent +Ä organ izing +Ä enc ounters +Ä T OD +Ä jew el +S ave +Ä Christ ie +Ä he ating +Ä l azy +Ä C P +Ä cous in +Con fig +Ä reg ener +Ä ne arest +Ä achie ving +EN S +th row +Ä Rich mond +ant le +200 2 +Ä an ten +b ird +13 3 +Ä n arc +r aint +un ny +Ä Hispan ic +ourn aments +Ä prop he +Ä Th ailand +Ä T i +Ä inject ion +Ä inher it +rav is +Ä med i +Ä who ever +Ä DE BUG +G P +Ä H ud +C ard +p rom +Ä p or +Ä over head +L aw +Ä viol ate +Ä he ated +Ä descript ions +Ä achieve ments +Ä Be er +Ä Qu ant +W as +Ä e ighth +Ä I v +Ä special ized +U PDATE +Ä D elta +P op +J ul +Ä As k +oph y +Ä news letters +Ä T ool +Ä g ard +Ä Conf eder +Ä GM T +Ä Ab bott +Ä imm unity +Ä V M +Is lam +Ä impl icit +w d +Ä 19 44 +rav ity +omet ric +Ä surv iving +ur ai +Ä Pr ison +Ä r ust +Ä Sk etch +Ä be es +Ä The ory +Ä mer it +T ex +ch at +Ä m im +Ä past e +Ä K och +Ä ignor ance +Ä Sh oot +Ä bas ement +Un ited +Ä Ad vis +he ight +Ä f oster +Ä det ain +in formation +Ä ne ural +' ; +Ä prov es +all ery +Ä inv itation +um bers +Ä c attle +Ä bicy cle +z i +Ä consult ant +Ä ap ology +Ä T iger +Ä 12 3 +99 9 +Ä ind ividually +r t +ig ion +Ä Brazil ian +Ä dist urb +Ä entreprene urs +Ä fore sts +cer pt +pl ates +p her +clip se +Ä tw itter +Ä ac ids +ograph ical +h um +Ä B ald +if ully +Ä comp iler +Ä D A +Ä don or +as i +Ä trib al +l ash +Ä Con fig +Ä applic ants +Ä sal aries +13 5 +Put in +Ä F ocus +ir s +Ä misc onduct +Ä H az +Ä eat en +M obile +Mus lim +Ä Mar cus +v iol +Ä favor able +Ä st ub +ad in +Ä H ob +Ä faith ful +Ä electron ics +Ä vac uum +w ait +back ed +econom ic +d ist +Ä ten ure +Ä since re +Ä T ogether +Ä W ave +Ä prog ression +Ä den ying +Ä dist ress +br aska +th ird +Ä mix ing +Ä colon ial +Ä priv ately +Ä un rest +atern ity +Ä prem ises +ant i +greg ation +Ä lic ence +Ä H ind +Ä Sam uel +Ä convinc ing +Ä A ce +Ä R ust +Ä Net anyahu +Ä hand les +Ä P atch +orient ed +ah o +Ä G onz +Ä hack ers +claim er +Ä custom s +Ä Gr an +f ighters +Ä l uc +Ä man uscript +aren thood +Ä dev il +Ä war riors +Ä off enders +Will iam +Ä hol idays +Ä night mare +Ä le ver +iff erent +St at +Ä exhib ition +put ed +Ä P ure +Ä al pha +Ä enthus iasm +Ä Represent atives +E AR +Ä T yp +Ä whe at +Ä Al f +Ä cor rection +Ä ev angel +AT T +M iss +Ä s oup +Ä impl ied +par am +Ä sex y +Ä L ux +Ä rep ublic +p atch +ab lish +Ä ic ons +Ä father s +Ä G ET +Ä Car ib +Ä regul ated +Ä Co hen +Ä Bob by +Ä n er +Ä b ent +vent ory +Ä Al ong +Ä E ST +Ä Wall ace +Ä murd ers +r ise +ke ll +Ä Common wealth +Ä n asty +et a +Ä M IT +Ä administ ered +Ä genuine ly +Ed itor +n ick +Ä hyd ro +**************** **************** +Ä B le +Ä fin es +Ä g orge +aus ible +r h +Ä app le +ment ioned +Ä ro pe +ot yp +H R +Ä disappoint ing +Ä c age +n ik +Ä doub ts +Ä F REE +print s +Ä M UST +Ä vend ors +Ä In qu +Ä liber als +Ä contract or +Ä up side +child ren +Ä trick y +Ä regul ators +charg ed +l iter +Ä  *** +Ä reb ell +l ang +Ä loc als +Ä phys icians +Ä he y +ar se +t m +Ä Le x +Ä behavior al +success ful +F X +Ä br ick +ov ic +Ä con form +Ä review ing +Ä ins ights +Ä bi ology +Ä Rem ove +Ä Ext ra +Ä comm itting +indu ced +ignt y +ig m +Ä at omic +Comm on +Ä E M +Ä P ere +Ä It ems +e h +Ä pres erved +Ä H ood +Ä prison er +Ä bankrupt cy +Ä g ren +us hes +Ä explo itation +Ä sign atures +Ä fin an +] ," +Ä M R +Ä me g +rem lin +Ä music ians +Ä select ing +Ä exam ining +IN K +l ated +H i +Ä art ic +Ä p ets +Ä imp air +Ä M AN +Ä table ts +in clude +R ange +Ä ca ut +Ä log s +Ä mount ing +Ä un aware +Ä dynam ics +Ä Palest ine +Ä Qu arter +Ä Pur ple +Ä m a +Ä Im port +Ä collect ions +ci ation +Ä success or +Ä cl one +Ä aim ing +Ä poss essed +Ä stick ing +Ä sh aking +Ä loc ate +Ä H ockey +T urn +17 0 +Ä fif teen +Ä Har rison +Ä continu ously +Ä T C +Ä Val ent +Ä Res cue +Ä by pass +am ount +Ä m ast +Ä protect s +Ä art istic +Ä somet ime +Ä sh oe +Ä shout ed +ific ant +et itive +Ä Reg ister +Ä J in +Ä concent rated +ling ton +on ies +Ä gener ator +yr im +Ä Ar men +Ä clear ing +id o +Ä T W +al ph +Ä lad ies +H ard +Ä dial og +Ä input s +ÃĻ Äž +Ä pos es +Ä sl ots +Ä Prem ium +Ä le aks +Ä boss es +Ä 11 3 +c ourse +A cc +Ä New ton +Ä Aust ria +Ä M age +Ä te aches +ab ad +Ä we ars +Ä c yl +Ä cur se +Ä S ales +Ä W ings +Ä p sy +Ä g aps +Ä Ice land +Ä P interest +Ä land lord +Ä defin itions +Ä K er +Ä sufficient ly +Ä P ence +Ä Arch itect +Ä sur pass +Ä 11 4 +Ä super hero +Ä Dise ase +Ä pri ests +Ä C ulture +Ä defin itive +Ä secret ly +Ä D ance +inst all +ch ief +Ä Jess ica +W ould +Up dated +Ä lock er +Ä K ay +Ä mem orial +è ÂĻ +f at +Ä dis gu +Ä flav ors +Ä Base ball +Ä Res istance +Ä k icks +Ä en v +Ä teen agers +D ark +Ä C AR +Ä h alt +Ä L G +Ä Gab riel +Ä fe ver +Ä s atur +Ä m all +Ä affili ate +Ä S leep +Ä Spe cific +Ä V el +Ä j ar +Ä Sac red +Ä Ed wards +Ä A CL +Ä ret ained +Ä G iant +Ä lim itation +in ces +Ä ref usal +Ä T ale +Ä But ler +Ä acc idents +Ä C SS +Ä import ed +Ä Cop y +Î Âą +ER T +z el +Ä div isions +h ots +Ä Al b +Ä D S +Load er +W ashington +at isf +Ä Creat ive +\ . +Ä Aut om +red ict +Ä recept or +Ä Carl os +Met hod +ok a +Ä mal icious +Ä ste pping +, [ +Ä D ad +Ä att raction +Ä Effect s +Ä Pir ate +Ä C er +Ä Indust ry +Ä R ud +Ä char ter +Ä d ining +Ä ins ists +Ä config ure +Ä ( # +Ä Sim ple +Ä Sc roll +UT C +17 5 +Ä K on +Ä market place +Ä  ÃŖÄ¤ +Ä ref res +Ä g ates +er red +Ä P od +Ä beh ave +Fr ank +n ode +Ä endors ed +he tt +as ive +Ä Hom eland +Ä r ides +Ä Le ave +er ness +Ä flood ing +A FP +Ä ris en +Ä contin ually +Ä un anim +Ä Cont ract +Ä P as +Ä gu ided +Ä Ch ile +b d +Ä su cc +pt ic +Ä comm ittees +Ä L uther +Ä Any one +Ä s ab +12 4 +Ä p ixel +Ä B ak +Ä T ag +Ä Benn ett +En ter +sm all +Ä President ial +Ä p ul +Ä contr ace +arch ive +Ä coast al +Ä K ids +19 2 +ÃĸÄĸ ² +ick y +ING TON +Ä w olf +Ä St alin +T ur +id get +am as +Ä Un less +Ä spons or +Ä mor ph +Ä Cho ose +Ä run ner +Ä un bel +Ä m ud +Ä Man a +Ä dub bed +Ä g odd +ure rs +wind ow +Ä rel ied +Ä celebr ating +os c +Ä 13 5 +Ä lobb ying +Ä incom plete +Ä restrict ion +Ä inc ap +it us +Ä expect ation +Ä Ap ollo +Ä int ens +Ä syn c +G H +Ä manip ulation +B Y +Ä spe ar +Ä bre asts +Ä vol can +il ia +M aterial +Ä form ats +Ä B ast +Ä parliament ary +Ä sn ake +Ä serv ants +Ä Tr udeau +Ä Gr im +Ä Arab ic +Ä SC P +Ä Boy s +st ation +Ä prospect ive +ord e +in itialized +Ä b ored +AB LE +Ä access ed +Ä tax i +Ä She ll +aid en +urs ed +in ates +Ä Ins urance +Ä Pet e +Sept ember +6 50 +Ä ad ventures +Ä Co ver +Ä t ribute +Ä sk etch +Ä em power +Ä  Ø +Ä Gl enn +Ä D aw += \" +Ä Polit ics +Ä gu ides +Ä d ioxide +Ä G ore +Ä Br ight +Ä S ierra +Ä val ued +c ond +Ä po inter +Se lect +Ä risk y +Ä absor b +im ages +Ä ref uses +Ä bon uses +__ _ +Ä h ilar +Ä F eatures +2 20 +Ä Collect or +F oot +Ä 19 64 +cul us +Ä d awn +Ä work out +Ä L O +Ä philosoph ical +Ä Sand y +Ä You th +Ä l iable +A f +bl ue +Ä overt urn +less ness +Ä Trib une +Ä In g +Ä fact ories +Ä cat ches +Ä pr one +Ä mat rix +Ä log in +Ä in acc +Ä ex ert +s ys +Ä need le +Ä Q ur +Ä not ified +ould er +t x +Ä remind s +Ä publisher s +Ä n ort +Ä g it +Ä fl ies +Ä Em ily +Ä flow ing +Ä Al ien +Ä Str ateg +Ä hard est +Ä mod ification +AP I +Ä M Y +Ä cr ashes +st airs +n umber +Ä ur ging +ch annel +Ä Fal con +Ä inhabit ants +Ä terr ifying +Ä util ize +Ä ban ner +Ä cig arettes +Ä sens es +Ä Hol mes +Ä pract ition +Ä Phill ips +ott o +Ä comp ile +Mod el +Ä K o +Ä [ ] +Americ ans +Ä Ter ms +Ä med ications +Ä An a +Ä fundament ally +Ä Not ice +Ä we aker +Ä  0000 +Ä gar lic +Ä out break +Ä econom ist +Ä B irth +Ä obst acles +ar cer +Ä Or thodox +Ä place bo +Ä C rew +asp berry +Ä Ang els +Ä dis charge +Ä destruct ive +11 7 +Ä R ising +Ä d airy +l ate +Ä coll ision +Ä Tig ers +ean or +ocument ed +Ä In valid +Ä d ont +Ä L iter +Ä V a +Ä hyd rogen +Ä vari ants +Ä Brown s +Ä 19 65 +Ä ind igenous +Ä trad es +Ä remain der +Ä swe pt +Ä Imp act +Ä red ist +Ä un int +grad uate +ÃŖÄĨ ġ +Ä W ILL +ÃŖÄŖÂŽ ç +Ä Crit ical +Ä f isher +Ä v icious +Ä revers ed +Y ear +Ä S ox +Ä shoot ings +Ä fil ming +Ä touchdown s +ai res +m el +Ä grand father +Ä affect ion +ing le +Ä over ly +Add itional +Ä sup reme +Ä Gr ad +Ä sport ing +Ä mer cy +Ä Brook s +ount y +Ä perform s +Ä tight ly +Ä dem ons +Ä kill ings +Ä fact ion +Ä Nov a +aut s +Ä und oubtedly +ar in +Ä under way +ra k +Ä l iv +Ä Reg ion +Ä brief ing +s ers +cl oud +Ä M ik +us p +Ä pred iction +az or +Ä port able +Ä G and +Ä present ing +Ä 10 80 + Âģ +ush i +Ä Sp ark +there um +Ä just ification +Ä N y +Ä contract ors +ming ham +Ä St yle +ÃĨ ħ +Ä Chron icles +Ä Pict ure +Ä prov ing +Ä w ives +set t +Ä mole cules +Ä Fair y +Ä consist ing +Ä p ier +al one +in ition +Ä n ucle +j son +Ä g otta +Ä mob il +Ä ver bal +ar ium +Ä mon ument +uck ed +Ä 25 6 +T ech +mine craft +Ä Tr ack +Ä t ile +Ä compat ibility +as is +Ä s add +Ä instruct ed +Ä M ueller +Ä le thal +Ä horm one +Ä or che +el se +Ä ske let +Ä entert aining +Ä minim ize +ag ain +Ä under go +Ä const raints +Ä cig arette +Ä Islam ist +Ä travel s +Ä Pant hers +l ings +C are +Ä law suits +ur as +Ä cry st +Ä low ered +Ä aer ial +Ä comb inations +Ä ha un +Ä ch a +Ä v ine +Ä quant ities +Ä link ing +b ank +Ä so y +B ill +Ä Angel a +Ä recip ient +Ä Prot est +Ä s ocket +Ä solid arity +Ä Ãĸ Ĩ +m ill +Ä var ies +Ä Pak istani +Dr agon +Ä un e +Ä hor izon +³³³³ ³³³³ +Ä prov inces +Ä frank ly +Ä enact ed +not es +[ ' +Ä 19 2 +ocr acy +Ä endorse ment +Ä over time +Tr ue +L ab +lic ted +Ä D NC +Ä be ats +Ä Jam ie +15 2 +Ä IN T +Cont act +Ä account ed +h ash +Ä Pack ers +p ires +Ä les bian +Ä amend ments +Ä hop eful +Ä Fin land +Ä spot light +Ä config ured +Ä trou bled +Ä g aze +Ä Cal gary +Ä rel iability +Ä ins urg +sw er +b uy +Ä Sk in +Ä p ixels +Ä hand gun +Ä par as +Ä categ or +Ä E L +Ä Re x +Ind eed +Ä kind a +Ä conj unction +Ä Bry an +Ä Man ufact +y ang +Pl us +S QL +ish ment +Ä dom inate +Ä n ail +Ä o ath +Ä eru pt +Ä F ine +it bart +Ä Ch ip +Ä Ab d +Ä N am +Ä buy er +Ä diss ent +Le aks +Cont in +Ä r ider +Ä Some one +Ä ill usion +c in +Ä Boe ing +Ä in adequ +ov ation +i ants +Ä reb uild +4 50 +Ä Dest iny +S W +Ä T ill +H it +ia z +Ä Bang l +acher s +Ä Re form +Ä se gments +Ä system atic +d c +Ä Conserv atives +Ä port al +h or +Ä Dragon bound +Ä drag ged +om o +Ä the e +ad vert +Ä Rep orts +Ä E t +Ä barrel s +Aug ust +Ä compar isons +Ä he x +Ä an throp +" [ +bor ough +ab i +Ä pict ured +play ing +Ä Add ress +Ä Mir ror +Sm ith +Ä t ires +Ä N PR +AA AA +Ä class ification +Ä Th an +Ä H arm +Ä R A +Ä reject ion +min ation +Ä r anged +Ä F alls +D I +H ost +ÃŖÄ¤ ´ +Ä Ex ample +list ed +th irds +Ä saf egu +br and +Ä prob able +Can ada +IT ION +Ä Q aeda +Ä ch ick +Ä import s +h it +l oc +W W +Ä ble w +Ä any time +Ä wh oles +ik ed +Ä cal culation +cre ate +Ä O ri +Ä upgr aded +Ä app ar +ut ory +Ä M ol +B rit +Ä J ong +IN AL +Ä Start ing +Ä d ice +urt le +Ä re lying +cl osure +Ä prof itable +Ä sl aughter +Ä Man ual +c aster +Ä " $ +Ä fe ather +Ä Sim ply +ie ves +Ä deter ior +Ä PC I +Ä st amp +Ä fl aws +Ä sh ade +ham mer +Ä pass port +Ä cont ing +am el +Ä obser vers +Ä neg lect +Ä R B +Ä Brother hood +Ä skept ical +f amily +us k +Ä emotion ally +Ãĸ Äģ +Ä Bet a +ason able +id ity +Ä M ul +Ä kick ing +Ä C arm +oll ah +VERT IS +Ä At hen +Ä lad der +Ä Bul let +ÃĨ ÂŖ +00 01 +Ä Wild life +Ä M ask +Ä N an +R ev +Ä un acceptable +leg al +Ä crowd ed +ag i +Ä C ox +j e +Ä mor ality +Ä fu els +Ä c ables +Ä man kind +Ä Carib bean +Ä anch or +Ä by te +Ä O ften +Ä O z +Ä craft ed +Ä histor ian +Ä W u +Ä tow ers +Ä Citiz ens +Ä hel m +Ä cred entials +Ä sing ular +Ä Jes se +Ä tack les +Ä cont empt +Ä a fore +Ä Sh adows +Ä n il +Ä ur gent +app le +bl ood +Ä v on +Ä off line +Ä breat he +Ä j umps +Ä irre levant +ox ic +om al +import ant +J im +Ä gl oves +arm ing +dep th +Ä tal ents +ook ie +Ä S B +Ä pal m +uff s +est a +IG H +Ä can on +Ä Ver izon +Ä P le +Ä cou pled +vel t +Ä fundra ising +Ä Get ting +Ä D LC +Ä mathemat ical +Ä H S +Ä Card inals +te lling +Ä spons ors +Ä  Ï +Ä Bull s +op tion +Ä prop ose +Ä mem orable +Ä embr aced +Ä decl ining +He alth +ed a +Ä } ; +Ä sp am +m ile +Ä pit cher +Ä E ight +Ä car ing +ut ic +ro le +Ä air line +ernand ez +Ä Ath let +Ä cert ification +ux e +rig er +Ä em pir +Ä sens ation +Ä dis m +Ä b olt +Ä ev olve +H ouse +Ä consult ation +Ä D uty +Ä tou ches +Ä N athan +Ä f aint +h ad +" ( +Ä Cons umer +Ä Ext reme +Ä 12 7 +Ä Her m +Ä Sac rament +iz oph +Ä anx ious +ul ously +Ä soc ially +Ä U TC +Ä sol ving +Ä Let ter +Hist ory +ed uc +Pr ice +) ); +Ä rel oad +am ic +Ä p ork +Ä disc ourse +Ä t ournaments +ai ro +Ä K ur +Ä Cost a +Ä viol ating +Ä interf ere +Ä recre ational +uff le +Ä spe eches +Ä need ing +Ä remem bers +Ä cred ited +n ia +f ocused +amer a +Ä b ru +um bs +Ä Cub an +Ä preced ing +Ä nons ense +ac ial +Ä smart phones +Ä St ories +S ports +Ä Emer gency +oun cing +ef ined +Ä b er +Ä consult ing +Ä m asters +he astern +." [ +Ä Run ning +Ä sus cept +Ä F eng +Americ a +pr ises +st itial +Ä Week ly +Ä Great er +mod ules +if ter +G raphics +ul er +Ä who lly +Ä supp ress +Ä conce aled +Ä happ ily +Ä accept s +Ä En joy +Ä r ivers +Ä Ex cept +2 25 +Ä N HS +Ä Mc Connell +Ä p ussy +fer red +ut able +Ä att ain +Ä > = +Ä depos its +roph ic +Ä not orious +Ä Sh aw +il itation +Ä epid emic +all ic +Ä small est +ov ich +Ä access ories +per ties +Ä sur plus +Ä Me ch +Ä amb ig +Ä Imm igration +Ä ch im +ev al +Ä pract icing +Ä Myster y +Ä dom ains +Ä Sil icon +app s +Ä kilomet ers +e a +Ä Sm ash +Ä warrant y +Ä n ost +s il +re v +J on +Ä Dub lin +Ä tast es +Ä b out +g reat +er ror +Ä sw itches +Ä B apt +D O +ok i +Ä sour ced +pro du +Ä attach ment +Ä Iss ue +Ä Quest ion +Jo in +Ä f itted +Ä unlaw ful +^ ^ +ere k +Ä authent ication +Ä st ole +Ä account ability +l abel +S earch +Ä al beit +atic an +fund ed +Ä Add ing +Ä I Q +Ä sub mar +l it +a que +Ä Lear ning +Ä int eger +M aster +Ä Ch rom +Ä prem ier +O p +Ä Li u +Ä bl essed +Ä Gl obe +Ä Resp onse +Ä legit im +Ä Mer kel +Ä dispos al + ´ +Ä gau ge +pe at +Ä indu ced +Ä question able +arth y +Ä V it +Ä F eed +U ntil +U t +worth y +R Y +Ä H erald +Ä Ham mer +Ä med al +Ä R ivers +Ä H ack +Ä clar ify +Ä track ed +Ä autonom ous +Ä ten ant +Ä Q atar +er ie +Ä gr im +Ä Mon itor +Ä resist ant +Ä Spe c +Ä Well s +N AS +14 8 +Ä min ers +iot ics +Ä miss es +11 6 +g ian +g it +Ä E yes +p res +Ä grad uated +Ä ang el +Ä syn chron +Ä efficient ly +Ä trans mitted +H arry +Ä glob ally +EN CE +Ä Mont ana +r aged +Ä Pre vention +Ä p iss +Ä L l +Ä she lf +Ä B JP +Ä Test ament +Ä L ate +ik er +Ä H app +Ä Jul ian +h all +Ä sp ont +Ä shut down +Ä incons istent +Ä subscrib ers +Ä ske leton +Ä Ne braska +Ä ins pire +Ä V oid +F eed +Ä ang les +Ä Spr ings +Ä bench mark +Ä vacc ines +izoph ren +se xual +uff ed +Ä sh ine +Ä K ath +Ä gest ure +ine a +Ä r ip +Ä opp ression +Ä cons cience +b t +Ä L um +Ä inc idence +Ä F a +w r +Ä min eral +Ä Sp urs +alk y +Ä th under +Ä op io +Be ing +Ä Pal m +Ä was ted +Ä l b +i aries +Ä Initi ative +Ä cur ric +Ä mark er +Ä Mc L +Ä ext ensions +Ä P v +Ä Ar ms +Ä offer ings +Ä def enses +Ä vend or +Ä contrad ict +Ä Col in +Ä redd it +Ä per ipher +12 2 +Ä s ins +E dit +IC T +So ft +Ä Sh ah +Ä administr ator +Ä T rip +Ä porn ography +Ä tu ition +in ence +Ä Pro gress +Ä cat alog +Ä su ite +Ä h ike +Ä reprodu ctive +eng ine +Ä d rought +Ä No ah +Ä 2 30 +Ä d ude +Ä relax ed +Ä part ition +Ä particip ant +Ä tel esc +Ä fe as +Ä F F +own er +Ä swe eping +Ä l enses +Ä match up +Ä Re pl +ourn als +Ä cred ible +Ä grand mother +Ä ther mal +Ä subscrib ing +Ä ident ities +col m +U CT +Ä reluct ant +us ers +Ä C ort +Ä assist ed +OS S +ATION S +IS H +Ä pharm aceutical +ic able +ad ian +Ä Son ic +Ä F ury +Ä M ong +A H +Ä Psych ology +Ä ph osph +Ä treat s +Ń Äļ +Ä stead ily +Ä Hell o +Ä rel ates +Ä cl ue +Ex pl +a uth +Ä rev ision +Ä e ld +os ion +Ä br on +14 4 +ri kes +Ä min es +Ä blank et +Ä F ail +el ed +Ä Im agine +Ä Pl anned +a ic +Re quest +M ad +Ä Hor se +Ä Eag le +Ä cap ac +15 7 +Ä l ing +Ä N ice +Ä P arenthood +min ster +og s +ens itive +Not hing +Ä car n +F in +Ä P E +Ä r ifles +Ä L P +S and +Ä gui Active +Ä tour ist +C NN +Ä unve iled +Ä predec essor +} { +u ber +Ä off shore +Ä opt ical +Ä R ot +Ä Pear l +et on +Ä st ared +Ä fart her +at ility +cont in +Ä G y +Ä F oster +Ä C oc +ri ents +Ä design ing +Ä Econom y +ON G +W omen +Ä N ancy +er ver +Ä mas cul +Ä casual ties +Ä 2 25 +Ä S ullivan +Ä Ch oice +Ä a ster +w s +Ä hot els +Ä consider ations +Ä cou ch +Ä St rip +Ä G n +Ä manip ulate +l ied +Ä synt hetic +Ä assault ed +Ä off enses +Ä Dra ke +Ä im pe +Oct ober +Ä Her itage +h l +Ä Bl air +Un like +Ä g rief +Ä 4 50 +Ä opt ed +Ä resign ation +il o +Ä ver se +Ä T omb +Ä u pt +Ä a ired +Ä H ook +Ä ML B +Ä assum es +out ed +Ä V ers +Ä infer ior +Ä bund le +Ä D NS +ograp her +Ä mult ip +Ä Soul s +Ä illust rated +Ä tact ic +Ä dress ing +Ä du o +Con f +Ä rel ent +Ä c ant +Ä scar ce +Ä cand y +Ä C F +Ä affili ated +Ä spr int +yl an +Ä Garc ia +Ä j unk +Pr int +ex ec +C rit +Ä port rait +ir ies +Ä OF F +Ä disp utes +W R +L ove +ÃŖÄŖ ÄĻ +Ä Re yn +Ä h ipp +op ath +Ä flo ors +Ä Fe el +Ä wor ries +Ä sett lements +Ä P os +Ä mos que +Ä fin als +Ä cr ushed +Ä Pro bably +Ä B ot +Ä M ans +Ä Per iod +Ä sovere ignty +Ä sell er +Ä ap ost +Ä am ateur +Ä d orm +Ä consum ing +Ä arm our +Ä Ro ose +Ä int ensive +Ä elim inating +Ä Sun ni +Ä Ale ppo +j in +Ä adv ise +p al +Ä H alo +Ä des cent +Ä simpl er +Ä bo oth +ST R +L ater +Ä C ave +== = +Ä m ol +Ä f ist +Ä shot gun +su pp +Ä rob bery +E ffect +Ä obsc ure +Ä Prof essional +Ä emb assy +Ä milit ant +Ä inc arcer +Ä gener ates +Ä laun ches +Ä administr ators +Ä sh aft +Ä circ ular +Ä fresh man +Ä W es +Ä Jo el +Ä D rew +Ä Dun can +Ä App arently +s ight +Ä Intern al +Ä Ind ividual +Ä F E +Ä b ore +Ä M t +Ä broad ly +Ä O ptions +ount ain +ip es +Ä V ideos +20 4 +Ä h ills +Ä sim ulation +Ä disappoint ment +it an +Ä Labor atory +Ä up ward +Ä bound ary +Ä dark er +h art +Ä domin ance +C ong +Ä Or acle +Ä L ords +Ä scholars hip +Ä Vin cent +ed e +Ä R ah +Ä encour ages +ro v +Ä qu o +Ä prem ise +Ä Cris is +Ä Hol ocaust +Ä rhyth m +Ä met ric +cl ub +Ä transport ed +Ä n od +Ä P ist +Ä ancest ors +Ä Fred er +th umbnails +Ä C E +ON D +Ph il +ven ge +Ä Product s +cast le +Ä qual ifying +Ä K aren +VERTIS EMENT +Ä might y +Ä explan ations +Ä fix ing +D i +Ä decl aring +Ä anonym ity +Ä ju ven +Ä N ord +Ä Do om +Ä Act ually +O k +ph is +Ä Des ert +Ä 11 6 +I K +Ä F M +Ä inc omes +V EL +ok ers +Ä pe cul +Ä light weight +g ue +Ä acc ent +Ä incre ment +Ä Ch an +Ä compl aining +Ä B aghd +Ä midfield er +Ä over haul +Pro cess +Ä H ollow +Ä Tit ans +Sm all +man uel +Ä Un ity +Ä Ev ents +S ty +Ä dispro portion +n esty +en es +Ä C od +Ä demonstr ations +Ä Crim son +Ä O H +Ä en rolled +Ä c el +Ä Bre tt +Ä a ide +Ä he els +Ä broad band +Ä mark ing +Ä w izard +Ä N J +Ä Chief s +Ä ingred ient +Ä d ug +Ä Sh ut +urch ase +end or +Ä far mer +Ä Gold man +12 9 +15 5 +Or der +Ä l ion +i ably +Ä st ain +ar ray +ilit ary +Ä FA Q +Ä expl oded +Ä McC arthy +Ä T weet +Ä G reens +ek ing +l n +ens en +Ä motor cycle +Ä partic le +Ä ch olesterol +B ron +Ä st air +Ä ox id +Ä des irable +ib les +Ä the or +for cing +Ä promot ional +ov o +b oot +Ä Bon us +raw ling +Ä short age +Ä P sy +Ä recru ited +Ä inf ants +Ä test osterone +Ä ded uct +Ä distinct ive +Ä firm ware +bu ilt +14 5 +Ä expl ored +Ä fact ions +Ä v ide +Ä tatt oo +Ä finan cially +Ä fat igue +Ä proceed ing +const itutional +Ä mis er +Ä ch airs +gg ing +ipp le +Ä d ent +Ä dis reg +ç Äļ +st ant +ll o +b ps +aken ing +Ä ab normal +Ä E RA +ÃĨÂŖ ÂĢ +Ä H BO +Ä M AR +Ä con cess +Ä serv ant +Ä as pir +l av +Ä Pan el +am o +Ä prec ip +Ä record ings +Ä proceed ed +Ä col ony +Ä T ang +ab lo +Ä stri pped +Le ft +to o +Ä pot atoes +Ä fin est +% ). +Ä c rap +Ä Z ach +ab ases +Ä G oth +Ä billion aire +w olf +Ä san ction +S K +Ä log ged +P o +ey ed +un al +Ä cr icket +Ä arm ies +Ä unc overed +Cl oud +ÃƒÂŗ n +Ä reb ounds +Ä m es +O per +P ac +Ä nation ally +Ä insert ed +p ict +Ä govern ance +Ð ¸ +Ä privile ges +G ET +Ä favor ites +im ity +Ä lo ver +the m +em pl +Ä gorge ous +An n +Ä sl ipped +Ä ve to +B ob +Ä sl im +u cc +Ä F ame +udden ly +Ä den ies +Ä M aur +Ä dist ances +Ä w anna +t ar +Ä S ER +Ä Ãĸ ÄĒ +Ä le mon +at hetic +Ä lit eral +Ä distingu ished +Ä answ ering +G I +Ä relig ions +Ä Phil os +Ä L ay +Ä comp os +ire ments +Ä K os +ine z +roll ing +Ä young est +and ise +Ä B orn +Ä alt ar +am ina +Ä B oot +v oc +Ä dig ging +Ä press ures +Ä l en +26 4 +Ä assass ination +Ä Bir mingham +Ä My th +Ä sovere ign +Ä Art ist +Ä Phot ograph +Ä dep icted +Ä disp ens +orth y +Ä amb ul +int eg +Ä C ele +Ä Tib et +Ä hier archy +Ä c u +Ä pre season +Ä Pet erson +Ä col ours +Ä worry ing +Ä back ers +Ä Pal mer +ĠÎ Âŧ +Ä contribut or +Ä hear ings +Ä ur ine +Ä  Ù +ourge ois +Sim ilar +Ä Z immer +s omething +Ä US C +Ä strength s +Ä F I +Ä log ging +As ked +Ä Th ai +in qu +Ä W alt +Ä crew s +it ism +3 01 +Ä shar ply +um ed +Ä red irect +r ators +In f +Ä We apons +Ä te asp +19 99 +L ive +Ä Es pecially +Ä S ter +Ä Veter ans +Ä int ro +other apy +Ä mal ware +Ä bre eding +Ä mole cular +Ä R oute +Ä Com ment +oc hem +Ä a in +Se ason +Ä lineback er +Ä ÂĢ +Ä Econom ics +es ar +Ä L ives +Ä Em ma +Ä k in +Ä Ter rit +Ä pl anted +ot on +Ä But ter +Ä Sp ons +P ER +Ä dun geon +Ä symb olic +Ä fil med +Ä di ets +Ä conclud es +Ä certain ty +Ä Form at +Ä str angers +form at +Ä Ph ase +Ä cop ied +Ä met res +ld a +Ä Us ers +Ä deliber ate +Ä was hed +Ä L ance +im ation +Ä impro per +Ä Gen esis +ick r +Ä K ush +Ä real ise +Ä embarrass ing +alk ing +b ucks +Ä ver ified +Ä out line +year s +Ä In come +20 2 +Ä z ombies +F inal +Ä Mill enn +Ä mod ifications +Ä V ision +Ä M oses +ver b +iter ranean +Ä J et +Ä nav al +Ä A gg +Ä ur l +Ä vict ories +Ä non etheless +Ä inj ust +Ä F act +ç Äŧ +Ä ins ufficient +re view +face book +Ä negoti ating +Ä guarant ees +im en +uten berg +Ä g ambling +Ä con gr +Load ing +Ä never theless +Ä pres idents +Ä Indust rial +Ä 11 8 +Ä p oured +Ä T ory +Ä 17 5 +Ä : = +Sc ott +ange red +T ok +Ä organ izers +M at +Ä G rowth +Ä ad ul +Ä ens ures +Ä 11 7 +ʞį ÃĨ +Ä mass acre +Ä gr ades +be fore +AD VERTISEMENT +Ä Sl ow +Ä M MA +ÃĸÄĸÄļ " +Ä V atican +Q aeda +Ä o we +66 66 +Ä S orry +Ä Gr ass +Ä background s +Ä exha usted +Ä cl an +Ä comprom ised +Ä E lf +Ä Isa ac +ens on +In vest +IF A +Ä interrupt ed +ÃŖÄĨÄĢ ÃŖÄĨŠ +Ä tw isted +Ä Drag ons +M ode +Ä K remlin +Ä fert il +he res +ph an +Ä N ode +f ed +Ä Or c +Ä unw illing +C ent +Ä prior it +Ä grad uates +Ä subject ive +Ä iss uing +Ä L t +Ä view er +Ä w oke +Th us +bro ok +Ä dep ressed +Ä br acket +Ä G or +Ä Fight ing +Ä stri ker +Rep ort +Ä Portug al +Ä ne o +w ed +19 9 +Ä flee ing +sh adow +ident ified +US E +Ste am +Ä stret ched +Ä revel ations +art ed +Ä D w +Ä align ment +est on +Ä J ared +S ep +Ä blog s +up date +g om +r isk +Ä cl ash +Ä H our +Ä run time +Ä unw anted +Ä sc am +Ä r ack +Ä en light +on est +Ä F err +Ä conv ictions +Ä p iano +Ä circ ulation +Ä W elcome +Ä back lash +Ä W ade +Ä rece ivers +ot ive +J eff +Ä network ing +Ä Pre p +Ä Expl orer +Ä lect ure +Ä upload ed +Ä Me at +B LE +Ä Naz is +Ä Sy nd +st ud +ro ots +ri ans +Ä portray ed +Ä  ?? +Ä Budd ha +s un +Rober t +Ä Com plex +Ä over see +Ä ste alth +T itle +Ä J obs +Ä K um +Ä appreci ation +Ä M OD +Ä bas ics +Ä cl ips +Ä nurs ing +Ä propos ition +Ä real ised +Ä NY C +Ä all ocated +ri um +ar an +Ä Pro duction +Ä V ote +Ä sm ugg +Ä hun ter +az er +Ä Ch anges +Ä fl uct +y on +Ar ray +Ä k its +W ater +Ä uncom mon +Ä rest ing +ell s +w ould +Ä purs ued +Ä assert ion +omet own +Ä Mos ul +Ä Pl atform +io let +Ä share holders +Ä tra ils +P ay +Ä En forcement +ty pes +Ä An onymous +Ä satisf ying +il ogy +Ä ( ' +w ave +c ity +Ste ve +Ä confront ation +Ä E ld +C apt +ah an +ht m +Ä C trl +ON S +2 30 +if a +hold ing +Ä delic ate +Ä j aw +Ä Go ing +or um +S al +Ä d ull +Ä B eth +Ä pr isons +Ä e go +Ä El sa +avor ite +Ä G ang +Ä N uclear +Ä sp ider +ats u +Ä sam pling +Ä absor bed +Ä Ph arm +iet h +Ä buck et +Ä Rec omm +O F +Ä F actory +AN CE +Ä b acter +H as +Ä Obs erv +12 1 +Ä prem iere +De velop +Ä cur rencies +C ast +Ä accompany ing +Ä Nash ville +Ä fat ty +Ä Bre nd +Ä loc ks +Ä cent ered +Ä U T +augh s +or ie +Ä Aff ordable +v ance +D L +em et +Ä thr one +Ä Blu etooth +Ä n aming +if ts +AD E +Ä correct ed +Ä prompt ly +Ä ST R +Ä gen ome +Ä cop e +Ä val ley +Ä round ed +Ä K end +al ion +p ers +Ä tour ism +Ä st ark +v l +Ä blow ing +Ä Sche dule +st d +Ä unh appy +Ä lit igation +ced es +Ä and roid +Ä integ ral +ere rs +ud ed +t ax +Ä re iter +Ä Mot ors +oci ated +Ä wond ers +Ä Ap ost +uck ing +Ä Roose velt +f ram +Ä yield s +Ä constit utes +aw k +Int erest +Ä inter im +Ä break through +Ä C her +Ä pro sec +Ä D j +Ä M T +Res p +Ä P T +Ä s perm +ed it +B T +Lin ux +count ry +le ague +Ä d ick +Ä o ct +Ä insert ing +Ä sc ra +Ä Brew ing +Ä 19 66 +Ä run ners +Ä pl un +id y +Ä D ian +Ä dys function +Ä ex clusion +Ä dis gr +Ä incorpor ate +Ä recon c +Ä nom inated +Ä Ar cher +d raw +achel or +Ä writ ings +Ä shall ow +Ä h ast +Ä B MW +Ä R S +Ä th igh +Ä 19 63 +Ä l amb +Ä fav ored +ag le +Ä cool er +Ä H ours +Ä G U +Ä Orig in +Ä glim pse +---------------- ---- +L im +Ä che ek +Ä j ealous +- ' +Ä har ness +Ä Po ison +Ä dis abilities +ne apolis +Ä out look +Ä not ify +Ä Indian apolis +Ä ab rupt +ns ic +Ä enc rypted +Ä for fe +reat h +Ä r abb +Ä found ations +Ä compl iment +Ä Inter view +Ä S we +Ä ad olesc +Ä mon itors +Ä Sacrament o +Ä time ly +Ä contem pl +Ä position ed +Ä post ers +ph ies +iov ascular +v oid +Ä Fif th +Ä investig ative +OU N +Ä integ rate +Ä IN C +ish a +ibl ings +Ä Re quest +Ä Rodrig uez +Ä sl ides +Ä D X +Ä femin ism +Ä dat as +Ä b end +ir us +Ä Nig eria +F ox +Ch ange +Ä air plane +Ä Lad en +Ä public ity +ixt y +Ä commit ments +Ä aggreg ate +Ä display ing +Ä Ar row +Ä 12 2 +Ä respect s +and roid +s ix +Ä Sh a +Ä rest oration +) \ +W S +oy s +Ä illust rate +with out +12 6 +Ä ÃĸÄļ Ĥ +Ä pick up +n els +Ä  .... +f ood +Ä F en +) ? +Ä phenomen a +Ä compan ions +Ä W rite +Ä sp ill +Ä br idges +Ä Up dated +Ä F o +Ä insect s +ASH INGTON +Ä sc are +il tr +Ä Zh ang +Ä sever ity +Ä ind ul +14 9 +Ä Co ffee +Ä norm s +Ä p ulse +Ä F T +Ä horr ific +Ä Dest roy +Ä J SON +Ä o live +Ä discuss es +R est +E lect +Ä W inn +Ä Surv iv +Ä H ait +S ure +op ed +Ä ro oted +Ä S ke +Ä Bron ze +Ä l ol +Def ault +Ä commod ity +red ited +Ä liber tarian +Ä forb idden +Ä gr an +à ¨ +Ä l ag +en z +dri ve +Ä mathemat ics +Ä w ires +Ä crit ically +Ä carb ohyd +Ä Chance llor +Ä Ed die +Ä ban ning +Ä F ri +Ä compl ications +et ric +Ä Bangl adesh +Ä band width +St op +Ä Orig inally +Ä half way +yn asty +sh ine +Ä t ales +rit ies +av ier +Ä spin ning +Ä WH O +Ä neighbour hood +b ach +Ä commer ce +Ä S le +B U +Ä entreprene ur +Ä pecul iar +Ä Com ments +f re +3 20 +IC S +Ä imag ery +Ä Can on +Ä Elect ronic +sh ort +( ( +D ig +Ä comm em +u ced +Ä incl ined +Ä Sum mon +Ä cl iff +Ä Med iterranean +Ä po etry +Ä prosper ity +Ä Re ce +Ä p ills +m ember +Ä fin ale +un c +Ä G ig +ä ÂŊ +Ä l od +Ä back ward +- + +Ä For ward +Ä th ri +s ure +Ä so ap +Ä F X +R ES +Ä Se xual +oul os +Ä fool ish +Ä right eous +Ä co ff +terror ism +ust ain +ot er +Ä ab uses +ne xt +Ä ab usive +Ä there after +Ä prohib ition +Ä S UP +Ä d ip +Ä r ipped +Ä inher ited +Ä b ats +st ru +G T +Ä flaw ed +ph abet +Ä f og +do ors +Ä im aging +Ä dig its +Ä Hung ary +Ä ar rog +Ä teach ings +Ä protocol s +Ä B anks +à ¸ +p ound +Ä C urt +." ) +. / +Ä ex emption +end ix +Ä M ull +Ä impro ves +Ä G amer +d imensional +I con +Ä Marg aret +St atus +d ates +Ä int ends +Ä dep ict +Ä park ed +J oe +Ä Mar ines +chn ology +! ). +Ä jud ged +Ä we ights +R ay +Ä apart ments +he ster +Ä rein force +Ä off ender +occ up +Ä s ore +e pt +Ä PH P +Ä B row +Ä author ization +Ä R isk +Ä Del aware +Ä Q U +Ä not ifications +Ä sun light +Ä ex clude +d at +Ä m esh +Ä Sud an +Ä belong ed +Ä sub way +Ä no on +Ä Inter ior +ol ics +Ä L akers +Ä c oding +Dis claimer +Cal if +O ld +Ä dis l +???? ? +Ä confir ms +Ä recruit ment +Ä hom icide +Cons ider +Ä Jeff rey +ft y +} ; +Ä object ion +do ing +Ä Le o +W ant +Ä gl ow +Ä Clar ke +Ä Norm an +Ä ver ification +Ä pack et +Ä Form ula +Ä pl ag +es ville +Ä shout ing +Ä o v +Ä R EC +Ä B ub +Ä n inth +Ä ener g +Ä valid ity +Ä up s +j ack +Ä neighbor ing +Ä N ec +ew orks +Ä H ab +are z +Ä sp ine +Ä event ual +Ä Le aders +Ä C arn +Ä prob ation +Ä rom ance +ms g +Ä Mechan ical +ER Y +R ock +Ä part isan +N ode +ass ets +min ent +Ä foreign ers +Ä test ify +Ä Us ually +l ords +Ä G ren +Ä Pow ell +BI L +Ä s r +Ä add ict +Ä shell s +Ä s igh +Ä Y ale +tern ity +Ä 7 50 +E U +Ä R ifle +Ä pat ron +em a +Ä B annon +an ity +Ä trop ical +Ä V II +c ross +Every thing +Ä IS O +Ä hum ble +ass ing +Ä F IG +Ä upd ating +ys on +Ä cal cium +Ä compet ent +Ä ste ering +Pro t +Ä S Y +Ä Fin als +Ä R ug +15 9 +13 7 +Ä G olf +Ä 12 6 +Ä accommod ation +Ä Hug hes +Ä aest hetic +art isan +Ä Tw ilight +Ä pr ince +Ä Agric ulture +Ä Dis co +Ä preced ent +Ä typ ing +author ized +O ption +Ä A ub +l ishes +ach t +m ag +P eter +Ä U FO +mont on +Ä L ith +Ä a rom +Ä sec uring +Ä conf ined +priv ate +Ä sw ords +Ä mark ers +Ä metab olic +se lect +Ä Cur se +Ä O t +g ressive +Ä inc umb +Ä S aga +Ä pr iced +Ä clear ance +Cont ent +Ä dr illing +Ä not ices +Ä b ourgeois +Ä v est +Ä cook ie +Ä Guard ians +ry s +in yl +Ä 12 4 +Ä pl ausible +on gh +Ä Od in +Ä concept ion +Ä Y uk +Ä Baghd ad +Ä Fl ag +Aust ral +Ä I BM +Ä intern ationally +Ä Wiki Leaks +I ED +Ä c yn +Ä cho oses +Ä P ill +Ä comb ining +Ä rad i +Ä Moh ammed +def ense +atch ing +Sub ject +ic iency +Fr ame +Ä { " +Ä che ss +Ä tim er +19 0 +Ä t in +Ä ord inance +emet ery +Ä acc using +Ä notice able +Ä cent res +Ä l id +Ä M ills +img ur +Ä z oom +erg ic +Ä comp ression +pr im +f ind +Ä sur g +Ä p and +Ä K ee +Ä Ch ad +cell ence +oy le +Ä social ism +Ä T ravis +Ä M Hz +Ä gu ild +ALL Y +Ä Sub scribe +Ä Rel ated +Ä occur rence +itch ing +Ä fict ional +Ä cr ush +Ä E A +c od +m ix +Ä Tri ple +Ä retrie ve +Ä stimul us +Ä psych iat +Ä Do or +Ä homosexual ity +Ä element ary +Ä cell ular +id ian +Ä L aun +Ä intrig uing +Ä fo am +Ä B ass +id i +its u +Ä ass ure +Ä congr at +Ä business man +Ä Bo ost +cl ose +Ä l ied +Ä sc iences +Ä O mega +Ä G raphics +Ä < = +sp oken +Ä connect ivity +S aturday +Ä Aven gers +Ä to ggle +Ä ank le +Ä national ist +mod el +Ä P ool +ophob ia +V ar +Ä M ons +ator ies +Ä aggress ively +C lear +For ge +act ers +Ä hed ge +Ä pip es +Ä bl unt +Ä s q +Ä remote ly +W ed +as ers +Ä ref riger +Ä t iles +Ä resc ued +Ä compr ised +ins ky +Ä man if +avan augh +Ä prol ifer +Ä al igned +x ml +Ä tri v +Ä coord ination +Ä P ER +Ä Qu ote +13 4 +b f +Ä S aw +Ä termin ation +Ä 19 0 +Ä add itions +Ä tri o +Ä project ions +Ä positive ly +Ä in clusive +Ä mem br +19 90 +old er +Ä pract iced +ink le +Ar ch +Ä star ters +ari us +Ä inter mediate +Ä Ben ef +Ä K iller +Ä inter ventions +Ä K il +Ä F lying +In v +Ä prem ature +Ä psych iatric +Ä ind ie +Ä coll ar +Ä Rain bow +af i +Ä dis ruption +Ä FO X +cast ing +Ä mis dem +c ro +Ä w ipe +ard on +Ä b ast +Ä Tom my +Ä Represent ative +Ä bell y +Ä P O +Ä Bre itbart +13 2 +Ä mess aging +Sh ould +Ref erences +Ä G RE +ist ical +L P +Ä C av +Ä C razy +Ä intu itive +ke eping +Ä M oss +Ä discont in +Ä Mod ule +Ä un related +Ä Pract ice +Ä Trans port +Ä statist ically +orn s +Ä s ized +p u +Ä ca f +Ä World s +Ä Rod gers +Ä L un +Ä Com ic +l iving +Ä c ared +Ä clim bed +) { +Ä consist ed +Ä med ieval +fol k +Ä h acked +Ä d ire +Ä Herm ione +Ä t ended +ce ans +D aniel +w ent +Ä legisl ators +Ä red es +g ames +Ä g n +am iliar +Ä + + +gg y +th reat +Ä mag net +Ä per ceive +Ä z ip +Ä indict ment +Ä crit ique +g ard +Ä Saf e +Ä C ream +Ä ad vent +ob a +Ä v owed +ous ands +Ä sk i +Ä abort ions +u art +Ä stun ned +Ä adv ancing +Ä lack ed +Ä \ " +Ä sch izophren +Ä eleg ant +Ä conf erences +Ä cance led +Ä Hud son +Ä Hop efully +Ä tr ump +Ä frequ encies +Ä met eor +Ä Jun ior +Ä Fle et +Ä Mal colm +Ä T ools +Ä  ........ +Ä h obby +Ä Europe ans +Ä 15 00 +Ä Int o +Ä s way +Ä App ro +Ä Com pl +Comm unity +Ä t ide +Ä Sum mit +ä Âģ +Ä inter vals +Ä E ther +Ä habit at +Ä Steven s +lish ing +Ä Dom ain +Ä trig gers +Ä ch asing +Ä char m +Ä Fl ower +it ored +Ä bless ing +Ä text ures +F ive +Ä liqu or +R P +F IN +Ä 19 62 +C AR +Un known +Ä res il +Ä L ily +Ä abund ance +Ä predict able +r ar +Ä bull shit +le en +che t +M or +M uch +ä š +Ä emphas ized +Ä cr ust +Ä prim itive +Ä enjoy able +Ä Pict ures +Ä team mate +pl er +Ä T ol +Ä K ane +Ä summon ed +th y +ram a +Ä H onda +Ä real izing +Ä quick er +Ä concent rate +cle ar +Ä 2 10 +Ä Erd ogan +ar is +Ä respond s +Ä B I +Ä elig ibility +Ä pus hes +Ä Id aho +Ä agg rav +Ä ru ins +ur ations +Ä b ans +Ä an at +sh are +Ä gr ind +h in +um en +Ä ut ilities +Ä Yan kees +Ä dat abases +Ä D D +Ä displ aced +Ä depend encies +Ä stim ulation +h un +h ouses +Ä P retty +Ä Raven s +Ä TOD AY +Ä associ ates +Ä the rape +cl ed +Ä de er +Ä rep airs +rent ice +Ä recept ors +Ä rem ed +Ä C e +Ä mar riages +Ä ball ots +Ä Sold ier +Ä hilar ious +op l +13 8 +Ä inherent ly +Ä ignor ant +Ä b ounce +Ä E aster +REL ATED +Ä Cur rency +E V +ÃŖÄĨ ŀ +Ä Le ad +Ä dece ased +B rien +Ä Mus k +J S +Ä mer ge +heart ed +c reat +m itt +m und +Ä ÃĸÄĸ Ä­ +Ä B ag +Ä project ion +Ä j ava +Ä Stand ards +Ä Leon ard +Ä coc onut +Ä Pop ulation +Ä tra ject +Ä imp ly +Ä cur iosity +Ä D B +Ä F resh +Ä P or +Ä heav ier +ne ys +gom ery +Ä des erved +Ä phr ases +Ä G C +Ä ye ast +d esc +De ath +Ä reb oot +Ä met adata +IC AL +Ä rep ay +Ä Ind ependence +Ä subur ban +ical s +Ä at op +Ä all ocation +gener ation +Ä G ram +Ä moist ure +Ä p ine +Ä Liber als +Ä a ides +Ä und erest +Ä Ber ry +Ä cere mon +3 70 +ast rous +Ä Pir ates +Ä t ense +Ä Indust ries +Ä App eals +Ä N ear +Ä Ã¨ÂŖÄą ç +Ä lo vers +Ä C AP +Ä C raw +Ä g iants +Ä effic acy +E lement +Ä Beh avior +Ä Toy ota +Ä int est +P riv +A I +Ä maneu ver +Ä perfect ion +Ä b ang +p aper +r ill +Ge orge +b order +in ters +Ä S eth +Ä cl ues +Ä Le vi +Ä Re venue +14 7 +Ä v apor +Ä fortun ate +Ä threat ens +Ä ve t +Ä depend ency +ers ed +art icle +Ä Bl izzard +Ä ch lor +Ä min us +Ä B ills +Ä cryptoc urrency +Ä metabol ism +ter ing +Ä p estic +step s +Ä Tre asure +ract ed +Ä Const ant +Ä tem p +13 9 +Ä Det ective +ur ally +Ä recover ing +Ä cort ex +Ä 14 4 +cl osed +Ä prejud ice +aun ted +Ä storm s +Ä N OW +Ä mach inery +Add ress +Ä compe lled +27 0 +Ä desp air +b ane +Ä veget able +Ä bed s +Lear n +Ä color ful +Ä sp ike +Ä marg ins +Ä symp athy +Ä works hop +Ä C BC +S at +Ä burn s +Ä G ender +Ä 12 9 +Ä C able +Ä deb ts +Ä The resa +Ä reflect ing +Ä a irst +Ä r im +ram id +Ä weakness es +W rit +ogg le +t i +Ä Ch arge +Ä we ighed +Ä ( . +Ä l aughter +Ä rou ter +Ä Democr acy +D ear +Ä has ht +Ä d y +Ä hint s +run ning +Ä fin ishes +ar us +M ass +res ult +asc us +Ä v intage +Ä con qu +Ä wild ly +ac ist +Ä l ingu +Ä prot agonist +st rom +te enth +Ä Sol o +m ac +f illed +Ä re nown +it ives +Ä mot ive +Ä Ant ar +Ä M ann +Ä Ad just +Ä rock ets +Ä trou bling +e i +Ä organ isms +ass is +Christ ian +Ä 14 5 +Ä H ass +Ä sw all +Ä w ax +Ä Surv ival +V S +Ä M urd +v d +stand ard +Ä drag ons +Ä acceler ation +r ational +f inal +Ä p aired +Ä E thereum +Ä interf aces +Ä res ent +Ä artif acts +Å ÂĢ +are l +Ä compet itor +Ä Nich olas +Ä Sur face +c pp +Ä T ot +Ä econom ically +Ä organ ised +Ä en forced +in ho +Ä var ieties +Ä ab dom +Ä Ba iley +id av +Ä Sal v +p aid +Ä alt itude +ess ert +Ä G utenberg +are a +op oulos +Ä profess ors +igg s +Ä F ate +he y +Ä 3 000 +D ist +Ä tw ins +c ill +Ä M aps +Ä tra ps +Ä we ed +Ä K iss +Ä y oga +Ä recip ients +Ä West minster +Ä pool s +Ä Wal mart +18 8 +Ä School s +att ack +Ä AR M +par agraph +W arning +j l +Ä self ish +anche z +Ä He ights +F re +Ä S oph +Ä  -------------------------------- +t ml +33 3 +Ä raid s +Ä satell ites +KE Y +Ä last s +Ñ Ĥ +In s +Ä D ame +Ä unp redict +// / +gh ai +Ä art illery +Ä cru ise +Ä g el +Ä Cabin et +Ä bl ows +Ä E sp +Ä prox imity +ot he +Ä Sk ills +Ä U pper +ob o +Ä N DP +Ä enjoy s +Ä repe ating +Ä Const ruction +Ä Quest ions +H illary +Ä u int +Ä process ors +Ä Gib son +Ä Mult iple +q a +Ä B om +Ä M iles +vent ional +Ä hur ts +s kin +Ä A IDS +Ä advis ers +Ä R oot +Ä method ology +Ä D ale +Ä det on +Ä Know ledge +sequ ently +Ä 12 1 +Ä connect s +C y +Ä D anger +Ä contribut ors +Ä B ent +Ä br ass +Ä Gun s +int o +Ä Fort une +Ä bro ker +bal ance +Ä length s +Ä v ic +Ä aver aging +Ä appropri ately +Ä Camer a +Ä sand wich +Ä CD C +Ä coord inate +Ä nav ig +Ä good ness +l aim +Ä bra ke +Ä extrem ist +Ä W ake +Ä M end +Ä T iny +Ä C OL +Ä R F +Ä D ual +Ä W ine +C ase +Ä ref ined +Ä l amp +L ead +Ä b apt +Ä Car b +Ä S add +Ä Min neapolis +PD F +Ear ly +Ä H idden +I ts +Ä T IME +Ä p ap +Ä commission ed +Ä F ew +Ä Col ts +Ä B ren +Ä bot hered +Ä like wise +Ex per +Ä Sch w +c ry +n n +Ä M itch +im on +M G +b m +UM P +r ays +Ä regist ry +Ä 2 70 +ach ine +re lla +ant ing +00 000 +Ä ru ined +sp ot +Ä t a +Ä maxim ize +Ä incon ven +D ead +H uman +En abled +Ä Mar ie +Ä ch ill +Ä Parad ise +Ä star ring +Ä Lat ino +Ä Prot ocol +Ä E VER +Ä suppl iers +m essage +Ä Bro ck +Ä ser um +ÃĸĸÄĒÃĸĸÄĒ ÃĸĸÄĒÃĸĸÄĒ +Ä en comp +Ä amb ition +ues e +Ä ar rows +And rew +Ä anten na +Ä 19 61 +Ä B ark +Ä b ool +ÃŖÄ¤ ÂĒ +Ä St orage +Ä rail way +Ä toug her +Ä C ad +Ä was hing +P y +' ] +em bed +Ä Mem phis +ack le +Ä fam ously +Ä F ortunately +ov ies +Ä mind set +Ä sne ak +Ä D h +RA W +Ä Sim pson +Ä liv est +Ä land mark +Ä c ement +L ow +Ä thr illed +Ä Cour se +in el +Ä ch uck +id ate +gl obal +Ä wh it +Ä  ïÂŋÂŊ +ad ays +s ki +Ä S V +Ä vir uses +30 6 +Ä Resp ons +Ä the aters +Ä Br anch +Ä Gene va +Ä M K +Ä unbel iev +Ä commun ist +Orig inal +Ä Re ceived +Ä Trans fer +Ä Ar g +In put +Ä Str ategy +Ä pal ace +the ning +D ri +Ä sent encing +umbn ail +Ä p ins +re cy +Ä s iblings +Get ting +Ä B U +Ä North west +Ä prolong ed +Ä Sak ura +C omb +Ä B our +Ä inadequ ate +Ä K ash +Ä us ername +Ä Impro ve +Ä batt ling +Ä M AC +Ä curric ulum +Ä s oda +Ä C annon +Ä sens ible +sp ons +De cember +Ä w icked +Ä P engu +Ä dict ators +Ä He arts +og yn +Ä similar ities +Ä St ats +Ä h ollow +it ations +": [ +Ä h over +Ä List en +s ch +S und +Ä c ad +Ä Par ks +Ä l ur +Ä hy pe +Ä L em +N AME +is ure +Fr iday +Ä shoot s +Ä clos es +Ä d b +Ä R idge +Ä Diff erent +Ä repl ies +Ä Broad way +op ers +Ä int oler +Ä Ze us +akes pe +Ä propri etary +Ä request ing +Ä contro llers +Ä M IN +im edia +be cca +Ä exp ans +Ä oil s +B ot +Ä Ch and +Ä pr inter +Ä to pped +Ä P OL +Ä Ear lier +S ocial +av in +Ä decre ases +Ä Se b +Ä specific ations +Ä Bl ast +Ä K urt +Ä fre el +B rown +Ä dil ig +ro e +Ä Pro blem +Ä Qu ad +Ä decent ral +Ä V ector +an ut +Ä plug ins +Ä Greg ory +Ä fuck ed +el ines +Ä Amb assador +t ake +Ä cle ans +ong yang +An onymous +st ro +" } +al ine +Ä O dd +Ä E ug +2 16 +Ä bo il +Ä P owers +Ä nurs es +Ob viously +Ä Techn ical +Ä exceed ed +OR S +Ä extrem ists +Ä tr aces +ex pl +Ä com r +Ä S ach +) / +Ä m asks +Ä sc i +B on +Ä reg ression +we gian +Ä advis or +it ures +Ä V o +ex ample +Ä Inst ruct +Ä s iege +Ä redu ctions +pt r +Ä stat utory +Ä rem oves +Ä p uck +red its +Ä be e +Ä sal ad +Ä promot ions +Ä Josh ua +with standing +ET H +Ä Ch a +im us +Ä expend iture +aun ting +Ä delight ed +Ä 15 5 +be h +Ä car pet +Ä Sp art +Ä j ungle +l ists +Ä bull ying +Ä Nob el +Ä Gl en +Ä referen ced +Ä introdu ces +se in +Ä cho pped +gl ass +Ä W rest +Ä neutral ity +Ä Ãĸ Äģ +Ä investig ator +Ä shel ves +Ä un constitutional +Ä reprodu ction +Ä mer chant +m ia +Ä met rics +Ä explos ives +Ä Son ia +Ä bod ily +Ä thick ness +Ä predomin antly +Ä Ab ility +Ä mon itored +IC H +Ä ] . +Ä Mart inez +Ä vis ibility +Ä qu eries +Ä gen ocide +Ä War fare +Qu ery +Ä stud ios +Ä emb ry +Ä corrid or +Ä clean ed +com plete +Ä M H +Ä enroll ment +ING S +Ä impact ed +Ä dis astrous +Ä Y un +Ä Cl aire +Ä Bas ically +y t +uster ity +Ä indirect ly +w ik +Ä d od +Ä Car r +Ä am p +Ä prohib it +Ä In itial +Ä R d +ij i +Ä educ ate +c orn +i ott +Ä Beaut y +Ä detect ive +Ä Con n +s ince +Ä st agger +Ä ob ese +Ä b ree +olog ic +is se +walk er +Ä bl ades +Ä law ful +fun c +Ä Beh ind +Ä appet ite +Ä ( * +Ä t ennis +Ä off spring +Ä j ets +Ä struct ured +Ä afore mentioned +N ov +Ä sc aling +f ill +Ä st ew +Ä cur b +Ä Step han +ed In +S F +ob ic +Ê ŃÄļ +ou g +Ä M M +Ä gen etically +ope z +13 6 +Ä u mb +anc ers +Ä coh ort +Ä merch andise +Ä imp osing +Ä Legisl ature +Ä Arch ive +iv ia +Ä N aval +Ä off ences +Ä mir acle +Ä sn apped +Ä f oes +Ä extensive ly +Ä R af +Ä c ater +ed ience +K it +Ä B in +Ä recomm ends +Ä C ities +Ä rig id +Ä RE AD +Ä Nob le +Ä T ian +Ä certific ates +ant is +o iler +Ä Budd hist +d id +Ä survey ed +Ä down ward +Ä print s +Ä Mot ion +ron ics +Ä S ans +oss ibly +u ctions +Ä colon ies +Ä Dan ish +un it +Ä sp oil +Ä advis ory +ber ries +Pl an +Ä specific ation +op hers +Ä Res ource +Ä sh irts +prising ly +commun ications +Ä triv ial +Ä mention ing +ise xual +Ä supp lements +Ä super vision +B P +v or +Ä w it +Ä co oldown +Ä plaint iff +Ä Review s +Ä S ri +Ä M int +Ä Sug ar +Ä after ward +Ä Pri est +Ä Invest ment +og ene +Ä T aking +Ä stretch ing +Ä inflamm ation +Ä Te hran +Ä l ining +Ä free zing +Ä Ent ity +Ä ins piring +spe cial +pr ice +Ä su e +Ä P orter +oun ge +ET A +Ä D erek +Ä Lu is +u o +ym ph +Ä ex terior +ih il +Ä Ash ley +in ator +Ä nut rients +Ä Th rones +Ä fin ances +Ä In spect +Ä spe cially +Ä Requ ired +Ä P TS +Ä Viol ence +oint ed +sh ots +Ä ex cerpt +co on +IN S +Ä G ri +Ä recogn ised +We ek +You ng +Ä v om +is le +Ä Cur ry +Ä Budd h +Ä not ebook +Ä d urable +/ ? +Ä G ad +Ä P upp +Ä forg ive +p ark +Ä personal ities +an alysis +cl amation +Ä elev ator +Ä ware house +Ä R ole +un n +Ä illust ration +Ä Sc an +Ä atmosp heric +Im port +AN C +rict ed +f u +01 0 +Ä ar che +Ä reward ed +akespe are +Ä intern ally +Ä R BI +alk er +Ä eleph ant +ow itz +Ä P izza +Ä bip artisan +Ê s +Ä slow ed +Ä St ark +Ä over ride +OU S +Ä 3 20 +undred s +Ä De ck +Ä C ensus +be e +14 6 +ot or +Ä  ip +Ä u b +oc ations +Ä But ton +r ice +Ä c ripp +ff f +Ä orig inated +Ä overwhel med +app a +Ä fore most +ÃĸÄĸ Äŗ +Ä L EG +re lease +eat ured +at ches +Ä re ps +Ä l ending +Ä Re ference +Ä Cl ient +16 5 +vent h +Com plete +Ä Pat rol +Ä sw orn +c am +Ä shut tle +Ä R alph +Ä h ometown +- , +on al +Ä B P +ÃĨ Äą +Ä persu ade +Ä Alex and +Ä comb ines +Ä v ivid +Ä L ag +Ä enc oding +Ä sal vation +w en +Ä Rec overy +i ya +Un iversity +Ä B iden +Ä bud gets +Ä Tex ans +f its +Ä hon ored +Ä p ython +T D +## # +cl one +Ä bl ink +Ä L iquid +Ä unemploy ed +Ä cl ashes +Ä Coun sel +Ä direct ing +Ä pun ct +Ä Fal cons +Ä sh ark +Ä Dam ascus +Ä je ans +Ä emb ark +Ä se ize +Ä up wards +2 80 +Ä E z +Ä Any thing +Ä ex otic +l ower +Ä Creat or +Ä U m +Ä subur bs +ber ger +Ä W end +Ä m int +Ä X X +Ä D ro +Ä suff ers +Ä her b +t ree +Ä frag ile +Ä flood ed +Ä Al cohol +ole an +ny der +Ä K O +F ram +Ä 13 6 +Ä ow ed +Ä Me lee +Ä H ash +Ä wh isk +Ä su do +r r +Qu ick +app ro +Ä i i +Ä Ex amples +he e +Ä promot es +per ature +k ar +Ä Hon or +Ä s odium +Ä L if +ros so +intend ent +Ä correspond ent +F ound +sec ret +Ä ident ifies +ag ne +Ä l ou +Ä P P +Ä coinc idence +m ove +Ä milit ia +Ä inf iltr +Ä Prim ary +Ä pitch ing +Ä I b +Ä GO OD +ÃŖÄ¤ ¸ +Ä W izards +ir al +Ä Ven us +R R +Ä ÃĸÄĸ ġ +Ä Case y +Ä sad ly +Ä adm ire +Ä embarrass ed +c b +M el +Ä tub es +Ä beaut ifully +Ä Queens land +Bel ow +re z +qu et +ple asant +Ġ ÂĢ +C amp +Ä dec isive +19 98 +Ä L amb +ut ton +h n +Ä J agu +au nder +Ä C ord +Ä cl erk +Ä ca ffe +Ä wip ed +Ä re im +Ä Mount ains +Ä imprison ed +Ä develop s +Ä P ra +Ä model ing +Any one +ance l +Ä S it +Ä shield s +Ä l awn +Ä card iovascular +Ä demonstr ating +Ä par se +Ä Israel is +Ä euro s +14 3 +Ä gl orious +ins ki +ec d +Ä condition ing +Ä hel pless +Ä micro sc +Ä Har bor +Ä st akes +Ä 2 60 +Ä un equ +Ä Fl oyd +Ä d amp +Ä appar atus +Ä Law s +Ä coun ters +Ä indu ce +at able +Ä Ah med +Ä sl am +N ovember +Ä pers ist +Ä im minent +ÃƒÂĄ n +Ä sh red +Ä ph ases +Ä Ed monton +Ä Arm strong +Ä Me et +Ä K itty +Ñ Äĸ +c irc +Ä Ad ult +Ä a rose +Ä X en +D an +g ow +Ä super f +Ä Ad mir +Ä end ure +Ä key word +yr us +Ä y arn +Ä path way +Ä Hop kins +mid t +Ä cens orship +d ependent +Ä instruct or +S ources +Ä to e +Ä ball oon +N ob +Ä sw ear +Ä Cast ro +Ä gl oss +Ä K avanaugh +Ä remark ably +Ph otos +Ä N om +Ä S outheast +y ers +Ä valid ation +Ä cann on +Ä Vict ory +Ä Pier re +Ä caut ious +Aud io +Ä f etch +Ä G ift +Ä H yp +Ä rem edy +Z E +Ä sc ent +Ä be ard +Ä R ut +- " +Ä pat ents +H y +Ä un just +Ä pot ato +Ä forth coming +Ä che f +Ä R ift +aff e +Ä R OM +Ä L aunch +Ä p ads +Ä Ne o +Ä on set +Ä squee ze +s afe +Ä pref ix +Ä T M +Ä N early +Ä Clin ical +Ä M ental +ot iation +Ä Un ic +ant ry +Ä C ir +Ä ep it +à ÂĻ +Ä extract ed +verse ly +ri ad +Ä str ains +Ä to ps +Ä po em +Ä Rand y +Ä Map le +TH ER +up iter +Ä SS D +Äŧ Ê +Ä un con +per ing +Ä sle pt +in ers +Ä under water +Ä Ev idence +g one +20 5 +Ä histor ians +Ä synt hesis +Ä f rog +b asketball +Ä vibr ant +Ä sub ord +Ä 3 65 +Ä D ial +Ä cooper ate +HA HA +Ä greet ed +15 8 +Ä j azz +Ä into x +Ä Walk ing +Ä super visor +Ä F usion +Ä Mer cedes +s end +H am +s d +n l +Ä tour s +Ä F IFA +Ä cul p +g d +30 4 +Ä ple as +Ä illust rates +Ä Colomb ia +Ä highlight ing +Ä Sum mary +Ä exp osing +Ä D ru +Ä ir ony +r itional +Ä Car roll +Ä Ell is +P ict +Ä R apt +Ä ad apter +Ä un m +Ä cor pse +Ä celeb rities +D en +at um +Ä Ap ocalypse +Ä W ag +lin ing +Ä horm ones +R ub +Ä X i +Ä V aults +20 8 +alky rie +inos aur +Ä feed s +v ity +Ä defe ating +W ait +Ä emphas ize +Ä Steel ers +yr inth +le ys +Ä Whe never +Current ly +Ä Cl ock +Ä collect ively +any on +Ä J P +Ä ment ality +Ä download s +Ä surround ings +Ä Barn es +Ä flags hip +Ä indic ators +Ä gra pp +Jan uary +Ä Element al +Ä Athen a +ib al +Ä s ights +Ä cap ita +Ä Treat y +Ä vo iced +Ä G az +let te +Ä y a +Ä exp ired +Leg end +H ot +n ature +Ä unst able +Ä 2 80 +à Âē +Com ment +AL E +Ä quest s +Ä hand ler +n is +Ä vers atile +Ä conce al +enge ance +Ä Inter active +Ä obs essed +Ä Dog s +Ä cr acked +S ound +s v +Ä D ylan +ro ads +f x +Ä Cath olics +Ä H ag +Ä sl ammed +Ä gl owing +s ale +Ä tiss ues +Ä Ch i +ne e +Ä c her +s ic +ur rection +Ä b acon +ul atory +) ." +Ä ir regular +FOR M +ass ed +Ä intention al +Ä compens ate +Ä Spe aking +Ä S ets +15 3 +Ä convent ions +b ands +em ade +Ä e cc +Ä Win ston +Ä Assass in +Ä Belg ian +Ä depend ence +Ä nic he +Ä b ark +Ä J azz +Ä disadvant age +Ä gas oline +Ä 16 5 +çÄŧ ÄĻ +ess a +mod ule +ang ular +O Y +Ä Treat ment +it as +ol ation +Ä Arn old +Ä fe ud +Ä N est +Ä the atre +ew ater +Ä min ors +olic y +Ä H aven +div ision +Ä tr unk +F ar +Ä P ull +Ä capt uring +Ä 18 00 +Ä Te en +Ä ex empl +Ä clin ics +Ä B urg +Ä subst it +Ä pay load +Ä L av +Ä T roy +Ä W itness +Ä frag ments +Ä pass words +Ä g ospel +Ä G in +Ä ten ants +ol ith +S ix +Pre vious +Ä Ag es +Ä Dar win +Ä bl at +Ä em pathy +sm ith +b ag +Ä E cho +Ä C amb +Ä M add +Ä B oo +Ä red e +Ä Burn ing +Ä smooth ly +Ä Ad rian +Ä V ampire +Ä Mon sters +ste am +Sty le +M a +re a +Ä D war +aly st +urs or +Ä elim ination +Ä crypt o +ch t +Ä E ternal +ÃĸÄĸÂĻ ] +Ä S orce +I ll +N ER +Ä u h +Con clusion +w age +Ä resp ir +Ä rem inis +het ical +Ä g y +Ä util ized +ic idal +Ä 19 00 +Ä hun ters +Ä Sw an +Ä Re act +Ä vis itor +Ä Thanks giving +30 8 +Post s +Ä h ips +19 97 +om ers +Ä kn ocking +Ä Veh icle +Ä t il +Ä 13 8 +Ä m i +Ä Invest igation +Ä Ken ya +Ä cas ino +Ä mot ives +Ä reg ain +re x +Ä week ends +Ä stab bed +bor o +Ä explo ited +Ä HA VE +Ä Te levision +c ock +Ä prepar ations +Ä ende av +Ä Rem ote +Ä M aker +Ä Pro du +Ä Ev an +Ä inform ational +Ä Louis ville +15 4 +Ä Dream s +Ä pl ots +Ä Run ner +Ä hur ting +Ä acad emy +Ä Mont gomery +n m +Ä L anc +Ä Al z +2 10 +el ong +Ä retail er +Ä ar ising +Ä rebell ion +Ä bl onde +play ed +Ä instrument al +C ross +Ä ret ention +Ä therape utic +Ä se as +Ä infant ry +Ä Cl int +Ä prompt ing +Ä bit ch +Ä st ems +Ä K ra +Ä the sis +Ä B og +ru ed +Ä k ings +Ä cl ay +ific ent +Ä Y ES +Ä Th ing +Ä Cub s +vey ard +els h +in arily +Ä E y +Ä Roll ing +Ä ev olving +Ind ia +Ä recogn izes +Ä grad uation +is ers +Ä fert ility +Ä Mil an +Comm and +Ä box ing +Ä 19 43 +Ä gl uten +Ä Em ir +Ä id ol +Ä con ceived +Ä Cre ation +Mer it +udd y +uss ions +Ä Lie utenant +iet al +Ä unch anged +Ä Sc ale +Ä Crime a +ball s +ator ial +Ä depth s +Ä empir ical +Ä trans m +Ä uns afe +miss ible +com fort +15 6 +Ä mechan ic +00 2 +l ins +Ä sm oked +P os +Ä slow ing +Ä l av +Tex as +Ä che ating +Ä Met ropolitan +eth yl +Ä discover ing +as se +Ä pen cil +Ä Py ongyang +Ä clos et +Ä She et +Ä Ent ry +ou stic +Ä my st +er ate +ari at +Ä miner als +Ä music ian +Ä P ul +Ä M az +24 9 +Ä per missions +Ä  iv +en ary +ick ers +Ä B ing +he a +en able +Ä gri ev +Ä assert ed +Ä Colon el +Ä aff idav +w o +Ä se ated +Ä R ide +Ä paint ings +Ä P ix +Ä 13 7 +ish i +umb ai +g otten +Ä Ear l +Ä in ning +Ä c ensus +Ä trave lled +Ä Cons ult +18 5 +b ind +Ä simpl icity +Ä overlook ed +Ä Help ful +Ä mon key +Ä overwhelming ly +Bl ood +Ä Fl int +Ä J ama +Ä Pres ent +Ä R age +Ä T A +pt ive +Ä turn out +w ald +Ä D olphins +Ä V PN +Ä on ion +Ä craft ing +m ma +Ä Merc ury +Ä arr ange +Ä alert s +Ä O T +zb ollah +Ä g ases +Ä Richards on +s al +l ar +Ä fro st +Ä lower ing +Ä acc laim +Ä start ups +Ä G ain +ess ment +Ä guard ian +äÂē Âē +Ä P ie +Ä L inks +Ä mer its +Ä aw ake +Ä parent al +Ä exceed s +Ä id le +Ä Pil ot +Ä e Bay +Ä Ac cept +ipe g +C am +Ä K ot +Ä trad ers +olit ics +unk er +Ä P ale +os i +an mar +Ä 19 47 +Ä F ell +est ial +it ating +G F +Ä S r +if ted +Ä connect or +Ä B one +ill es +2 60 +h ma +Ä overl ap +Ä Git Hub +Ä clean er +Ä Bapt ist +Ä W AS +Ä lung s +Ñ ÄŖ +Ä B UT +Ä c ite +Ä pit ched +reat ment +Ä tro phies +Ä N u +38 6 +Ä Pr ide +Ä attend ees +[ ] +17 9 +Ä spat ial +Ä pri zes +Ä Rel igion +Ä show case +Ä C ategory +vid ia +T arget +Pro perty +? , +Ä f usion +p ie +Ä U CLA +Ä sound track +Ä prin cess +Ä C aval +sh ould +Ä lim bs +Back ground +Ä lone ly +Ä c ores +Ä T ail +she et +Ä 13 2 +R a +ÃŖÄ¤ ÂĢ +Ä B olt +Ä book ed +Ä admin ister +Ä equ als +w y +Ä observ ing +Ä Bar on +Ä Ad obe +Ä v irgin +Ä Social ist +M ove +gh azi +Ä Lind a +2 12 +Ä bre wing +Ä merch ants +bur se +Ä div or +Ä met als +Ä N er +Ä sum s +Ä En emy +Ä en vision +Ä grant ing +Ä H oney +Ä Sk yrim +Ä soc io +gr aded +Ä select ive +W ASHINGTON +Ä 19 48 +Ä Sir ius +Ä G ross +act ivity +Ä I van +Ä fur ious +BS D +Ä Pre vious +Ä respons ive +Ä char itable +Ä le aning +Ä P ew +Ä viol ates +\\\\ \\\\ +Ä Com ing +w ire +Ä po et +Ä res olutions +comm and +Ä Portug uese +Ä nick name +Ä de af +Feb ruary +Ä recogn ise +Ä entire ty +Ä season al +pl aced +Ä Te legraph +Ä micro phone +our ing +Ä gr ains +Ä govern ed +Ä post p +Ä W aters +in ement +Ä und ocumented +Ä Com cast +Ä f ox +Ä assault s +re on +man y +Ä Jen kins +Ä Any way +Ä assess ments +Ä down s +Ä M ouse +Ä super b +k t +Ä D ow +Ä tax ation +4 01 +Ä sm iles +Ä undert aken +Ä ex h +Ä enthusi astic +Ä tw ent +Ä government al +Ä autonom y +Ä Techn ologies +Ä Ch ain +Ä preval ent +f b +Ä nic otine +og ram +j ob +Ä awa iting +Ä Men u +Ä dep uties +k ov +ish ops +But ton +Ä Shan ghai +Ä dies el +Ä D uck +R yan +Ä PC s +N F +j ury +ent e +Ä inacc urate +edd y +Wh atever +Ä show c +Ä N ad +od us +et r +Ä plaint iffs +Ä W OR +Ä Ass ange +Ä priv at +Ä premium s +Ä t am +UR L +Ä el ites +Ä R anger +otten ham +Ä H off +Ä At hens +Ä defin ite +Ä s ighed +Ä even ly +2 11 +Ä Am ber +ak ia +Ä mail ing +Ä cr ashing +Ä Confeder ate +ru gged +W al +Ä Dep ths +Ä juven ile +Ä react or +Introdu ction +Ä Del uxe +19 95 +Ä S anchez +Ä M ead +iv able +: - +Ä Plan ning +Ä T rap +qu in +Ä Prot ect +ve red +In formation +Ä kid ney +inn amon +l as +Ä polic ing +Ä toler ate +Ä Q i +Ä bi ased +F ort +Ä K i +s ave +Ä privile ged +Ä be asts +Ä Gl as +Ä C inem +Ä come back +Sund ay +Ä ext inction +h ops +Ä trans mit +Ä doub les +Ä Fl at +16 7 +Ä dis puted +Ä injust ice +f oo +V ict +role um +Ä Jul ie +Con text +Ä R arity +iss ue +Comp onent +Ä counsel ing +an ne +d ark +Ä object ions +u ilt +Ä g ast +Ä pl ac +Ä un used +ÃŖÄĨ ÄŠ +Ä T rial +Ä J as +hed ral +ob b +Ä tempor al +Ä PR O +Ä N W +Ä Ann iversary +L arge +Ä ther m +Ä d avid +Ä system ic +Ä Sh ir +m ut +Ä Ne pt +add ress +Ä scan ning +Ä understand able +Ä can vas +C at +Ä Z oo +Ä ang els +L O +Ä Stat ement +Ä S ig +ov able +Ä A way +sh aring +ocr ats +st ated +Ä weigh ing +N or +w ild +B ey +Ä aston ishing +Ä Reyn olds +Ä op ener +Ä train er +Ä surg ical +p n +Ä adjust ing +whe el +Ä f rown +erv ative +Ä susp end +With in +te in +Ä obst acle +Ä liber ties +ym es +Ä ur anium +ans om +an ol +ub a +Ä L oss +Ä a rous +Ä Hend erson +W ow +s pl +c ur +ĠÂ Ń +Ä their s +Dam age +Ä download ing +Ä disc ern +Ä St o +Ä Fl a +Ä h ath +Ä A j +Ä un pleasant +Europe an +exp ensive +Ä screens hot +Ä U V +Ä all ied +Ä Pers ian +Ä monop oly +Ä at om +Ä Reds kins +"> < +Ä can cell +Ä cinem a +13 1 +f air +Ä Alf red +Ä d uck +arg s +22 3 +Ä IS I +Ä sign aling +in ar +Ä laugh s +Ä for wards +Ä reck less +Ä listen ers +at ivity +Ä vast ly +n ant +L ess +Ä Hun ting +Ä Scient ific +IT ED +Ä kn ight +Ä H TC +us a +t mp +Ä r ude +Ä Legend ary +Ä ar ises +B ad +Ä Cl aim +pe g +Ä real ities +Th ink +Ġ ° +Ä ro de +Ä stri ve +Ä an ecd +Ä short s +Ä hypot hes +Ä coord inated +Ä Gand hi +Ä F PS +R ED +Ä suscept ible +Ä shr ink +Ä Ch art +Hel p +Ä  ion +de ep +rib es +Ä K ai +Ä Custom er +Sum mary +Ä c ough +w ife +Ä l end +Ä position ing +Ä lot tery +Ä C anyon +Ä f ade +Ä bron ze +Ä Kenn y +Ä bo asts +Ä Enh anced +rec ord +Ä emer gence +Ä a kin +Ä B ert +it ous +Ãĸĸ Äŗ +Ä st ip +Ä exch anged +om ore +als h +Ä reserv oir +Ä stand point +W M +Ä initi ate +Ä dec ay +Ä brew ery +Ä ter ribly +Ä mort al +lev ard +Ä rev is +N I +el o +Ä conf ess +Ä MS NBC +Ä sub missions +Cont roller +Ä 20 2 +Ä R uth +} ); +Ä Az ure +Ä  ." +20 6 +Ä Market ing +Ä l aund +ien cies +Ä renown ed +Ä T rou +Ä N GO +ble ms +Ä terr ified +Ä war ns +Ä per t +Ä uns ure +4 80 +ale z +ult z +Ä Out side +Ä st yl +Ä Under ground +Ä p anc +Ä d ictionary +Ä f oe +rim inal +Ä Nor wegian +Ä j ailed +Ä m aternal +Ê e +Ä Lu cy +c op +Ch o +Ä uns igned +Ä Ze lda +Ä Ins ider +Ä Contin ued +Ä 13 3 +Ä Nar uto +Ä Major ity +16 9 +Ä W o +ÃŖÄ¤ Äĩ +Ä past or +Ä inform al +Ð ÂŊ +an throp +jo in +ÃŖÄŖ Äš +it ational +N P +Ä Writ ing +f n +Ä B ever +19 5 +Ä y elling +Ä dr astically +Ä e ject +Ä ne ut +Ä th rive +Ä Fre qu +ou x +Ä possess es +Ä Sen ators +Ä D ES +Ä Sh akespeare +Ä Fran co +Ä L B +uch i +Ä inc arn +Ä found ers +F unction +Ä bright ness +Ä B T +Ä wh ale +Ä The ater +m ass +Ä D oll +S omething +Ä echo ed +Ä He x +c rit +af ia +Ä godd ess +Ä ele ven +Ä Pre view +Ä Aur ora +Ä 4 01 +uls ive +Ä Log an +in burgh +Ä Cent ers +Ä ON LY +Ä A id +Ä parad ox +Ä h urd +Ä L C +D ue +c ourt +Ä off ended +Ä eval uating +Ä Matthew s +Ä to mb +Ä pay roll +Ä extra ction +Ä H ands +if i +Ä super natural +Ä COM M +] = +dog s +Ä 5 12 +Ä Me eting +Rich ard +Ä Max imum +Ä ide als +Th ings +m and +Ä Reg ardless +Ä hum ili +b uffer +L ittle +Ä D ani +Ä N ak +Ä liber ation +Ä A be +Ä O L +Ä stuff ed +ac a +ind a +raph ic +Ä mos qu +Ä campaign ing +Ä occup y +S qu +r ina +Ä W el +Ä V S +Ä phys ic +Ä p uls +r int +oad ed +ET F +Ä Arch ives +Ä ven ues +h ner +Ä Tur bo +Ä l ust +Ä appeal ed +que z +il ib +Ä Tim othy +Ä o mn +d ro +Ä obs ession +Ä Sav age +19 96 +Gl obal +J es +2 14 +Ä sl iding +Ä disapp ro +Ä Mag ical +Ä volunt arily +g b +ane y +Ä prop het +Ä Re in +Ä Jul ia +Ä W orth +aur us +Ä b ounds +ie u +)) ) +Ä cro re +Ä Citiz en +S ky +Ä column ist +Ä seek ers +ond o +IS A +Ä L ength +Ä nost alg +Ä new com +Ä det rim +ent ric +3 75 +Ä G E +Ä aut op +Ä academ ics +App Data +Ä S hen +Ä id iot +Ä Trans it +Ä teasp oon +W il +K O +Ä Com edy +> , +Ä pop ulated +W D +Ä p igs +Ä O culus +Ä symp athetic +Ä mar athon +19 8 +Ä seiz ure +s ided +Ä d op +irt ual +L and +Ä Fl oor +osa urs +... ] +Ä l os +Ä subsid iary +E Y +Ä Part s +Ä St ef +Ä Jud iciary +Ä 13 4 +Ä mir rors +Ä k et +t imes +Ä neuro log +Ä c av +Ä Gu est +Ä tum or +sc ill +Ä Ll oyd +E st +Ä cle arer +Ä stere otypes +Ä d ur +not hing +Red dit +Ä negoti ated +---------------- -------- +23 5 +Ä fl own +Ä Se oul +Ä Res ident +Ä S CH +Ä disappear ance +Ä V ince +g rown +Ä grab s +r il +Ä Inf inite +Ä Tw enty +Ä pedest rian +Ä jer sey +Ä F ur +Ä Inf inity +Ä Ell iott +Ä ment or +Ä mor ally +Ä ob ey +sec ure +iff e +Ä antib iotics +ang led +Ä Fre eman +Ä Introdu ction +J un +Ä m arsh +ic ans +Ä EV ENTS +och ond +W all +icult y +Ä misdem eanor +Ä l y +Th omas +Ä Res olution +Ä anim ations +Ä D ry +Ä inter course +Ä New castle +Ä H og +Ä Equ ipment +17 7 +Ä territ orial +Ä arch ives +20 3 +Fil ter +Ä Mun ich +Ä command ed +Ä W and +Ä pit ches +Ä Cro at +Ä rat ios +Ä M its +Ä accum ulated +Ä Specific ally +Ä gentle man +acer b +Ä p enn +Ä a ka +Ä F uk +Ä interven e +Ä Ref uge +Ä Alz heimer +Ä success ion +oh an +d oes +L ord +Ä separ at +Ä correspond ence +Ä sh iny +P rior +Ä s ulf +Ä miser able +Ä ded ication +( ). +Ä special ists +Ä defect s +Ä C ult +Ä X ia +Ä je opard +Ä O re +Ab ility +Ä le ar +Ä amb itions +Ä B MI +Ä Arab s +Ä 19 42 +Ä pres ervation +ific ate +Ä ash amed +l oss +Ä Rest aur +Ä rese mble +Ä en rich +Ä K N +Ä Cl an +fl oat +Ä play able +IT T +Ä harm ony +arr ison +Ä We instein +w ere +Ä poison ing +Ä Com put +Ä Word Press +m ajor +Ä Val ve +F an +Ä Th row +Ä Rom ans +Ä Dep ression +ad os +Ä tort ured +Ä bal ancing +bott om +Ä acqu iring +Ä Mon te +ard i +Ä a ura +Ä # # +Ä Stand ing +Ä Atl as +C F +Ä intr ins +Ä Ben ghazi +Ä camp ing +Ä t apped +bl ade +st rous +Ä R abb +Ä W ritten +t ip +Ä Ne igh +ster dam +Ä All ow +Ä He aling +Ä R hod +n um +Ä caffe ine +Ä Per cent +Ä bo o +Ä app les +30 5 +Ä wel coming +Ä appl aud +Ä a usterity + ¹ +Ä Re ality +ef e +ÃĨ ÂŽ +Ä su cks +Ä tab s +Ä Pay Pal +Ä back pack +Ä gif ted +abul ary +Ä Sc out +ir teen +Ä ch in +Ä o mitted +Ä negative ly +Ä access ing +Ä E arn +Ä ambul ance +Ä head phones +Ä 20 5 +Ä Ref resh +p resident +Ä Kit chen +Ä Ent ered +Ä S nyder +00 5 +om ical +Ä borrow ed +Ä N em +Ä av iation +Ä st all +rim ination +Ä uniform s +it ime +Ä Sim mons +ener gy +ab lished +y y +qual ified +Ä rall ies +Ä St uart +fl ight +Ä gang s +r ag +Ä v ault +lu x +Ä Com par +Ä design ation +20 9 +Ä J os +d ollar +z ero +Ä well s +30 3 +Ä constitu ents +Ä he ck +Ä c ows +Ä command ers +Ä different ial +Ä C atherine +29 9 +Ä val ve +Ä br ace +Ä perspect ives +c ert +f act +icular ly +Ä Mc N +pl anes +Ä int ric +Ä pe as +ov an +Ä toss ed +ret ch +Ä L opez +Ä unf amiliar +de ath +Ä A part +Ä Ch ang +Ä relie ved +rop he +Ä air ports +Ä fre ak +ut il +M ill +Ä Ch in +Ä Ow en +m ale +Ä Bro ken +Ä Wind s +ro b +r ising +Ä fire fighters +Ä author itarian +Ä 14 8 +Bit coin +ex ternal +Ä brow sers +iche ver +or ian +Ä un b +Ä po ke +Ä Z ot +M id +Ä Pop ular +Ä co vert +Ä cont ributes +Ä 6 50 +Ä cont ention +G ate +Ä cons oles +Ä chrom os +Ä I X +Ä vis ually +Ä E isen +Ä jewel ry +Ä deleg ation +Ä acceler ate +Ä R iley +Ä sl ope +Ä ind oor +it ially +Ä huge ly +Ä tun nels +Ä fin ed +Ä direct ive +Ä fore head +ustom ed +Ä sk ate +Mus ic +g as +Ä recogn izing +am bo +Ä over weight +Ä Gr ade +Ù ÄŦ +Ä sound ing +Ä lock ing +Ä R EM +St ore +Ä exc av +Ä Like wise +Ä L ights +Ä el bow +Ä Supp ly +w ic +Ä hands ome +19 94 +C oll +Ä adequ ately +Ä Associ ate +Ä stri ps +Ä crack down +Ä mar vel +Ä K un +Ä pass ages +@@ @@ +Ä T all +Ä thought ful +names e +Ä prost itution +bus iness +Ä ball istic +person al +c ig +iz ational +R ound +ĠÂłĠÂł ĠÂłĠÂł +Ä Cole man +Ä adm itting +Ä Pl ug +Ä bit coins +Ä Su z +Ä fair ness +Ä supp lier +Ä catast rophic +Ä Hel en +o qu +M arc +Ä Art icles +g ie +Ä end angered +Ä dest iny +Ä Vol t +ol ia +ax is +Ä che at +Ä un ified +IC O +qu ote +30 2 +Ä S ed +Ä supp ression +Ä analy zing +Ä squ at +Ä fig uring +Ä coordin ates +Ä ch unks +Ä 19 46 +Ä sub p +Ä w iki +Ä For bes +Ä J upiter +Ä E rik +im er +Ä Com mercial +\ ) +Ä legitim acy +Ä d ental +Ä Me an +Ä defic its +5 50 +Orig inally +Ä Hor ror +Ä contam ination +ll ah +Ä conf isc +Ä Cl are +T B +Ä F ailed +an ed +Ä rul er +Ä Cont roller +Ä femin ists +F ix +g ay +20 7 +Ä r abbit +Th ird +ownt own +Ä gl ue +Ä vol atile +Ä sh ining +Ä f oll +Ä imp aired +Ä sup ers +ÃĻ ÄĒ +Ä cl utch +ÄŧÊ ĨĴ +Ä pro let +Ä ( ! +Ä y elled +Ä K iev +Ä Er n +Ä Sh ock +K B +Ä sit uated +qu ery +Ä N as +Ä an nex +char acter +Ä Hol iday +Ä autom ation +Ä J ill +Ä Rem astered +Ä l inem +Ä wild erness +Ä Hor izon +Ä Gu inea +A Z +Ä main land +Ä sec recy +LE ASE +Ä p unk +Ä Prov ince +( ), +Spe ed +Ä hand ing +Ä Seb ast +S ir +r ase +Ä j ournals +Ä con gest +Ä T ut +ir rel +Ä schizophren ia +Ä mis ogyn +health y +I ron +Ä react ed +- $ +25 2 +Ä pl ural +Ä pl um +Ä barg ain +Ä ground ed +f inder +Ä dis se +Ä L az +O OD +Ä at roc +F actory +Ä min ions +Ä o ri +Ä B rave +Ä P RE +Ä My anmar +Ä H od +Ä exped ition +Ä expl ode +Ä Co ord +Ä ext r +Ä B rief +Ä AD HD +Ä hard core +feed ing +Ä d ile +Ä F ruit +Ä vacc ination +Ä M ao +osp here +Ä cont ests +- | +Ä f ren +isp here +R om +Ä Sh arp +Ä Tre nd +Ä dis connect +ÃĸÄĸÂĸ ÃĸÄĸÂĸ +Ä per secution +Ear th +Ä health ier +38 4 +Ä c ob +Ä Tr inity +OW S +AN N +Ä special ty +Ä g ru +Ä cooper ative +wh y +Start ing +Ä Iss ues +st re +ens or +Ä 18 5 +Ad v +! ? +Ä Re vel +em ia +Ä H ulk +Ä celebr ations +Ä S ou +ra ud +Ä Kle in +Ä un real +con text +Ä partners hips +Ä adop ting +t ical +Ä spl ash +Ä He zbollah +c ategory +cycl op +xt on +Ä D ot +urd y +t z +Ä envelop e +Ä N L +Ãĸ ġ +Ä where in +Spe c +18 4 +Ä te lev +al iation +Ä myth s +ÃĨ ° +Ä rig orous +Ä commun icating +Ä obser ver +Ä re he +Ä W ash +Ä apolog ized +Ä T in +Ä expend itures +work ers +d ocument +Ä hes itate +Ä Len in +Ä unpredict able +Ä renew al +cl er +ok ia +Ä CON T +Ä post season +Tok ens +Ä ex acerb +Ä bet ting +Ä 14 7 +Ä elev ation +W ood +Ä Sol omon +19 4 +00 4 +out put +Ä redu nd +Ä M umbai +Ä p H +Ä reprodu ce +Ä D uration +MA X +Ä b og +C BS +Ä Bal ance +Ä S gt +Ä Rec ent +Ä c d +Ä po pped +Ä incomp et +pro p +ay an +g uy +Pac ific +Ä ty r +Ä { { +Ä My stic +Ä D ana +Ä mast urb +Ä ge ometry +à Âĸ +Ä Cor rect +Ä traject ory +Ä distract ed +Ä f oo +Ä W elsh +L uc +m ith +Ä rug by +Ä respir atory +Ä tri angle +Ä 2 15 +Ä under graduate +Ä Super ior +ch anging +_ - +Ä right ly +Ä refere e +Ä luc rative +Ä un authorized +Ä resemb les +Ä GN U +Ä Der by +Ä path ways +Ä L ed +Ä end urance +Ä st int +Ä collect or +F ast +Ä d ots +Ä national s +Ä Sec urities +Ä wh ip +Par am +Ä learn s +M agic +Ä detail ing +m oon +Ä broadcast ing +Ä b aked +26 5 +hol m +Ä S ah +Ä Hus sein +Ä Court esy +17 4 +Ä 14 6 +Ä ge ographic +pe ace +Ä jud ging +Ä S tern +B ur +Ä story line +G un +Ä St ick +24 5 +30 7 +ÃŖÄ¤Â´ ÃŖÄĨÂŗ +Ä Administ rator +Ä bur nt +Ä p ave +ch oes +Ex ec +Ä camp uses +Res ult +Ä mut ations +Ä Ch arter +Ä capt ures +Ä comp ares +Ä bad ge +S cient +Ä er ad +ier y +o i +ett es +Ä E state +Ä st rap +Ä proud ly +Ä f ried +Ä withd rawn +Ä V oy +ph ony +It ems +Ä P ierce +b ard +Ä ann otation +ant on +ill on +Im pro +... ) +Ä happ ier +---- -- +ad just +Ä staff ers +Ä activ ism +Ä per f +Ä al right +N eed +Ä comm ence +Ä opio id +Ä Am anda +E s +Ä P ars +Ä K aw +W orks +24 8 +Ä ind o +t c +end ant +Ä M oto +Ä legal ization +OT E +Ä task ed +Ä t sp +Ä ACT IONS +16 6 +Ä refres hing +Ä N R +Ä Pere z +Ä infring ement +S Y +List en +in ning +k u +Ä rot ate +pro gram +ar ah +Des ign +Ä ( Ã‚ÂŖ +Ä st oring +Ä war rants +Ä jud gement +Ä B rist +us ually +ph oto +Ä R an +Ä P ine +Ä outrage ous +Ä Valent ine +lu ence +Ä Every body +Al tern +Ä rele vance +Ä termin ated +Ä d essert +Ä fulf illed +Ä prosecut ed +Ä W ords +Ä m igrant +Ä cultiv ation +ÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤ ÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤ +idel ity +Ä V ern +Ä Log in +Ä metaph or +Ä T ip +Ä recru its +Ä P ig +rib ing +Ä enthusi asts +ex per +Ä fright ening +Ä H air +ans on +str ate +Ä h i +He ight +Ä own ing +n one +Ä dis like +Ä kn ives +pher d +Ä loud ly +Ä AP Is +Dis play +Ä L ac +Ä US S +ab l +ver ages +J ew +Ä 17 2 +Ä Hist orical +at oon +Ä Phys ics +in tern +Ä warm th +Ä to pp +D M +Ä gun man +Ä em peror +od i +ÃŖÄĨ ÂŖ +in atory +Ä R ib +Ä 13 1 +Ä Sat urn +Ä Sh ining +Ä w aking +Qu otes +Ä comed ian +en berg + ÂŊ +Ä belie vers +Ä paper work +c ustom +Ä le v +Ä l ament +Ä pour ing +22 2 +p olitical +Ä Supp lement +m aid +Ä cruel ty +Ä t read +ys ics +A w +rit es +Ä mod ifier +Ä P osition +Ad am +l b +ub s +Ä imper fect +Ä cl usters +Ä Engine er +Ä C herry +Ä inaug uration +Ä S au +Ä embod iment +Ä Un cle +Ä over r +Ä explos ions +c ule +Ä Princ eton +Ä Andre a +Ä incorrect ly +Ä earn est +Ä pil gr +Ä S print +Ä slee ve +Ä he ars +Ä Am azing +Ä brow sing +ag in +Ä hom eland +Ä ha w +Ä d iving +ist ered +17 8 +Ä barg aining +Ä Arc ade +Ä deleg ate +ters on +................................ ................................ +Ä Jackson ville +27 5 +Ä st agn +Ä ad am +Ä Sher man +C B +Ä sub urb +Ä Food s +Ä conver ting +Ä Ar ist +Ä ch ambers +l ove +Ä am ino +Ä G an +Ä mad ness +m c +Ä US E +def ined +Ä ul tr +ind ust +Ä w olves +l ance +Add itionally +Ä cr acks +as ia +Ä Re ason +Ä P ump +Ä accident al +Ä L aser +Ä R id +Ä initial ized +ell i +Ä un named +Ä n oun +Ä Pass ed +Ä host age +Ä Eth iop +sh irts +Ä un rel +Ä Emb assy +Ä 19 41 +Ä at oms +Ä pur ported +16 4 +Ä F i +Ä gall ons +Ä Mon ica +Ä p g +en ment +Ä sort ed +Ä G ospel +Ä he ights +Ä tr aced +Ä under going +She ll +Ä s acks +Ä proport ions +Ä hall uc +F ont +ac et +Ä war mer +Ä IN TER +Ä grab bing +Pl ug +Ä real ization +Ä Bur ke +Ä en chant +AT ER +Ä Se ed +Ä abund ant +F M +Ä c ivic +V s +is i +Ä v ow +Ä re per +Ä Partners hip +Ä penet ration +Ä ax e +Ä sh attered +Ä Z ombies +Ä v inyl +Ä Al ert +e on +Ä oblig ed +Ä Ill ust +Ä Pl aza +Ä Front ier +Ä david jl +Ä Ser ial +Ä H av +Ä Nut rition +B i +Ä Ãĸĸ ÄĒ +Ä J ays +lin ux +Ä hur ry +Ä v oy +Ä hop eless +Ä Ste alth +Ä  ÃŖÄŖ +ess ors +tt le +b org +Ä Saf ari +f ell +Ä w ary +d ue +Ä Ab ove +H a +E LL +Ä not or +Ä W on +T oo +Ä occup ations +Ä poss essions +Ä inv iting +Ä pred ators +Ä acceler ated +Ä 15 7 +uter te +Ä C ube +e ast +acc ount +G ive +Ä trans plant +red ients +id able +Ä screens hots +Ä G und +Ä F S +Ä travel ers +Ä sens ory +Ä F iat +Ä Rock ets +İ Ä­ +_ { +F riend +Ä char ming +AL S +Ä enjoy ment +m ph +Ä 5 000 +Ä RE G +Ù Ĩ +b ia +Ä comp ilation +ro st +Ä V P +Ä Sch ne +201 9 +Ä cop ying +M ORE +Ä Fl ore +f alls +2 15 +t otal +Ä dis ciples +d ouble +Ä exceed ing +Ä sm ashed +Ä concept ual +Ä Rom ania +Ä B rent +Ä I CE +Ä T ou +Ä g rap +Ä n ails +18 9 +ÃŖÄĨ Äē +Ä proc ure +e ur +Ä confir ming +Ä C ec +aw i +Ä Ed en +Ä n g +Ä engine ered +at ics +Ä hook ed +Ä disgust ing +Ä Mur der +ÃŖÄ¤ Âŋ +L ibrary +Ä 16 8 +Al most +hem atic +Men u +Ä Not re +Ä J ur +Ä kidn apped +Ä hack er +Ä J ade +Ä creep y +Ä draw ings +Ä Spons or +Ä cycl ists +Ä Gob lin +Ä optim ized +Ä st aged +Ä Mc D +bet ween +A ge +en o +S ex +Ä W ide +n ings +av is +Ä incap able +Ä K ob +Ä reward ing +Ä L one +oles cent +Ä contract ed +Ä stick y +J ose +B all +f est +Ä In put +Ä Rec ently +Ä to mat +squ are +App lication +Ä nit rogen +Ä dupl icate +Ä Rec on +Ä D ear +L ondon +Ä int ra +Ä d ock +Ä out reach +Ä M illion +Ä mamm als +am pton +V AL +Ä sn aps +Ä d os +Ä Wh ole +Ä Read y +T ry +Ä Winn ipeg +ear ance +Ä inc urred +ren ched +Ä NS W +il ot +rain e +Ä c ube +g ot +Ä run way +etermin ed +Ä Haw ks +Ä surviv or +Ä W ish +Ä D in +Ä DE F +Ä V ault +18 7 +Ä mush rooms +Ä cris p +be y +Ä Disco very +Ä development al +Ä parad igm +Ä cha otic +Ä T su +Ä 3 33 +b ons +Ä bacter ial +Ä comm its +Ä cos mic +Ä me ga +oc ative +Ä P aint +ophob ic +Ä v ain +Ä car ved +Ä Th ief +Ä G ul +ows hip +Ä c ites +Ä Ed inburgh +Ä dimin ished +Ä acknowled ges +Ä K ills +Ä mic row +Ä Her a +Ä sen iors +Ä where by +H op +at ron +Ä un available +Ä N ate +Ä 4 80 +Ä sl ated +Ä Re becca +Ä B attery +Ä gram mar +Ä head set +Ä curs or +Ä ex cluding +any e +aunder ing +eb in +Ä feas ible +Ä Pub lishing +Ä Lab s +Ä Cl iff +Ä Ferr ari +Ä p ac +vis ible +mark ed +pe ll +Ä pol ite +Ä stagger ing +Ä Gal actic +Ä super st +Ä par an +Ä Offic ers +ÃŖÄĸ ÄŖ +Ä specific s +ul us +23 9 +Ä P aste +AM P +Ä Pan ama +Ä De lete +angu ard +rest rial +Ä hero ic +Ä D y +ا ÙÄĻ +Ä incumb ent +Ä cr unch +t ro +Ä sc oop +Ä blog ger +Ä sell ers +ure n +Ä medic ines +Ä C aps +Ä Anim ation +ox y +Ä out ward +Ä inqu iries +22 9 +Ä psych ologist +Ä S ask +ev il +Ä contam inated +ÃŖÄ¤ ¨ +he rence +Ä brand ed +Ä Abd ul +z h +Ä paragraph s +Ä min s +Ä cor related +er b +Ä imp art +Ä mil estone +Ä Sol utions +ot le +Ä under cover +Ä mar ched +Ä Charg ers +f ax +Ä Sec rets +Ä r uth +we ather +Ä femin ine +Ä sh am +Ä prest igious +igg ins +Ä s ung +hist ory +ett le +gg ie +Ä out dated +ol and +Ä per ceptions +Ä S ession +Ä Dod gers +u j +Ä E ND +D oc +Ä defic iency +Gr and +Ä J oker +Ä retro spect +Ä diagn ostic +Ä harm less +Ä ro gue +Ä A val +E qu +Ä trans c +Ä Roberts on +Ä Dep ending +Ä Burn s +iv o +Ä host ility +F eatures +Äĩ Äē +Ä dis comfort +Ä L CD +spec ified +Ä Ex pect +3 40 +Ä imper ative +Ä Reg ular +Ch inese +Ä state wide +Ä sy mm +Ä lo ops +Ä aut umn +N ick +Ä sh aping +Ä qu ot +Ä c herry +Ä Cross ref +èÂĻ ÄŧÊĨĴ +Stand ard +he ed +Ä D ell +Ä Viet namese +Ä o st +Ä V alkyrie +O A +Ass ad +Ä reb ound +Ä Tra ffic +pl aces +ÃĻ Äē +Ä B uc +17 2 +Ä shel ters +Ä ins isting +Ä Certain ly +Ä Kenn eth +Ä T CP +Ä pen al +Ä Re play +he ard +Ä dial ect +iz a +Ä F Y +it cher +Ä D L +Ä spir al +Ä quarterback s +Ä h ull +Ä go ogle +Ä to dd +Ä Ster ling +Ä Pl ate +Ä sp ying +mb ol +Ä Real m +Ä Pro ced +Ä Cr ash +Ä termin ate +Ä protest ing +C enter +gu ided +Ä un cover +Ä boy cott +Ä real izes +s ound +Ä pret ending +Ä V as +19 80 +Ä fram ed +Ä 13 9 +Ä desc ended +Ä rehab ilitation +Ä borrow ing +Ä B uch +Ä bl ur +R on +Ä Fro zen +en za +Ch ief +Ä P oor +Ä transl ates +M IN +Ä 2 12 +J ECT +Ä erupt ed +Ä success es +S EC +Ä pl ague +Ä g ems +d oms +Ä stret ches +Ä Sp y +Ä story telling +C redit +Ä P ush +Ä tra ction +Ä in effective +Ä L una +Ä t apes +Ä analy tics +erc ise +Ä program mes +Ä Car bon +Ä beh old +he avy +Ä Conserv ation +Ä F IR +Ä s ack +ter min +ric ks +Ä hous ed +Ä unus ually +I ce +Ä execut ing +Ä Mor oc +ed ay +Ä ed itions +Ä sm arter +Ä B A +Ä out law +Ä van ished +ib a +AL SE +Ä Sil va +23 8 +C ould +Ä philos opher +Ä evac uated +Sec ret +14 2 +Ä vis as +ÃŖÄ¤ ÂŦ +Ä M alt +Ä Clear ly +Ä N iger +Ä C airo +Ä F ist +3 80 +Ä X ML +aut o +it ant +Ä rein forced +Rec ord +Ä Surviv or +G Hz +Ä screw s +parent s +Ä o ceans +ma res +Ä bra kes +vas ive +Ä hell o +Ä S IM +rim p +Ä o re +Ä Arm our +24 7 +Ä terr ific +Ä t ones +14 1 +Ä Min utes +Ep isode +Ä cur ves +Ä inflamm atory +Ä bat ting +Ä Beaut iful +L ay +Ä unp op +v able +Ä r iots +Ä Tact ics +b augh +Ä C ock +Ä org asm +Ä S as +Ä construct or +et z +G ov +Ä ant agon +Ä the at +Ä de eds +ha o +c uts +Ä Mc Cl +Ä u m +Ä Scient ists +Ä grass roots +ys sey +"] => +Ä surf aced +Ä sh ades +Ä neighb ours +Ä ad vertis +oy a +Ä mer ged +Up on +Ä g ad +Ä anticip ate +Any way +Ä sl ogan +Ä dis respect +I ran +Ä T B +act ed +Ä subp oen +medi ately +OO OO +Ä wa iver +Ä vulner abilities +ott esville +Ä Huff ington +J osh +Ä D H +M onday +Ä Ell en +K now +x on +it ems +22 8 +Ä f ills +Ä N ike +Ä cum ulative +and als +I r +Ä  ÃŦ +Ä fr iction +ig ator +Ä sc ans +Ä Vi enna +ld om +Ä perform ers +P rim +Ä b idding +M ur +Ä lean ed +Ä Pri x +al ks +Ä [ ÃĸÄĸÂĻ] +Ä Tw itch +Ä Develop er +Ä G ir +Ä call back +Ab stract +Ä acc ustomed +Ä freed oms +Ä P G +ur acy +Ä l ump +is man +,, ,, +19 92 +Ä R ED +Ä wor m +M atch +Ä Pl atinum +I J +Ä Own er +Tri via +com pl +Ä new born +Ä fant as +O wn +Ä 19 59 +Ä symp ath +Ä ub iqu +Ä output s +Ä al lev +Ä pr ag +K evin +Ä fav ors +Ä bur ial +Ä n urt +so lete +c ache +Ä 15 6 +Ä unl ocks +te chn +M aking +Ä con quer +ad ic +ÃĻ Ä¸ +Ä el f +Ä elect orate +Ä Kurd s +Ä St ack +Ä Sam urai +Ä Ãĸ Äēħ +Ä { } +Ä S aid +Ä Fall out +Ä kind ness +Ä Custom s +Ä Bou levard +Ä helicop ters +ot ics +Ä Ve get +com ment +Ä critic ised +Ä pol ished +Ä Rem ix +Ä C ultural +Ä rec ons +Ä do i +at em +Sc reen +Ä bar red +Com ments +Ä Gener ally +Ä sl ap +7 20 +V ari +p ine +Ä em pt +Ä h ats +Ä Play ing +l ab +a verage +form s +Ä C otton +Ä can s +Ä D ON +Ä Som alia +C rypt +Ä Incre ases +E ver +mod ern +Ä sur geon +3 000 +Ä random ized +================================ ================================ +B ern +im pl +Ä C OR +Ä pro claim +th ouse +Ä to es +Ä am ple +Ä pres erving +Ä dis bel +gr and +B esides +Ä sil k +Ä Pat tern +h m +Ä enter prises +Ä affidav it +Ä Advis ory +Ä advert ised +Ä Rel igious +se ctions +psy ch +Ä Field s +aw ays +Ä hasht ag +Ä Night mare +Ä v ampire +Ä fore nsic +rosso ver +n ar +Ä n avy +Ä vac ant +Ä D uel +Ä hall way +Ä face book +ident ally +Ä N RA +Ä m att +Ä hur ricane +Ä Kir by +Ä P uzzle +Ä sk irt +ou st +du llah +Ä anal ogy +in ion +Ä tomat oes +Ä N V +Ä Pe ak +Ä Me yer +Ä appoint ments +Ä m asc +Ä al ley +re hend +Ä char ities +Ä und o +Ä dest inations +Ä Test ing +"> " +c ats +* . +Ä gest ures +gener al +Le ague +Ä pack ets +Ä Inspect or +Ä Ber g +Ä fraud ulent +Ä critic ize +F un +Ä bl aming +nd ra +Ä sl ash +Ä E ston +Ä propos ing +Ä wh ales +Ä therap ist +Ä sub set +Ä le isure +EL D +Ä C VE +Ä Act ivity +Ä cul min +sh op +Ä D AY +is cher +Ä Admir al +Ä Att acks +Ä 19 58 +Ä mem oir +Ä fold ed +Ä sex ist +Ä 15 3 +Ä L I +Ä read ings +Ä embarrass ment +Ä Employ ment +w art +ch in +Ä contin uation +l ia +Rec ently +Ä d uel +Ä evac uation +Ä Kash mir +Ä dis position +Ä R ig +Ä bol ts +Ä ins urers +4 67 +M ex +Ä ret aliation +Ä mis ery +Ä unre asonable +r aining +I mm +Ä P U +em er +Ä gen ital +ÃŖÄ¤ Âŗ +Ä C andy +Ä on ions +Ä P att +lin er +Ä conced ed +Ä f a +Ä for c +Ä H ernandez +Ä Ge off +deb ian +Ä Te ams +Ä c ries +Ä home owners +23 7 +A BC +Ä st itch +Ä stat istic +Ä head ers +Ä Bi ology +Ä mot ors +Ä G EN +Ä L ip +Ä h ates +Ä he el +S elf +i pl +ED IT +ort ing +Ä ann ot +Ä Spe ech +old emort +Ä J avascript +Ä Le Bron +Ä foot print +Ä f n +Ä seiz ures +n as +h ide +Ä 19 54 +Ä Be e +Ä Decl aration +Ä Kat ie +Ä reserv ations +N R +f emale +Ä satur ated +Ä b iblical +Ä troll s +Dev ice +ph otos +Ä dr ums +ÃŖÄĨÄĢÃŖÄĨŠ ÃŖÄ¤Â´ÃŖÄĨÂŗ +N ight +f ighter +Ä H ak +ri ber +Ä c ush +Ä discipl inary +ba um +Ä G H +Ä Sch midt +ilib rium +Ä s ixty +Ä Kush ner +ro ts +Ä p und +Ä R ac +Ä spr ings +Ä con ve +Bus iness +F all +Ä qual ifications +Ä vers es +Ä narc iss +Ä K oh +Ä W ow +Ä Charl ottesville +ed o +Ä interrog ation +Ä W ool +36 5 +B rian +Ä ÃĸÄž Äĩ +Ä alleg es +ond s +id ation +Ä Jack ie +y u +Ä l akes +Ä worth while +Ä cryst als +Ä Jud a +Ä comp rehend +Ä fl ush +Ä absor ption +Ä O C +Ä fright ened +Ä Ch ocolate +Mart in +Ä bu ys +Ä bu cks +Ä app ell +Ä Champions hips +Ä list ener +Ä Def ensive +Ä c z +ud s +Ä M ate +Ä re play +Ä decor ated +Ä s unk +Ä V IP +Ä An k +Ä 19 5 +aa aa +Nob ody +Ä Mil k +Ä G ur +Ä M k +Ä S ara +Ä se ating +Ä W id +Tr ack +Ä employ s +Ä gig antic +AP P +ÃŖÄ¤ § +in ventory +Ä tow el +at che +l asting +Ä T L +Ä lat ency +Ä kn e +B er +me aning +Ä up held +Ä play ground +Ä m ant +S ide +Ä stere o +Ä north west +Ä exception ally +Ä r ays +Ä rec urring +D rive +Ä up right +Ä ab duct +Ä Mar athon +Ä good bye +Ä al phabet +h p +Ä court room +ring ton +ot hing +T ag +Ä diplom ats +Ä bar bar +Ä Aqu a +18 3 +33 33 +Ä mat urity +Ä inst ability +Ä Ap ache +Ä = == +Ä fast ing +Ä Gr id +Mod Loader +Ä 15 2 +A bs +Ä Oper ating +ett i +Ä acqu aint +Don nell +Ä K em +Ä For ge +Ä arm ored +M il +Ä philos ophers +in vest +Pl ayers +Ãĸ ÄĒ +Ä my riad +Ä comr ades +R ot +Ä remember ing +Ä correspond s +Ä program mers +Ä Lyn n +Ä o lig +Ä co herent +yn chron +Ä Chem ical +Ä j ugg +p air +post s +E ye +Ä In ner +Ä sem ester +ott est +Ä Emir ates +ric anes +or ously +m its +Ä W is +Ä d odge +l ocation +Ä f aded +Am azon +Ä Pro ceed +Ä IN FO +j ournal +Ä Tru ck +T en +Ä 2 17 +Ä stat utes +m obile +Ä T ypes +Rec omm +b uster +pe x +Ä leg ends +Ä head ache +f aced +Ä Wi Fi +if ty +Ä H ER +Ä circ uits +ER ROR +22 6 +ol in +Ä cyl inder +osp ace +ik ers +P rem +Qu ant +Ä conflic ting +Ä slight est +Ä for ged +ion age +Step hen +Ä K ub +Ä Opp ortun +Ä He al +Ä bl o +Ä rul ers +Ä h uh +Ä submar ine +f y +ass er +Ä allow ance +Ä Kas ich +Ä T as +Ä Austral ians +Forge ModLoader +Ä ÃĸĨ Äŗ +Ä Mat rix +am ins +Ä 12 00 +Ä Ac qu +23 6 +D ocument +Ä Bre aking +19 3 +Ä Sub st +Ä Roll er +Ä Pro perties +Ä N I +t ier +Ä cr ushing +Ä advoc ating +Further more +keep ers +Ä sex ism +x d +Ä call er +Ä S ense +chie ve +Ä T F +Ä fuel ed +Ä reminis cent +Ä obs ess +ur st +Ä up hold +Ä F ans +het ics +Ä Ãĸ Äš +Ä B ath +Ä be verage +Ä o scill +25 4 +Ä pol es +Ä grad ual +Ä ex ting +Ä S uff +Ä S uddenly +Ä lik ing +Ä 19 49 +un ciation +am ination +Ä O mar +Ä L V +Ä Con sequently +Ä synt hes +Ä G IF +Ä p ains +Ä interact ing +u ously +inc re +Ä rum or +Ä Scient ology +19 7 +Ä Z ig +Ä spe lling +Ä A SS +Ä exting u +ms on +Ä g h +Ä remark ed +Ä Strateg ic +Ä M ON +ÃĨ ÂĨ +g ae +Ä WH AT +E ric +Ä Camp us +Ä meth ane +Ä imag in +J UST +Ä Al m +X T +i q +Ä R SS +Ä wrong doing +att a +Ä big ot +Ä demonstr ators +Ä Cal vin +Ä V illa +Ä membr ane +Ä Aw esome +Ä benef ic +26 8 +Ä magn ificent +Ä L ots +G reg +Ä Bor is +Ä detain ees +Ä H erman +Ä whis pered +Ä a we +Prof essor +fund ing +Ä phys iological +Ä Dest ruction +Ä lim b +Ä manip ulated +Ä bub bles +Ä pse ud +Ä hyd ra +Ä Brist ol +Ä st ellar +Ä Exp ansion +Ä K ell +Ä Interest ingly +Ä m ans +Ä drag ging +Ä ec ological +Ä F it +Ä g ent +Ä benef ited +Ä Hait i +Ä poly g +ÃŖÄĨ İ +Ä 20 30 +Ä pro w +Ä recon struction +Ä was t +Ä psych ic +Ä Gree ks +Hand ler +16 2 +Ä P ulse +Ä sol icit +Ä sy s +Ä influ x +Ä G entle +per cent +Ä prolifer ation +Ä tax able +Ä disreg ard +Ä esc aping +Ä g inger +Ä with stand +Ä devast ated +Ä D ew +ser ies +Ä inject ed +ela ide +Ä turn over +he at +Äģ Ĥ +H appy +Ä Sil ent +ÃŖÄ¤ Ń +iv ism +Ä ir rational +AM A +Ä re ef +r ub +Ä 16 2 +Ä bank ers +Ä Eth ics +v v +Ä critic isms +K n +18 6 +M ovie +Ä T ories +Ä no od +Ä dist ortion +F alse +od ore +Ä t asty +Res earch +Ä U ID +- ) +Ä divor ced +Ä M U +Ä Hay es +Ä Is n +ian i +Ä H Q +Ä " # +ign ant +Ä tra umatic +Ä L ing +H un +Ä sab ot +on line +r andom +Ä ren amed +ra red +K A +d ead +Ê t +Ä Ass istance +Ä se af +++++ ++++ +Ä se ldom +Ä Web b +Ä bo olean +u let +Ä ref rain +Ä DI Y +ru le +Ä shut ting +Ä util izing +load ing +Ä Par am +co al +oot er +Ä attract ing +Ä D ol +Ä her s +ag netic +Ä Re ach +im o +Ä disc arded +Ä P ip +01 5 +ÃÂŧ r +Ä m ug +Im agine +C OL +Ä curs ed +Ä Sh ows +Ä Curt is +Ä Sach s +spe aking +Ä V ista +Ä Fram ework +ong o +Ä sub reddit +Ä cr us +Ä O val +R ow +g rowing +Ä install ment +Ä gl ac +Ä Adv ance +EC K +Ä LGBT Q +LE Y +Ä ac et +Ä success ive +Ä Nic ole +Ä 19 57 +Qu ote +Ä circumst ance +ack ets +Ä 14 2 +ort ium +Ä guess ed +Ä Fr ame +Ä perpet rators +Ä Av iation +Ä Ben ch +Ä hand c +A p +Ä 19 56 +25 9 +r and +Net Message +d in +urt les +h ig +Ä V III +ff iti +Ä Sw ords +b ial +Ä kidn apping +dev ice +Ä b arn +Ä El i +auc as +S end +Con structed +Ġ ÂŊ +Ä need les +Ä ad vertisements +Ä v ou +Ä exhib ited +Ä Fort ress +As k +B erry +TY PE +Ä can cers +ump ing +Ä Territ ory +Ä pr ud +Ä n as +Ä athe ist +Ä bal ances +ÃŖÄŖ Ł +Ä Sh awn +& & +Ä land sc +Ä R GB +Ä pet ty +Ä ex cellence +Ä transl ations +Ä par cel +Ä Che v +E ast +Ä Out put +im i +Ä amb ient +Ä Th reat +Ä vill ains +Ä 5 50 +IC A +Ä tall er +Ä le aking +c up +Ä pol ish +Ä infect ious +Ä K C +Ä @ @ +back ground +Ä bureaucr acy +Ä S ai +un less +it ious +Ä Sky pe +At l +ID ENT +00 8 +Ä hyp ocr +Ä pit chers +Ä guess ing +Ä F INAL +Bet ween +Ä vill agers +Ä 25 2 +f ashion +Ä Tun is +Be h +Ä Ex c +Ä M ID +28 8 +Ä Has kell +19 6 +Ä N OR +Ä spec s +Ä inv ari +Ä gl ut +Ä C ars +Ä imp ulse +Ä hon ors +g el +Ä jurisd ictions +Ä Bund le +ul as +Calif ornia +Ä Incre ase +Ä p ear +Ä sing les +Ä c ues +Ä under went +Ä W S +Ä exagger ated +Ä dub ious +Ä fl ashing +L OG +) ]. +J ournal +t g +V an +Ä I stanbul +Ä In sp +Ä Frank en +D raw +Ä sad ness +Ä iron ic +Ä F ry +x c +Ä 16 4 +is ch +W ay +Ä Protest ant +h orn +Ä un aff +Ä V iv +ill as +Ä Product ions +Ä H ogan +Ä per imeter +Ä S isters +Ä spont aneous +Ä down side +Ä descend ants +Ä or n +w orm +Japan ese +Ä 19 55 +Ä 15 1 +Ä Do ing +els en +umb les +Ä rad ically +Ä Dr um +Ä B ach +Ä li abilities +Ä O B +Ä Element ary +Ä mem e +yn es +Ä finger print +Ä Gr ab +Ä undert ake +Mem bers +Ä Read er +Ä Sim s +g od +Ä hypot hetical +s cient +Ä A J +Ä char ism +Ä ad missions +Ä Miss ile +tr ade +Ä exerc ising +Ä Back ground +W ritten +Ä voc als +whe ther +Ä v i +Ä W inner +Ä l itter +Ä Sh ooting +ST EM +ÃŖÄ¤ ÂĄ +Ä A FL +Ä vari ability +Ä e ats +Ä D PS +b row +Ä eleph ants +Ä str at +Ä  Å +Ä sett lers +Matt hew +Ä in advert +H I +Ä IM F +Ä Go al +Ä nerv es +John son +ey e +ablish ment +Th ursday +BIL ITY +H ad +am oto +het amine +ep s +Ä mit ochond +Ä comp ressed +Ä Tre vor +Ä Anim als +T ool +L ock +Ä twe ak +Ä pin ch +Ä cancell ation +P ot +Ä foc al +Ä Ast ron +17 3 +Ä A SC +Ä O THER +umn i +Ä dem ise +d l +Ù ħ +Sem itism +Ä cr acking +Ä collabor ative +Ä expl ores +s ql +Ä her bs +Ä config urations +m is +Ä Res ult +ace y +Ä Sm oke +Ä san ct +el ia +Ä deg ener +Ä deep est +Ä scream ed +Ä n ap +Soft ware +Ä ST AR +E F +Ä X in +spons ored +mans hip +23 3 +Ä prim aries +Ä filter ing +Ä as semble +m il +Ä My ers +b ows +Ä pun ched +M ic +Ä innov ations +Ä fun c +and o +Ä fr acking +Ä V ul +О Ð +osh op +Ä Im mun +Ä sett ling +Ä adolesc ents +Ä reb uilding +Ä transform ing +Ä par ole +Ä har bor +Ä book ing +ot ional +onge vity +Ä Y o +b ug +Ä emer ges +Ä Method s +Ä Ch u +P res +Ä Dun geons +Ä tra iling +Ä R um +Ä H ugh +ÃĨ¤ Š +Ä E ra +Ä Batt les +Res ults +Ä Tr ading +Ä vers a +c ss +ax ies +he et +Ä gre ed +19 89 +Ä gard ens +Ä conting ent +P ark +Ä Leaf s +h ook +ro be +Ä diplom acy +Ä F uel +Ä Inv asion +Ä upgr ading +M ale +Ä e lic +Ä relent less +Ä Co venant +ap esh +Ä T rop +T y +pro duction +art y +Ä pun ches +ak o +cyclop edia +Ä R abbit +Ä HD MI +Ä 14 1 +Ä f oil +Item Image +Ä F G +Ä implement ations +Ä P om +ixt ures +Ä aw ait +Ä 3 30 +am us +Ä umb rella +Ä fore see +se par +Ä circum cision +Ä peripher al +S ay +Ä Exper t +In c +Ä withd rew +Ä And ers +f ried +Ä radio active +Ä Op ening +Ä board ing +Ä N D +Ä over throw +Act iv +W P +Ä Act s +× Äģ +Ä mot ions +v ic +Ä M ighty +Ä Def ender +a er +Ä thank ful +Ä K illing +Ä Br is +mo il +Ä predict ing +26 6 +ch oice +Ä kill ers +Ä inc ub +Ä Che st +ather ing +Ä pro claimed +fl ower +oss om +umbled ore +Ä Cy cling +Ä Occup y +AG ES +P en +Ä Y ug +Ä pack aged +Ä height ened +c ot +st ack +C ond +Ä st amps +m age +Ä persu aded +Ä ens l +Ä Card inal +Ä sol itary +Ä possess ing +Ä C ork +Ä ev id +Ä T ay +Ä bl ues +Ä extrem ism +Ä lun ar +Ä cl own +Te chn +Ä fest ivals +Ä Pv P +Ä L ar +Ä consequ ently +p resent +Ä som eday +ç İĭ +Ä Met eor +Ä tour ing +c ulture +Ä be aches +S hip +c ause +Ä Fl ood +ÃŖÄĨ ¯ +Ä pur ity +th ose +Ä em ission +b olt +Ä ch ord +Ä Script ure +L u +Ä $ { +cre ated +Other s +25 8 +Ä element al +Ä annoy ed +Ä A E +d an +Ä S ag +Res earchers +Ä fair y +ÃĸÄĸÄĩ ÃĸÄĸÄĩ +======== ==== +Sm art +GG GG +Ä skelet ons +Ä pup ils +link ed +Ä ur gency +en abled +Ä F uck +Ä coun cill +r ab +U AL +T I +Ä lif es +Ä conf essed +B ug +Ä harm on +Ä CON FIG +Ä Ne utral +D ouble +Ä st aple +Ä SH A +Brit ish +Ä SN P +AT OR +oc o +Ä swing ing +ge x +ole on +pl ain +Ä Miss ing +Ä Tro phy +v ari +ran ch +Ä 3 01 +4 40 +00000000 00000000 +Ä rest oring +Ä ha ul +uc ing +ner g +Ä fut ures +Ä strateg ist +quest ion +Ä later al +Ä B ard +Ä s or +Ä Rhod es +Ä D owntown +????? - +Ä L it +Ä B ened +Ä co il +st reet +Ä Port al +FI LE +Ä G ru +* , +23 1 +ne um +Ä suck ed +Ä r apper +Ä tend encies +Ä Laure n +cell aneous +26 7 +Ä brow se +Ä over c +head er +o ise +Ä be et +Ä G le +St ay +Ä m um +Ä typ ed +Ä discount s +T alk +Ä O g +ex isting +Ä S ell +u ph +C I +Ä Aust rian +Ä W arm +Ä dismiss al +Ä aver ages +c amera +Ä alleg iance +L AN +=" # +Ä comment ators +Ä Set ting +Ä Mid west +Ä pharm ac +Ä EX P +Ä stain less +Ch icago +Ä t an +24 4 +Ä country side +Ä V ac +29 5 +Ä pin ned +Ä cr ises +Ä standard ized +T ask +Ä J ail +Ä D ocker +col ored +f orth +" }, +Ä pat rons +Ä sp ice +Ä m ourn +Ä M ood +Ä laund ry +Ä equ ip +Ä M ole +y ll +Ä TH C +n ation +Ä Sher lock +Ä iss u +Ä K re +Ä Americ as +Ä A AA +Ä system atically +Ä cont ra +Ä S ally +Ä rational e +Ä car riage +Ä pe aks +Ä contrad iction +ens ation +Ä Fail ure +Ä pro ps +Ä names pace +Ä c ove +field s +ÃŖÄ¤ Ä­ +Ä w ool +Ä C atch +Ä presum ed +Ä D iana +r agon +ig i +Ä h amm +Ä st unt +Ä G UI +Ä Observ atory +Ä Sh ore +Ä smell s +ann ah +Ä cock pit +Ä D uterte +8 50 +Ä opp ressed +bre aker +Ä Cont ribut +Ä Per u +Ä Mons anto +Ä Att empt +Ä command ing +Ä fr idge +Ä R in +Ä Che ss +ual ity +Ä o l +Republic an +Ä Gl ory +Ä W IN +.... ... +ag ent +read ing +Ä in h +J ones +Ä cl icks +al an +Ä [ ]; +Ä Maj esty +Ä C ed +op us +ate l +à ÂĒ +AR C +Ä Ec uador +ÃŖÄĨ ł +Ä K uro +Ä ritual s +Ä capt ive +Ä oun ce +Ä disag reement +Ä sl og +f uel +P et +M ail +Ä exerc ised +Ä sol ic +Ä rain fall +Ä dev otion +Ä Ass essment +Ä rob otic +opt ions +Ä R P +Ä Fam ilies +Ä Fl ames +Ä assign ments +00 7 +aked own +Ä voc abulary +Re illy +Ä c aval +g ars +Ä supp ressed +Ä S ET +Ä John s +Ä war p +bro ken +Ä stat ues +Ä advoc ated +Ä 2 75 +Ä per il +om orph +Ä F emin +per fect +Ä h atch +L ib +5 12 +Ä lif elong +3 13 +Ä che eks +Ä num bered +Ä M ug +B ody +ra vel +We ight +Ä J ak +Ä He ath +Ä kiss ing +Ä J UST +Ä w aving +u pload +Ä ins ider +Ä Pro gressive +Ä Fil ter +tt a +Ä Be am +Ä viol ently +ip ation +Ä skept icism +Ä 19 18 +Ä Ann ie +Ä S I +Ä gen etics +Ä on board +at l +Ä Fried man +Ä B ri +cept ive +Ä pir ate +Ä Rep orter +27 8 +Ä myth ology +Ä e clipse +Ä sk ins +Ä gly ph +ing ham +F iles +C our +w omen +Ä reg imes +Ä photograp hed +K at +Ä MA X +Offic ials +Ä unexpected ly +Ä impress ions +F ront +;;;; ;;;; +Ä suprem acy +Ä s ang +Ä aggrav ated +Ä abrupt ly +Ä S ector +Ä exc uses +Ä cost ing +ide press +St ack +Ä R NA +ob il +Ä ghost s +ld on +at ibility +Top ics +Ä reim burse +Ä H M +Ä De g +Ä th ief +y et +ogen esis +le aning +Ä K ol +Ä B asketball +Ä f i +Ä See ing +Ä recy cling +Ä [ - +Cong ress +Ä lect ures +P sy +Ä ne p +Ä m aid +Ä ori ented +A X +Ä respect ful +re ne +fl ush +Ä Un loaded +re quest +gr id +Ä Altern atively +Ä Hug o +Ä dec ree +Ä Buddh ism +and um +And roid +Ä Cong o +Ä Joy ce +Ä acknowled ging +hes ive +Ä Tom orrow +Ä H iro +th ren +Ä M aced +Ä ho ax +Ä Incre ased +Ä Pr adesh +W ild +____ __ +16 1 +Ä a unt +Ä distribut ing +Ä T ucker +Ä SS L +Ä W olves +B uilding +ou lt +Ä Lu o +Ä Y as +Ä Sp ir +Ä Sh ape +Ä Camb od +Ä IP v +Ä m l +Ä ext rad +39 0 +Ä Penn y +d ream +Ä station ed +opt ional +ew orthy +. +Ä Works hop +Ä Ret ail +Ä Av atar +6 25 +N a +Ä V C +Ä Sec ure +M Y +19 88 +oss ip +Ä pro state +Ä und en +Ä g amer +Ä Cont ents +Ä War hammer +Ä Sent inel +3 10 +Ä se gregation +Ä F lex +Ä M AY +Ä dr ills +Ä Drug s +Islam ic +Ä sp ur +Ä ca fe +Ä imag inary +Ä gu iding +Ä sw ings +Ä The me +ob y +Ä n ud +Ä be gging +Ä str ongh +Ä reject ing +Ä pedest rians +Ä Pro spect +R are +s le +Ä concess ions +Ä Const itutional +Ä be ams +Ä fib ers +p oon +Ä instinct s +pro perty +Ä B IG +Sand ers +im ates +Ä co ating +Ä corps es +Ä TR UE +check ed +Ä 16 6 +A sh +Ä J S +Ä F iction +Ä commun al +Ä ener getic +oooo oooo +Ä now adays +IL D +ib o +Ä SU V +R en +Ä dwell ing +Sil ver +Ä t ally +Ä M oving +Ä cow ard +Ä gener als +Ä horn s +Ä circ ulated +Ä rob bed +Ä Un limited +Ä harass ed +Ä inhib it +Ä comp oser +Ä Spot ify +Ä spread s +3 64 +Ä su icidal +Ä no ises +Ä St ur +Ä s aga +Ä K ag +is o +Ä theoret ically +M oney +Ä similar ity +Ä slic ed +ut ils +ing es +" - +Ä an th +Ä imp ed +Mod ule +Through out +Ä men us +comm ittee +and i +ob j +in av +f ired +Ä Ab dullah +Ä und ead +Ä font s +H old +EN G +Ä sustain ability +Ä fl ick +Ä r azor +Ä F est +Ä Char acters +Ä word ing +Ä popul ist +Ä critic izing +Ä m use +v ine +Ä card board +Ä kind ly +Ä fr inge +Ä The ft +icult ural +Ä govern ors +Ä  ïÂŋÂŊïÂŋÂŊïÂŋÂŊïÂŋÂŊ +Ä 16 3 +Ä time out +Ä A uth +Child ren +A U +Ä red emption +Ä Al ger +Ä 19 14 +Ä w aved +Ä astron auts +og rams +Ä sw amp +Ä Finn ish +Ä cand le +Ä ton nes +ut m +Ä r ay +Ä sp un +Ä fear ful +art icles +Ä ca us +or ically +Ä Requ ires +Ä G ol +Ä pop e +Ä inaug ural +Ä g le +AD A +Ä IS IL +Ä Off ensive +Ä watch dog +Ä bal con +ent ity +Ä H oo +Ä gall on +AC C +Ä doub ling +Ä impl ication +Ä S ight +Ä doct r +---- --- +Ä \ \ +Ä m alt +R oll +Ä ÃĸÄĢ ÂĨ +Ä rec ap +add ing +u ces +Ä B end +fig ure +Ä tur key +Ä soc ietal +Ä T ickets +Ä commer cially +Ä sp icy +Ä 2 16 +Ä R amp +Ä superior ity +à ¯ +Ä Tr acker +C arl +Ä C oy +Ä Patri ot +Ä consult ed +Ä list ings +Ä sle w +reens hot +Ä G one +Ä [ ...] +30 9 +Ä h ottest +Ø Âą +Ä rock y +Ä D iaz +Ä mass age +Ä par aly +Ä p ony +A z +Ä cart ridge +Ä N Z +Ä sn ack +Ä Lam ar +ple ment +Ä Les lie +Ä m ater +Ä sn ipp +24 6 +Ä joint ly +Ä Bris bane +Ä iP od +Ä pump ing +Ä go at +Ä Sh aron +eal ing +Ä cor on +Ä an omal +rah im +Ä Connect ion +Ä sculpt ure +Ä sched uling +Ä D addy +at hing +Ä eyeb rows +Ä cur ved +Ä sent iments +Ä draft ing +D rop +( [ +Ä nom inal +Ä Leaders hip +Ä G row +Ä 17 6 +Ä construct ive +iv ation +Ä corrupt ed +ger ald +Ä C ros +Ä Che ster +Ä L ap +ÃŖÄŖ ÂĒ +OT H +D ATA +Ä al mond +pro bably +I mp +Ä fe ast +Ä War craft +F lor +Ä check point +Ä trans cription +Ä 20 4 +Ä twe aks +Ä rel ieve +S cience +Ä perform er +Z one +Ä tur moil +ig ated +hib it +Ä C afe +the med +Ä flu or +ben ch +Ä de com +Ä U nt +Ä Bar rett +Ä F acts +Ä t asting +Ä PTS D +Ä Se al +Ä Juda ism +Ä Dynam ic +Ä C ors +V e +Ä M ing +Ä Trans form +v on +Ä Def enders +Ä Tact ical +Ä V on +Ä Un ivers +Ä dist orted +Ä B reath +?' " +Ä ag on +Ä Dead ly +Ä l an +Ä Cy cle +orn ed +Ä rel iably +Ä gl or +Ä Mon key +ÃŖÄĨ ÂĄ +Ä ad ren +Ä microw ave +Ä Al ban +irc raft +dig it +sm art +Ä D read +¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯ +{ { +Ä Roc hester +Ä simpl ified +Ä inf licted +Ä take over +Ä your selves +ad itional +Ä mus cular +K S +Ä ing en +T ax +Ä Fe ature +27 7 +Ä cru c +Ä cr ate +Ä un identified +Ä acclaim ed +Ä M anga +Ä Fr ances +Ä Nep al +Ä G erald +Ä Ku wait +Ä sl ain +Ä He b +Ä G oku +ÃŖÄŖÂŽ ÃĻ +28 6 +M rs +Ä C ody +Ä San ctuary +01 6 +Ä dism ant +Ä datas et +Ä H ond +b uck +Ä Pat terson +Ä pal ette +Ä G D +ic ol +Ä L odge +Ä planet ary +ak in +Ä Regist ered +ab we +Ä Peters burg +Ä ha iled +Ä P iece +S che +Ä DO J +Ä en umer +18 1 +Ä Obs erver +Ä B old +f ounded +com merce +Ä explo its +Ä F inding +UR N +Ä S ne +Ä Ac id +ay ette +Ä Val ues +Ä dr astic +Ä architect ural +Ä " . +× ġ +ump ed +Ä wra pping +Ä wid ow +Ä Sl ayer +l ace +on ce +German y +av oid +Ä tem ples +P AR +à ´ +Ä Luc ifer +Ä Fl ickr +l ov +for ces +Ä sc outing +Ä lou der +tes y +Ä before hand +Ä Äĩ +Ä Ne on +Ä W ol +Ä Typ ically +Ä Polit ico +-+ -+ +Ä build er +Ä der ive +K ill +Ä p oker +Ä ambig uous +Ä lif ts +Ä cy t +Ä rib s +ood le +Ä S ounds +h air +Ä Synd rome +t f +Ä proport ional +u id +Ä per taining +Ä Kind le +Ä Neg ro +Ä reiter ated +Ä Ton ight +oth s +Ä Corn ell +Ä o wing +Ä 20 8 +elf are +oc ating +Ä B irds +Sub scribe +Ä ess ays +Ä burd ens +Ä illust rations +ar ious +ER AL +Ä Cal cul +Ä x en +Ä Link edIn +Ä J ung +Ä redes ign +Con nor +29 6 +Ä revers al +Ä Ad elaide +Ä L L +Ä s inking +Ä g um +US H +c apt +Ä Gr imm +Ä foot steps +Ä CB D +isp ers +Ä pro se +Wed nesday +Ä M ovies +ed in +Ä overturn ed +Ä content ious +US B +~~~~~~~~ ~~~~~~~~ +Ä Co pper +Ä point less +N V +val ues +olph in +d ain +Ä depos ited +Ä G W +Ä preced ed +Ä Cl a +Ä Go lem +Ä N im +ĠÎ ² +Ä Engine ers +m iddle +Ä fl att +oper ative +Ä council s +imb abwe +el in +Ä stress ful +Ä L D +Ä res h +l ake +Ä wheel chair +Ä Altern ative +Ä optim ize +oper ation +Ä pe ek +Ä ones elf +ig il +Ä trans itions +op athy +bl ank +Ä 16 9 +17 1 +________________________________ ________________________________ +Ä l aundering +En c +Ä D EC +Ä work outs +Ä sp ikes +Ä din osaurs +Ä discrim inatory +P ool +R ather +38 5 +R NA +tes ters +et o +Ä Ident ity +Ä ve in +Ä Bur ton +Ä arc ade +4 20 +Ult imately +Ä Sad ly +à ° +p ill +Ä cub ic +Ä Spect rum +the se +st ates +Ä un official +h awks +Ä EVER Y +Ä rain bow +Ä incarcer ation +and ing +Ä sy ll +Ä Ever ton +Ä 17 9 +Ä Ser bia +Ä 18 9 +m eter +Ä Mic key +Ä ant iqu +Ä fact ual +ne ck +Ä N are +n orm +m ust +Ä high ways +Ä gl am +Ä divid ing +Ä Squad ron +Ä Mar tha +Ä birth s +C over +//////// //////// +Ä W ong +Ph ot +Ä A LS +ri o +Ä Non etheless +Ä L emon +Ä 20 6 +Ä E E +Ä deriv ative +Ä WW II +v ote +Ä there in +Ä separ ating +44 6 +sy nc +Ä Stre ets +Ä r att +Ä municip ality +Ä Short ly +Ä mon k +) ," +Ä scr ub +Ä oper atives +Ne ither +Pl ace +Ä Lim it +F emale +Ä Act or +Char acter +Ä constit uted +35 7 +Ä protest ed +Ä St raw +Ä He ight +ild a +Ä Ty ph +Ä flood s +Ä cos metic +W AY +pert ure +up on +t ons +ess ing +Ä P ocket +Ä ro oft +Ä C aucas +Ä ant idepress +Ä incomp atible +EC D +Ä oper a +Ä Cont est +Ä gener ators +l ime +Def ense +19 87 +for um +Ä sav age +Ä Hung arian +n z +Ä met allic +Ä ex pelled +Ä res idency +Ä dress es +66 6 +Ä C lement +f ires +C ategory +Ä ge ek +al is +Ä c emetery +educ ated +Ä c rawl +Ä Un able +Ä T yson +ak is +Ä p ardon +Ä W ra +Ä strengthen ed +Ä F ors +33 5 +Ä H C +Ä M ond +Ä visual s +Ä Beat les +ett lement +Ä  ï +g ro +Ä b ash +Ä po orest +Ä ex cel +Ä aspir ations +Ä M unicip +ens ible +Ä ceremon ies +Ä intimid ation +Ä CON TR +be ck +Ä K ap +as u +Ä tradem arks +Ä S ew +Ä Comp etition +net work +Ä Ar ri +Ä T et +Ro aming +W C +D at +Ä so b +Ä pair ing +Ä overd ose +SA Y +ab er +Ä rev olt +Ä F ah +act ing +e q +est ation +F ight +Ä Mar ks +27 3 +Ä 17 8 +R aw +ÃŖÄŖ Ä­ +34 9 +bl ocks +Ä ver ge +est ine +Ä Pod esta +Ä inv asive +Ä profound ly +Ä A o +e ach +Ä l est +inter pret +Ä shr inking +Ä err one +Ä che es +ly s +Ä I vy +Ä Direct ory +Ä hint ed +V ICE +Ä contact ing +Ä G ent +he i +Ä label ing +Ä merc ury +Ä L ite +Ä exp ires +Ä dest abil +rit is +c u +Ä feather s +Ä ste er +Ä program med +Ä V ader +Go ing +Ä E lim +Ä y o +Ä Mic he +Ä 20 3 +Ä slee ves +Ä b ully +Ä Hum ans +36 8 +Ä comp ress +Ä Ban ner +AR S +Ä a while +Ä cal ib +Ä spons orship +Ä Diff iculty +Ä P apers +Ä ident ifier +} . +Ä y og +Ä Sh ia +Ä clean up +Ä vib e +int rodu +im ming +Austral ia +Ä out lines +Ä Y outube +tr ain +Ä M akes +Ä de ported +Ä cent r +Ä D ug +Ä B oulder +Ä Buff y +Ä inj unction +Ä Har ley +Ä G roups +Ä D umbledore +Ä Cl ara +Ä " - +Ä sacrific ed +ep h +Sh adow +ib ling +Ä freel ance +Ä evident ly +ph al +Ä ret ains +M ir +Ä fin ite +d ar +Ä C ous +Ä rep aired +Ä period ic +Ä champions hips +Ä aster oid +bl ind +Ä express ly +Ä Ast ros +Ä sc aled +Ä ge ographical +Ä Rap ids +En joy +Ä el astic +Ä Moh amed +Mark et +be gin +Ä disco vers +Ä tele communications +Ä scan ner +Ä en large +Ä sh arks +Ä psy chedel +Ä Rou ge +Ä snap shot +is ine +X P +Ä pestic ides +Ä L SD +Ä Dist ribution +re ally +Ä de gradation +Ä disgu ise +Ä bi om +Ä EX T +Ä equ ations +Ä haz ards +Ä Comp ared +) * +Ä virt ues +Ä eld ers +Ä enh ancing +Ä Ac ross +er os +ang ling +Ä comb ust +ucc i +Ä conc ussion +Ä contrace ption +Ä K ang +Ä express es +Ä a ux +Ä P ione +Ä exhib its +Deb ug +OT AL +Ä Al ready +Ä Wheel er +Ä exp ands +? : +Ä reconc iliation +Ä pir ates +Ä pur se +Ä discour age +Ä spect acle +R ank +Ä wra ps +Ä Th ought +Ä imp ending +O pp +Ä Ang lo +Ä E UR +Ä screw ed +ret ched +Ä encour agement +mod els +Ä conf use +mm m +Ä Vit amin +Ãĸďĺ Ãĸďĺ +C ru +Ä kn ights +Ä disc ard +Ä b ishops +Ä W ear +Ä Gar rett +k an +ÃŖÄĨ Ł +Ä mascul ine +cap ital +Ä A us +Ä fat ally +th anks +Ä A U +Ä G ut +12 00 +Ä  00000000 +Ä sur rog +Ä BI OS +ra its +Ä Wat ts +Ä resur rection +Ä Elect oral +Ä T ips +4 000 +Ä nut rient +Ä depict ing +Ä spr ink +Ä m uff +Ä L IM +Ä S ample +ps c +ib i +gener ated +Ä spec imens +Ä diss atisf +Ä tail ored +Ä hold ings +Ä Month ly +Ä E at +po ons +Ä ne c +Ä C age +Ä Lot us +Ä Lan tern +Ä front ier +Ä p ensions +Ä j oked +Ä Hard y +=-=- =-=- +r ade +U ID +Ä r ails +Ä em it +Ä sl ate +Ä sm ug +Ä sp it +Ä Call s +Ä Jac obs +f eat +Ä U E +Ä rest ruct +Ä regener ation +Ä energ ies +Ä Con nor +OH N +Ä Che ese +Ä g er +Ä resur rect +man agement +N W +Ä pres ently +Ä Bru ins +M ember +Ä M ang +id an +Ä boost ing +w yn ++ . +requ isite +Ä NY PD +Ä Me gan +Ä Cond itions +Ä p ics +nes ium +Ä R ash +Ä 17 4 +Ä D ucks +Ä emb ro +z u +on ian +rel igious +Ä c raz +Ä AC A +Ä Z ucker +EM A +Ä Pro s +We apon +Ä Kn ox +Ä Ar duino +Ä st ove +Ä heaven s +Ä P urchase +Ä her d +Ä fundra iser +Dig ital +5 000 +Ä prop onents +/ ÃĸÄĸÄ­ +Ä j elly +Ä Vis a +Ä mon ks +Ä advance ment +Ä W er +Ä 18 7 +e us +ert ility +Ä fet al +Ä 19 36 +L o +Ä out fits +Ä stair case +b omb +Ä custom ized +cl air +T ree +Ä m apped +Ä Consider ing +Ä Tor res +Ä meth yl +Ä approx imate +Ä do om +Ä Hans en +Ä c rossover +Ä stand alone +ä Âŧ +Ä inv ites +Ä gra veyard +Ä h p +Donald Trump +Ä esc ort +G ar +Ä predec essors +Ä h ay +Ä en zyme +Ä Stra ight +vis ors +I ng +ane ously +Ä App lied +Ä f ec +Ä Dur ant +Ä out spoken +or b +Ä z eal +Ä disgr ace +' ). +Ä Che ng +28 9 +Ä Ren a +Ä Su icide +29 4 +Ä out raged +Ä New man +Ä N vidia +Ä A ber +Ä B ers +Ä recre ation +Wind ow +Ä D P +x e +Ä ped oph +Ä fall out +ambo o +Ä present ations +Ä App s +Ä h tml +3 45 +Ä X XX +Ä rub bing +Ä Le ather +Ä hum idity +se ys +est ablished +Ä Un its +64 6 +Ä respect able +A uto +Ä thri ving +Ä Inn ovation +ang s +Ext ra +reg ulation +29 8 +p ick +Ex amples +Ä C J +Att ack +Ä dr acon +L T +Ä stick er +re rs +Ä sun ny +I ss +reg ulated +d im +Ä Ab stract +Ä hus bands +Off ice +om ination +it ars +AN GE +asc al +Ä K ris +Ä Inf antry +Ä m alf +Ä A the +Ä R ally +bal anced +................ ........ +OU P +Ä mole cule +met ics +Ä Spl it +Ä Instruct ions +Ä N ights +c ards +Ä t ug +Ä con e +ÃĨ Ń +Ä t x +Ä Disc ussion +Ä catast rophe +pp e +g io +Ä commun ism +Ä hal ted +Ä Gu ant +cle an +Ä Sc hed +Ä K anye +Ä w ander +Ä Ser iously +Ä 18 8 +enn ial +f ollow +product ive +Ä Fl ow +Ä S ail +Ä c raw +Ä sim ulations +or u +ang les +Ä N olan +Ä men stru +4 70 +Ä 20 7 +aj a +Ä cas ually +board ing +Ä 2 22 +ov y +Ä N umbers +um at +O E +28 7 +Ä Cle mson +Ä cert s +Ä sl id +Ä T ribe +Ä to ast +Ä fort unes +Ä f als +Ä Comm ittees +Ä g p +Ä f iery +Ä N ets +Ä An ime +Pack age +Ä Comp are +l aughter +in fect +Ä atroc ities +Ä just ices +Ä ins ults +Ä Vern on +Ä sh aken +Ä person a +est amp +36 7 +br ain +Ä experiment ing +K en +Ä Elect ronics +Ä 16 1 +dom ain +Ä graph ical +b ishop +Ä who pping +Ä Ev angel +Ä advertis ers +Ä Spe ar +Ä b ids +Ä destro ys +ut z +Ä unders c +Ä AD D +Ä an ts +Ä C um +ipp les +Ä F ill +Ä gl anced +Ä ind icted +Ä E ff +Ä mis con +Ä Des ktop +Ä ab ide +ÃŖÄĨ Äĸ +Ä I o +Ä C oul +Ä caps ule +Ä Ch rys +M ON +Ä und es +Ä I RA +Ä c itation +Ä dict ate +Ä Net works +Ä Conf lict +Ä St uff +x a +is ec +Ä Chem istry +Ä quarter ly +William s +an an +O pt +Ä Alexand ria +out heastern +Ä Spring field +Ä Black s +Ä ge ography +24 2 +Ä ut most +Ä Ex xon +ab outs +E VA +Ä En able +Ä Bar r +Ä disag reed +Ä Cy prus +Ä dement ia +Ä lab s +Ä ubiqu itous +Ä LO VE +Ä consolid ated +s r +Ä cream y +Ä Tim ber +Reg ardless +Ä Cert ificate +Ä " ... +ogen ous +Capt ain +Ä insult ing +Ä Sor os +Ä Inst r +Ä Bulgar ia +bet ter +Ä suck ing +Ä David son +at z +Ä coll ateral +g if +Ä plag ued +Ä C ancel +Ä Gard ner +R B +Ä six teen +Rem ove +ur istic +c ook +R od +Ä compr ising +f le +) ÃĸÄĸÄļ +Ä Vik ing +g rowth +agon al +Ä sr f +af ety +m ot +N early +st own +Ä F actor +Ä autom obile +Ä proced ural +m ask +amp ires +Ä disapp ears +j ab +3 15 +Ä 19 51 +ne eded +Ä d aring +le ader +Ä p odium +Ä un healthy +Ä m und +Ä py ramid +oc re +Ä kiss ed +Ä dream ed +Ä Fant astic +Ä G ly +ÃĨ ÄŦ +Ä great ness +Ä sp ices +Ä met ropolitan +Ä comp uls +i ets +101 6 +Ä Sh am +Ä P yr +fl ies +Ä Mid night +Ä swall owed +Ä gen res +Ä L ucky +Ä Rew ards +Ä disp atch +Ä I PA +Ä App ly +Ä a ven +al ities +3 12 +th ings +Ä ( ). +Ä m ates +Ä S z +Ä C OP +ol ate +O FF +Ä re charge +c aps +Ä York er +ic one +Ä gal axies +ile aks +D ave +Ä P uzz +Ä Celt ic +Ä A FC +27 6 +Ä S ons +Ä affirm ative +H or +Ä tutorial s +Ä C ITY +Ä R osa +Ä Ext ension +Ser ies +Ä f ats +Ä r ab +l is +Ä un ic +Ä e ve +Ä Sp in +Ä adul thood +ty p +Ä sect arian +Ä check out +Ä Cy cl +S ingle +Ä mart yr +Ä ch illing +88 8 +ou fl +Ä ] ; +Ä congest ion +m k +Ä Where as +Ä 19 38 +ur rencies +er ion +Ä bo ast +Ä Pat ients +Ä ch ap +Ä B D +real DonaldTrump +Ä exam ines +h ov +Ä start ling +Ä Bab ylon +w id +om ew +br ance +Ä Od yssey +w ig +Ä tor ch +Ä V ox +Ä Mo z +Ä T roll +Ä An s +Similar ly +Ä F ul +00 6 +Un less +Ä Al one +st ead +Ä Pub lisher +r ights +t u +Ä Does n +Ä profession ally +Ä cl o +ic z +Ä ste als +Ä  ÃĄ +19 86 +Ä st urdy +Ä Joh ann +Ä med als +Ä fil ings +Ä Fr aser +d one +Ä mult inational +Ä f eder +Ä worth less +Ä p est +Yes terday +ank ind +Ä g ays +Ä b orne +Ä P OS +Pict ure +Ä percent ages +25 1 +r ame +Ä pot ions +AM D +Ä Leban ese +Ä r ang +Ä L SU +ong s +Ä pen insula +Ä Cl ause +AL K +oh a +Ä Mac Book +Ä unanim ous +Ä l enders +Ä hang s +Ä franch ises +ore rs +Ä Up dates +Ä isol ate +and ro +S oon +Ä disrupt ive +Ä Sur ve +Ä st itches +Ä Sc orp +Ä Domin ion +Ä supp lying +Ar g +Ä tur ret +Ä L uk +Ä br ackets +* ) +Ä Revolution ary +Ä Hon est +Ä not icing +Ä Sh annon +Ä afford ed +Ä th a +Ä Jan et +! -- +Ä Nare ndra +Ä Pl ot +H ol +se ver +e enth +Ä obst ruction +Ä 10 24 +st aff +j as +or get +sc enes +l aughs +Ä F argo +cr ime +Ä orche str +Ä de let +ili ary +rie ved +Ä milit ar +Ä Green e +ÃĸÄš Äą +ÃŖÄŖ ÂĻ +Ä Gu ards +Ä unle ashed +Ä We ber +Ä adjust able +Ä cal iber +Ä motiv ations +Ġà ł +m Ah +Ä L anka +hand le +Ä p ent +Ä R av +Ä Ang ular +Ä K au +umb ing +Ä phil anthrop +Ä de hyd +Ä tox icity +e er +Ä Y ORK +w itz +ÃĨ Âŧ +Ä I E +commun ity +Ä A H +Ä ret ali +Ä mass ively +Ä Dani els +Ä D EL +Ä car cin +Ur l +Ä rout ing +Ä NPC s +Ä R AF +ry ce +Ä wa ived +Ä Gu atem +Every body +Ä co venant +Ä 17 3 +Ä relax ing +Ä qu art +al most +Ä guard ed +Ä Sold iers +Ä PL AY +Ä out going +L AND +Ä re write +Ä M OV +Ä Im per +Ä S olution +Ä phenomen al +Ä l ongevity +Ä imp at +Ä N issan +ir ie +Ä od or +Ä Z ar +ok s +Ä milit ias +Ä SP EC +Ä toler ated +ars er +Ä Brad ford ++ , +Ä sur real +s f +Can adian +Ä resemb lance +Ä carbohyd rate +VI EW +Ä access ory +me al +larg est +ieg el +Some one +Ä toug hest +os o +Ä fun nel +Ä condemn ation +lu ent +Ä w ired +Ä Sun set +Jes us +Ä P ST +Ä P ages +Ä Ty coon +Ä P F +Ä select ions +Ä  ठ+part isan +Ä high s +Ä R une +Ä craft s +le ad +Ä Parent s +Ä re claim +ek er +Ä All ied +ae per +Ä lo oming +Ä benefic iaries +Ä H ull +Stud ents +Jew ish +d j +Ä p act +tem plate +Ä Offic ials +Ä Bay lor +Ä he mp +Ä youth s +Ä Level s +Ä X iao +Ä C hes +Ä ende avor +Ä Rem oved +Ä hipp ocamp +H ell +ÃŖÄ¤ ÄŦ +80 5 +Ä d inosaur +Ä Wr ath +Ä Indones ian +Ä calcul ator +Ä D ictionary +Ä 4 20 +Ä M AG +( _ +! , +t arians +Ä restrict ing +rac use +Ä week day +OU NT +Ä sh rugged +leg round +Ä b ald +Ä Do ctors +Ä t outed +Ä Max well +Ä 2 14 +Ä diplom at +Ä rep ression +Ä constitu ency +v ice +r anked +Ä Nap oleon +g ang +Ä Fore ver +t un +Ä bul b +Ä PD T +Ä C isco +V EN +Ä res umed +Ste ven +Ä Manit oba +Ä fab ulous +Ä Ag ents +19 84 +Ä am using +Ä Myster ies +Ä or thodox +fl oor +Ä question naire +Ä penet rate +Ä film makers +Ä Un c +Ä st amped +Ä th irteen +Ä out field +Ä forward ed +Ä app ra +Ä a ided +t ry +Ä unf ocused +Ä L iz +Ä Wend y +Ä Sc ene +Ch arg +Ä reject s +Ä left ist +Ä Prov idence +Ä Br id +reg n +Ä prophe cy +Ä L IVE +4 99 +Ä for ge +Ä F ML +Ä intrins ic +Ä F rog +Ä w ont +Ä H olt +Ä fam ed +CL US +aeper nick +Ä H ate +Ä C ay +Ä register ing +ort ality +rop y +ocaly ptic +a an +n av +Ä fasc ist +IF IED +Ä impl icated +Ä Res ort +Ä Chand ler +Ä Br ick +P in +ys c +Us age +Ä Hel m +us ra +ÃĸÄēħ ÃĸÄēħ +Ä Ab bas +Ä unanim ously +Ä ke eper +Ä add icted +?? ? +Ä helm ets +Ä ant ioxid +aps ed +80 8 +gi ene +Ä wa its +Ä min ion +ra ved +Ä P orsche +Ä dream ing +Ä 17 1 +Ä C ain +Ä un for +ass o +Ä Config uration +k un +hard t +Ä n ested +Ä L DS +L ES +Ä t ying +en os +Ä c ue +Ä Mar qu +sk irts +Ä click ed +Ä exp iration +Ä According ly +Ä W C +Ä bless ings +Ä addict ive +Ä N arr +y x +Ä Jagu ars +Ä rent s +Ä S iber +Ä t ipped +ous se +Ä Fitz gerald +Ä hier arch +out ine +Ä wa velength +> . +ch id +Ä Process ing +/ + +r anking +E asy +Ä Const ruct +Ä t et +ins ured +H UD +Ä qu oting +Ä commun icated +in x +Ä in mate +Ä erect ed +Ä Abs olutely +Ä Sure ly +Ä un im +Ä Thr one +he id +Ä cl aws +Ä super star +Ä L enn +Ä Wh is +U k +ab ol +Ä sk et +Ä N iet +Ä per ks +Ä aff inity +Ä open ings +phas is +Ä discrim inate +T ip +v c +Ä gr inding +Ä Jenn y +Ä ast hma +hol es +Ä Hom er +Ä reg isters +Ä Gl ad +Ä cre ations +Ä lith ium +Ä appl ause +unt il +Just ice +Ä Tur ks +Ä sc andals +Ä b ake +t ank +M ech +Ä Me ans +Ä M aid +Republic ans +is al +wind ows +Ä Sant os +Ä veget ation +33 8 +t ri +Ä fl ux +ins ert +Ä clar ified +Ä mort g +Ä Ch im +Ä T ort +Ä discl aim +met al +Ä As ide +Ä indu ction +Ä inf l +Ä athe ists +amp h +Ä e ther +Ä V ital +Ä Bu ilt +M ind +Ä weapon ry +S ET +Ä 18 6 +ad min +g am +cont ract +af a +Ä deriv atives +Ä sn acks +Ä ch urn +E conom +Ä ca pped +Ä Under standing +Ä H ers +Ä I z +Ä d uct +I ENT +augh ty +Ä ÃĸÄž Äļ +Ä N P +Ä sa iling +In itialized +Ä t ed +Ä react ors +Ä L omb +Ä cho ke +Ä W orm +Ä adm iration +Ä sw ung +ens ibly +Ä r ash +Ä Go als +Ä Import ant +Sh ot +Ä R as +Ä train ers +Ä B un +Work ing +Ä har med +Ä Pand ora +Ä L TE +Ä mush room +Ä CH AR +Ä F ee +Ä M oy +B orn +ol iberal +Ä Mart ial +Ä gentle men +Ä ling ering +Offic ial +Ä gra ffiti +Ä N ames +D er +Ä qu int +ist rate +aze era +Ä NOT ICE +Ä Flore nce +Ä pay able +Ä dep icts +Ä Spe cies +He art +ÃĸÄļÄĸÃĸÄļÄĸÃĸÄļÄĸÃĸÄļÄĸ ÃĸÄļÄĸÃĸÄļÄĸÃĸÄļÄĸÃĸÄļÄĸ +Ä encl osed +Incre ases +D aily +Ä L is +Ä enact ment +Ä B acon +Ä St eele +dem and +Ä 18 3 +Ä mouth s +Ä str anded +Ä enhance ment +01 1 +Ä Wh ats +Ä he aled +en y +Ä R ab +Ä 3 40 +Ä Lab yrinth +ro ach +Ä Y osh +Ä Cl ippers +Ä concert s +Intern et +35 5 +Ä stick ers +Ä ter med +Ä Ax e +Ä grand parents +Fr ance +Ä Cl im +Ä U h +ul ic +Ä thr ill +cent ric +Ä Over view +Ä Cond uct +Ä substant ive +Ä 18 2 +m ur +Ä str ay +Ä Co ff +Ä rep etitive +Ä For gotten +Ä qual ification +ew itness +Ä Z imbabwe +Ä sim ulated +Ä J D +25 3 +Ä W are +Ä un sc +T imes +Ä sum mons +Ä dis connected +Ä 18 4 +ci us +Ä Gu jar +od ka +Ä er ase +Ä Tob acco +elect ed +Ä un cont +Ä She pard +Ä L amp +Ä alert ed +Ä oper ative +arn a +u int +Ä neglig ence +ac ements +Ä sup ra +Ä prev ail +Ä Sh ark +Ä bel ts +ÃŖÄŖ ÂĢ +Ä t ighter +Engine ers +Ä in active +Ä exp onent +Ä Will ie +a ples +Ä he ir +Ä H its +ian n +Ä S ays +Ä current s +Ä Beng al +Ä ar ist +B uffer +Ä bree ze +Ä Wes ley +Col a +Ä pron oun +Ä de ed +Ä K ling +Ä of t +Ä inf lict +Ä pun ishing +Ä n m +ik u +OD UCT +01 4 +Ä subsid y +Ä DE A +Ä Her bert +Ä J al +B ank +Ä def erred +Ä ship ment +B ott +Ä al le +b earing +HT ML +Off line +Ä 2 13 +Ä scroll ing +Ä sc anned +Ä Lib yan +Ä T OP +ch rom +d t +col umn +Psy NetMessage +Z ero +Ä tor so +0 50 +Ãĸġ IJ +Ä imp erson +Ä Schw artz +ud ic +Ä piss ed +Ä S app +25 7 +Ä IS Ps +og l +Ä super vised +Ä ad olescent +Ä att ained +Ä Del ivery +Ä B unny +Ä 19 37 +Ä mini ature +Ä o s +Ä 3 70 +60 8 +Ä Mour inho +Ä inn ate +Ä tem po +Ä N M +Ä Fall en +00 9 +Ä prov ocative +Stream er +Ä Bened ict +Ä Bol she +Ä t urtle +Ä PC B +Ä Equ al +Direct or +Ä R end +Ä flu ids +Author ities +Ä cous ins +requ ency +Ä Neigh bor +s ets +sh ared +Char les +pass word +Ä g ears +Ä 2 11 +Ä Hard ware +ri ka +Ä up stream +H om +Ä disproportion ately +iv ities +Ä und efined +Ä elect rons +Ä commem or +Event ually +Ä > < +Ä ir responsible +2 18 +Ä Re leased +Ä O VER +Ä I GN +Ä B read +st ellar +Ä S age +tt ed +dam age +ed ition +Ä Pre c +Ä l ime +Ä conf inement +Ä cal orie +we apon +Ä diff ering +Ä S ina +m ys +am d +Ä intric ate +k k +Ä P AT +ÃƒÂŖ o +st ones +lin ks +Ä r anch +Sem itic +Ä different iate +Ä S inger +occup ied +Ä fort ress +c md +Ä inter ception +Ä Ank ara +Ä re pt +Ä Sol itaire +Ä rem ake +p red +Ä d ared +aut ions +Ä B ACK +Run ning +Ä debug ging +Ä graph s +3 99 +Ä Nig el +Ä b un +Ä pill ow +Ä prog ressed +fashion ed +Ä ob edience +ER N +Ä rehe ars +C ell +t l +S her +Ä her ald +Ä Pay ment +Ä C ory +Ä De pt +Ä rep ent +Ä We ak +uck land +Ä ple asing +Ä short ages +Ä jur ors +Ä K ab +q qa +Ant i +Ä w ow +Ä RC MP +Ä t sun +Ä S ic +Ä comp rises +Ä sp ies +Ä prec inct +n u +Ä ur ges +Ä tim ed +Ä strip es +Ä B oots +Ä y en +Adv anced +Ä disc rete +Ä Arch angel +employ ment +D iff +Ä mon uments +Ä 20 9 +work er +Ä 19 6 +Ä I g +utter stock +T PS +J ac +Ä homeless ness +Ä comment ator +Ä rac ially +f ing +se ed +E le +ell ation +Ä eth anol +Ä par ish +Ä D ong +Ä Aw akening +Ä dev iation +Ä B earing +Ä Tsu k +Ä rec ess +Ä l ymph +Ä Cann abis +ÃĨ Äž +Ä NEW S +Ä d ra +Ä Stef an +Ä Wr ong +Ä S AM +Ä loose ly +Ä interpre ter +Ä Pl ain +Go vernment +Ä bigot ry +Ä gren ades +ave z +pict ured +Ä mand ated +Ä Mon k +Ä Ped ro +Ä l ava +27 4 +Ä cyn ical +Ä Scroll s +l ocks +M p +Ä con gregation +orn ings +ph il +Ä I bid +Ä f erv +Ä disapp earing +Ä arrog ant +sy n +Ä Ma ver +Ä Su it +24 1 +Ä ab bre +ack ers +P a +Ä Y el +Whe never +Ä 23 5 +Ä V ine +Ä An at +Ä ext inct +LE T +Ä execut able +V ERS +ox ide +D NA +Ä P rel +Ä resent ment +Ä compr ise +Ä Av iv +Ä inter ceptions +Ä prol ific +IN A +Ä Er in +though t +2 19 +Ä Psychiat ry +un ky +chem ist +H o +Ä McC oy +Ä br icks +L os +ri ly +Ä US SR +Ä r ud +Ä l aud +Ä W ise +Ä Emer ald +Ä rev ived +Ä dam ned +Ä Rep air +id em +ct ica +Ä patri arch +Ä N urs +me g +Ä cheap est +re ements +empt y +Ä Cele br +Ä depri vation +ch anted +Ä Th umbnails +E nergy +Ä Eth an +Ä Q ing +Ä opp oses +W IND +v ik +Ä M au +Ä S UB +66 7 +G RE +Ä Vol unte +nt on +C ook +ÃĨ IJ +es que +Ä plum met +Ä su ing +Ä pron ounce +Ä resist ing +Ä F ishing +Ä Tri als +Ä y ell +Ä 3 10 +Ä in duct +Ä personal ized +oft en +R eb +EM BER +Ä view point +Ä exist ential +() ) +rem ove +MENT S +l asses +Ä ev apor +Ä a isle +met a +Ä reflect ive +Ä entit lement +Ä dev ised +mus ic +asc ade +Ä wind ing +off set +Ä access ibility +ke red +Bet ter +Ä John ston +th inking +S now +Ä Croat ia +Ä At omic +27 1 +34 8 +Ä text book +Ä Six th +Ä  اÙÄĻ +Ä sl ider +Ä Bur ger +b ol +S ync +Ä grand children +Ä c erv ++ ) +Ä e ternity +Ä tweet ing +Ä spec ulative +Ä piv otal +Ä W P +Ä T ER +ynam ic +Ä u pl +Ä C ats +per haps +Ä class mates +Ä blat ant +' - +Ä l akh +ant ine +Ä B org +i om +/ ( +Ä Athlet ic +Ä s ar +OT A +Ä Hoff man +Never theless +Ä ad orable +Ä spawn ed +Ass ociated +Ä Dom estic +Ä impl ant +Ä Lux em +Ä K ens +Ä p umps +Ä S AT +Att ributes +50 9 +av our +Ä central ized +Ä T N +Ä fresh ly +Ä A chieve +Ä outs iders +her ty +Ä Re e +Ä T owers +Ä D art +ak able +Ä m p +Ä Heaven ly +Ä r ipe +Ä Carol ine +ry an +Ä class ics +Ä ret iring +Ä 2 28 +Ä a h +Ä deal ings +Ä punch ing +Ä Chap man +O ptions +max well +vol ume +Ä st al +Ä ex ported +Ä Qu ite +Ä numer ical +B urn +F act +Ä Key stone +Ä trend ing +Ä alter ing +Ä Afric ans +47 8 +Ä M N +Ä Kn ock +Ä tempt ation +Ä prest ige +Over view +Ä Trad itional +Ä Bah rain +Priv ate +Ä H OU +Ä bar r +Ä T at +C ube +US D +Ä Grand e +Ä G at +Ä Fl o +Ä res ides +Ä ind ec +vol ent +Ä perpet ual +ub es +Ä world view +Ä Quant um +Ä fil tered +Ä en su +orget own +ERS ON +Ä M ild +37 9 +OT T +à ÂĨ +Ä vit amins +Ä rib bon +Ä sincere ly +Ä H in +Ä eight een +Ä contradict ory +Ä gl aring +Ä expect ancy +Ä cons pir +Ä mon strous +Ä 3 80 +re ci +Ä hand ic +Ä pump ed +Ä indic ative +Ä r app +Ä av ail +Ä LEG O +Ä Mar ijuana +19 85 +ert on +Ä twent ieth +################ ################ +Ä Sw amp +Ä val uation +Ä affili ates +adjust ed +Ä Fac ility +26 2 +Ä enz ymes +itud inal +Ä imp rint +S ite +Ä install er +Ä T RA +m ology +lin ear +Ä Collect ive +ig ating +Ä T oken +Ä spec ulated +K N +Ä C ly +or ity +Ä def er +Ä inspect ors +appro ved +R M +Ä Sun s +Ä inform ing +Ä Sy racuse +ib li +7 65 +Ä gl ove +Ä author ize +ÃĸÄĸÂĻÃĸÄĸÂĻÃĸÄĸÂĻÃĸÄĸÂĻ ÃĸÄĸÂĻÃĸÄĸÂĻÃĸÄĸÂĻÃĸÄĸÂĻ +Ä Cru ise +Ä contract ing +she ll +IF E +Ä Jew el +p ract +Ä Phot oshop +Ä Know ing +h arm +Ä attract ions +ad an +et us +01 8 +w agen +Al t +Ä multip ly +Ä equ ilibrium +: { +Ä F ighters +Ä Ed gar +Ä four teen +Go vern +Ä mis use +Ä ab using +Ä ancest ry +ram er +64 4 +Ä wor ms +Ä thick er +Ä Comb ine +Ä peas ants +Ä v ind +Ä con quest +Ä m ocked +Ä c innamon +Ä C ald +Ä Gall up +Ä avoid ance +Ä incarn ation +Ä Str at +Ä t asted +ent a +Ä N eal +p ared +Ä termin ology +ject ion +Scient ists +Ä IN S +Ä De e +Ä direct ories +R oad +Ä Sh ap +br ight +Ä Direct ors +Ä Col umn +Ä b ob +Ä prefer ably +Ä gl itch +f urt +Ä e g +id is +C BC +Ä sur rendered +Ä test ament +33 6 +ug gest +Ä N il +an other +Ä pat hetic +Ä Don na +Ä 2 18 +Ä A very +Ä whis key +Ä f ixture +Ä Con quest +Ä bet s +O cc +Ä Le icester +] ." +Ä ) ); +Ä fl ashes +45 6 +Ä mask ed +ge bra +Ä comput ed +che l +aud er +Ä defe ats +Ä Liber ation +Ä Os ama +Ä V ive +Ch anges +Ch annel +Ä tar iffs +Ä m age +Ä S ax +Ä inadvert ently +Ä C RE +Ä Re aper +ink y +gr ading +Ä stere otyp +Ä cur l +Ä F ANT +Ä fram eworks +M om +Ä An ch +Ä flav our +car bon +Ä perm itting +let cher +Ä Mo zilla +Ä Park ing +Ä Ch amp +Sc roll +Ä murd erer +Ä rest ed +Ä ow es +Ä P oss +AD D +IF F +res olution +Ä Min ing +Ä compar ative +D im +Ä neighbour ing +Ä A ST +Ä T oxic +Ä bi ases +Ä gun fire +ur ous +Ä Mom ent +19 83 +Ä per vasive +tt p +Ä Norm ally +r ir +S arah +Ä Alb any +Ä un sett +Ä S MS +ip ers +l ayer +Ä Wh ites +up le +Ä tur bo +Ä Le eds +Ä that s +Ä Min er +M ER +Ä Re ign +Ä per me +Ä Bl itz +Ä 19 34 +Ä intimid ating +t ube +Ä ecc entric +ab olic +box es +Ä Associ ates +v otes +Ä sim ulate +um bo +aster y +Ä ship ments +FF FF +an th +Ä season ed +Ä experiment ation +Ãĸĸ ł +law s +Me et +idd les +ant ics +R ating +IS IS +h ift +Ä front s +b uf +01 7 +Ä un att +Ä D il +le ases +Ä Gard ens +77 7 +t ouch +ve ll +45 8 +Ä = ==== +s aving +Ä er osion +Ä Qu in +Ä earn s +Ä accomplish ment +Ä We i +Ä < [ +____ _ +Ä ir rig +Ä T eddy +Ä conqu ered +Ä Arm ored +Ä assert s +Ä manip ulating +r Ê +Ä transcript s +G allery +Ä plot ting +Ne il +Ä betray al +load er +Ä S ul +Ä displ acement +Ä roy alty +Ä W I +he it +Ä Dev ices +alle l +Ä municipal ities +Ä can al +St ars +Ä U AE +Ä " ÃĸÄĸÂĻ +Ä C U +ab ove +Ä reson ance +Ä guiActive Un +add ed +Ä Bra ves +Ä I bn +Ä here by +Ä B RE +Ä share holder +Ä H ir +Ä J i +Ä strange ly +Ä adm ired +Ä pl ight +Ä b achelor +Ä P ole +cipl inary +T ony +Ä Armen ian +Ä un man +Ä Zion ist +St age +isco ver +Ä autom otive +Ä s idelines +Ä sl ick +Ä Rena issance +Ä F UN +Im ages +Ä H aj +Ä p ing +Ä short cut +Ä Bl vd +Ä Look s +Ä bur sts +Ä cl amp +Ä m ish +Ä sort ing +Ä patri ot +Ä correct ness +Ä Scand inav +Ä Caval iers +p ython +az ar +Ä 3 75 +Ä Ja une +40 9 +Ä detrim ental +Ä stab bing +Ä poison ed +Ä f ountain +oc ent +or st +Ä Mar i +Ä r ains +Ä O vers +Ä Inst itution +ud get +AM Y +t ale +Ä K R +Ä Pr ices +Ä head aches +Ä lands l +Ä A ura +Bon us +Ä Z hao +Ä H ip +Ä hop s +Ä Kurd istan +Ä explo iting +ry n +Ä hypocr isy +op ening +Ä gun shot +Ä w ed +inter stitial +Inter stitial +Ä am en +Bre aking +Ä market ed +W ire +Ä C rowd +Contin ue +Ä K nown +Ä Effect ive +ore an +iz ons +Jose ph +Ä escal ation +us ername +Ä cur tain +AT ES +Ä P AR +Ä M iy +Ä counter fe +l ene +Ä cont enders +d aily +Ä As c +Ä Phill ip +most ly +Ä fil ename +he ne +Ä resemb ling +Ä st aging +Ä Ch loe +Ä w iring +H on +Ä Ren ew +ott age +Ä Hy brid +m uch +Ä stro kes +Ä policy makers +AP TER +Ä Ark ham +pl ot +Ä assist ants +Ä de port +Ä Se ga +Ä influ enza +Ä C ursed +Ä K obe +Ä skin ny +Prov ider +Ä R ip +Ä increment al +product s +B F +Ä d ome +Ä C redits +Ä los ers +int s +Ä Bet ty +Ä Tal ent +Ä D AM +L v +E ss +Ä d ens +tem p +J udge +od ic +Ä ' ( +UR ES +ets k +V O +Ä retrie ved +Ä architect s +Ù ÄŠ +Ä eth ic +Ä Second ary +st ocks +ad ia +Ä 3 25 +Ä Op inion +Ä simultane ous +Ä d izz +ul p +Ä smugg ling +ipp ery +R andom +f acing +Ä D as +Ä stock p +Ä discl osures +po inter +Ä cor al +Ä Se lection +Ä P ike +ival ent +Ä ruth less +Ä R im +Ä ensu ing +Ä Exper iment +Ä congress man +Ä belie ver +Ä un specified +Ä M ord +Ä knowledge able +Ä V ERY +T X +Ä stra ps +Ä tur f +apesh ifter +Ä mar ital +Ä fl ock +ÃŖÄŖ Ĩ +26 3 +AM ES +Ä Opp osition +Ä tre asures +Ä G OD +Ä model ed +Ä WOR LD +Ä ( [ +Ä Us age +H F +Ä $ ( +uss ed +Ä pione er +E ight +par se +b read +rit z +Ä Mir anda +Ä K ant +++ ) +ore n +Ä prov oked +Ä bre eds +Ä In cludes +Ä Past ebin +Ä Fl ip +J ava +Ä br ink +Ä rum ored +Ä un seen +Ä gar nered +Ä Def in +al ted +Ä tatt oos +Ä hes itation +is itions +Ä We aver +Ä Report ing +Ä therap ies +Ä consult ants +Ä resid ual +Ä Mal i +Ä Rom a +i ago +Ä Res idents +ub i +Ä remed ies +Ä adapt ive +Ä Al ive +Ä Bar cl +Ä wal lets +c rypt +etermin ation +Ä Pel osi +Ä sl ipping +oton in +Ä all iances +pat rick +ir is +Ä or th +Ä Per kins +Ä De V +Ä G ets +Ä dry ing +ge e +fore st +Ä For get +ore m +33 9 +Ä vague ly +Ä D ion +Ä P orn +Ä H OW +Ä p neum +Ä rub ble +Ä T aste +enc ia +Ä G el +Ä d st +Ä 24 5 +Ä Moroc co +inf lamm +Ä Tw ins +Ä b ots +d aughter +Ä B alk +Ä bre thren +Ä log os +Ä go bl +f ps +Ä sub division +Ä p awn +Ä squee zed +Ä mor ale +Ä D W +' " +Ä kn ot +ook y +Ä div isive +Ä boost ed +ch y +ÃŖÄĨ IJ +if act +Ä newcom ers +Ä Wrest ling +Ä sc outs +w olves +R at +Ä nin eteenth +Ä Os borne +St ats +Ä em powered +Ä psych opath +Ä O EM +ugg age +Ä P K +Ä Moh ammad +P ak +Ä anarch ists +Ä Ext ract +est hes +Ä Stock holm +l oo +Ä G raph +Ä deploy ing +Ä Str anger +Ä M old +Ä staff er +Ä discount ed +uck le +ple ase +Ä Land ing +ÃŃ a +Ä 19 3 +Ä an te +Ä rep etition +Ä + /- +Ä par ody +Ä live ly +AA A +Ä Hor us +Ä p its +ind ers +L OC +Ä Ven ice +40 6 +Ä Dis cover +Ãĸ Ĩ +ellect ual +Ä p ens +Ä ey el +ig uous +Im pl +Ä j oking +Ä inv al +Ä Bel fast +Ä credit ors +Ä Sky walker +ov sky +Ä cease fire +Ä se als +is oft +) ). +Ä Fel ix +IT S +Ä t resp +Ä Block chain +ew are +Ä Sch war +en ne +mount ed +Ä Be acon +les h +Ä immense ly +Ä che ering +Em ploy +sc ene +ish ly +atche wan +Ä Nic olas +Ä dr ained +Ä Ex it +Ä Az erb +j un +Ä flo ated +u ania +De ep +Ä super v +Ä myst ical +Ä D ollar +Ä Apost le +Ä R EL +Ä Prov ided +Ä B ucks +ÃŖÄĨ ´ +cut ting +Ä enhance ments +Ä Pengu ins +Ä Isa iah +Ä j erk +Ä W yn +Ä st alled +Ä cryptoc urrencies +Ä R oland +sing le +Ä l umin +Ä F ellow +Ä Cap acity +Ä Kaz akh +W N +Ä fin anced +38 9 +Ä t id +Ä coll usion +Ä My r +ÃŽ Äĸ +Sen ator +Ä ped iatric +Ä neat ly +Ä sandwic hes +Ä Architect ure +Ä t ucked +Ä balcon y +Ä earthqu akes +qu ire +F uture +Ä he fty +Ê Äš +Ä special izes +Ä stress es +Ä s ender +Ä misunder standing +Ä ep ile +Ä prov oke +Ä Col ors +Ä dis may +uk o +[ _ +58 6 +ne utral +Ä don ating +Ä Rand all +Mult i +Ä convenient ly +Ä S ung +Ä C oca +Ä t ents +Ä Ac celer +Ä part nered +27 2 +ir ming +Ä B AS +s ometimes +Ä object ed +ub ric +p osed +LC S +gr ass +Ä attribut able +V IS +Israel i +Ä repe ats +Ä R M +v ag +ut a +in ous +Ä in ert +Ä Mig uel +ÃĻ Åƒ +Ä Hawai ian +B oard +Ä art ific +Ä Azerb ai +as io +Ä R ent +A IN +Ä appl iances +Ä national ity +Ä ass hole +Ä N eb +Ä not ch +h ani +Ä Br ide +Av ailability +Ä intercept ed +Ä contin ental +Ä sw elling +Ä Pers pect +b ies +. < +ith metic +Ä L ara +Ä tempt ing +add r +Ä oversee ing +cl ad +Ä D V +Ä Ging rich +Ä m un +Ä App ropri +Ä alter ations +Ä Pat reon +Ä ha voc +Ä discipl ines +Ä notor iously +aku ya +ier i +? ). +Ä W ent +Ä sil icon +Ä tre mb +Cont ainer +K nown +Ä mort ar +est e +ick a +Ar thur +Ä Pre viously +Ä Mart y +Ä sp arse +g ins +Ä in ward +Ä Particip ant +C opy +Ä M isc +Ä antib iotic +Ä Ret ro +Ä el usive +Ä ass ail +Ä Batt alion +Ä B ought +Ä dimin ish +Ä Euro pa +s ession +Ä Danger ous +ies el +Ä disbel ief +Ä bl asts +ext reme +Ä Boy d +Ä Project s +Ä Gu ys +Ä under gone +Ä gr ill +Ä Dw ight +Ä 19 7 +US ER +Ä files ystem +Ä cl ocks +T aylor +Ä wra pper +Ä fold ing +ous and +Ä Philipp ine +ATION AL +Ä Per th +Ä as hes +Ä accum ulate +Ä Gate way +Sh op +orks hire +H an +Ä Bar rel +Ä Le h +Ä X V +Ä wh im +Ä rep o +Ä C G +Ä M am +Ä incorpor ating +Ä bail out +Ä lingu istic +Ä dis integ +C LE +Ä cinem atic +Ä F iber +S yn +il ion +Ä Com pos +c hens +Ä ne oc +Ä bo iled +F INE +on o +un cle +ik en +Ä B M +Î š +Ä receipt s +Ä disp osed +Ä Th irty +Ä R ough +Ä A BS +Ä not withstanding +oll en +# $ +Ä unrel iable +Ä bl oom +Ä medi ocre +Ä tr am +Ä Tas man +Ä sh akes +Ä manifest o +Ä M W +Ä satisf actory +Ä sh ores +Ä comput ation +Ä assert ions +orm ons +ar ag +ab it +Dem ocrats +Ä L oot +Ä Vol ks +ha ired +Ä grav itational +S ing +Ä M iz +Ä thro ttle +Ä tyr anny +Ä View s +Ä rob ber +Ä Minor ity +Ä sh rine +sc ope +pur pose +Ä nucle us +our cing +Ä US DA +Ä D HS +w ra +Ä Bow ie +Sc ale +Ä B EL +x i +I ter +Ä ( ), +w right +Ä sail ors +ous ed +NAS A +Ä Pro of +Ä Min eral +t oken +Ä F D +R ew +Ä e ll +6 30 +Ä chance llor +Ä G os +Ä amount ed +Ä Rec re +ome z +Ä Opt im +Ä Ol ive +Ä track er +ow ler +Ä Un ique +R oot +Ä mar itime +Ä Qur an +Ä Ad apt +Ä ecosystem s +Ä Re peat +Ä S oy +Ä I MP +Ä grad uating +and em +P ur +Ä Res et +Ä Tr ick +Ä Ph illy +Ä T ue +Ä Malays ian +Ä clim ax +Ä b ury +Ä cons pic +Ä South ampton +Ä Fl owers +Ä esc orted +Ä Educ ational +Ä I RC +Ä brut ally +e ating +Ä pill ar +Ä S ang +Ä J ude +ar ling +Ä Am nesty +Ä rem inding +Ä Administ rative +hes da +Ä fl ashed +Ä P BS +per ate +fe ature +Ä sw ipe +Ä gra ves +oult ry +26 1 +bre aks +Ä Gu er +Ä sh rimp +Ä V oting +qu ist +Ä analy tical +Ä tables poons +Ä S OU +Ä resear ched +Ä disrupt ed +Ä j our +Ä repl ica +Ä cart oons +b ians +} ) +c opy +G ot +ou ched +P UT +Ä sw arm +not ations +s aid +Ä reb uilt +Ä collabor ate +Ä r aging +Ä n ar +Ä dem ographics +Ä D DR +Ä dist rust +oss ier +Ä K ro +Ä pump kin +Ä reg rets +Ä fatal ities +Ä L ens +Ä O le +p d +Ä pupp et +Ä Out look +Ä St am +O l +F air +U U +Ä re written +Ä Âą +Ä fasc inated +Ä ve ctors +Ä trib unal +u ay +Ä M ats +Ä Co ins +[ [ +Ä 18 1 +Ä rend ers +Ä K aepernick +Ä esp ionage +Ä sum m +Ä d itch +Acc ount +Ä spread sheet +Ä mut ant +p ast +40 7 +Ä d ye +Ä init iation +Ä 4 000 +Ä punish able +Ä th inner +Ä Kh al +Ä inter medi +D un +Ä Goth am +Ä eager ly +Ä vag inal +p owers +V W +Ä WATCH ED +Ä pred ator +ams ung +Ä dispar ity +Ä [ * +Ä am ph +Ä out skirts +Ä Spir its +Ä skelet al +Ð Âģ +Ä R ear +Ä issu ance +Ä Log ic +re leased +Z Z +Ä B ound +Ent ry +Ä ex its +is ol +Ä Found er +Ä w re +Ä Green land +Ä M MO +t aker +IN C +ÃŖÄŖ ž +Ä hour ly +hen ko +Ä fantas ies +Ä dis ob +Ä demol ition +ÃŖÄĨ Ä­ +Ä en listed +rat ulations +Ä mis guided +Ä ens ured +Ä discour aged +m ort +Ä fl ank +Ä c ess +Ä react s +Ä S ere +s ensitive +Ä Ser pent +ass ad +Ä 24 7 +Ä calm ly +b usters +Ä ble ed +Ä St ro +Ä amuse ment +Ä Antar ctica +Ä s cept +Ä G aw +a q +ason ic +Ä sp rawling +n ative +atur ated +Ä Battle field +IV ERS +E B +Ä G ems +Ä North western +Ä Fil ms +Ä Aut omatic +Ä appre hend +ÃŖÄŖ ¨ +Ä gui Name +Ä back end +Ä evid enced +ge ant +01 2 +Ä S iege +Ä external To +Ä unfocused Range +Ä guiActiveUn focused +Ä gui Icon +Ä externalTo EVA +Ä externalToEVA Only +F ri +ch ard +en aries +Ä chief s +Ä c f +Ä H UD +Ä corro bor +Ä d B +Ä T aken +Ä Pat ricia +ra il +Ä Ch arm +Ä Liber tarian +rie ve +Person al +Ä O UR +ger ies +Ä dump ing +Ä neurolog ical +it imate +Ä Clint ons +raft ed +Ä M olly +Ä termin als +reg ister +Ä fl are +Ä enc oded +Ä autop sy +p el +m achine +Ä exempt ions +Ä Roy als +d istance +Ä draft s +Ä l ame +Ä C unning +Ä sp ouses +Ä Mark ets +Ä Car rier +Ä imp lying +Ä Y ak +s id +Ä l oser +Ä vigil ant +Ä impe achment +Ä aug mented +Ä Employ ees +Ä unint ended +tern ally +Ä W att +Ä recogn izable +ess im +ÃĻ Äŋ +Ä co ated +r ha +Ä lie utenant +Ä Legisl ation +pub lished +44 4 +01 3 +Ä ide ally +Ä Pass word +Ä simpl ify +Ä Met a +Ä M RI +Ä ple ading +organ ized +hand ler +Ä un ravel +cor rect +Ä  icy +Ä paran oid +Ä pass er +Ä inspect ions +of er +Ä Health care +28 3 +Ä Br ut +iol a +for ge +Ä Med ieval +MS N +ie vers +Ä Program ming +ÃĨ ÄĢ +Ä 2 23 +m u +Ä C LE +ug a +Ä sho ppers +Ä inform ative +Ä Pl ans +Ä supplement ation +Ä T ests +ty ard +ocy tes +Ä Veg a +Ä Gujar at +erman ent +Ex cept +Ä L OT +all a +Ä C umm +Ä O sw +Ä ven om +Ä Deb t +Ä D OWN +Ä reun ion +Ä m uc +Ä Rel ief +Ä ge op +ĠðŁ Äē +al ogue +An th +ech o +Ä cor ros +Ä repl ication +Ä Bl azing +Ä D aughter +Ä inf lic +Ä Lind sey +Ù ÄĒ +28 4 +Ex it +Ä gl oom +TA IN +Ä undermin ing +Ä adv ising +h idden +Ä over flow +Ä g or +urd ue +Ä e choes +enh agen +Ä imp uls +d rug +c ash +Ä as ync +Ä mir ac +at ts +p unk +Ä piv ot +Ä Legisl ative +Ä blog gers +Ä Cl aw +s burg +d yl +Ä Recomm end +Ä ver te +Ä prohib iting +Ä Pant her +Jon athan +Ä o min +Ä hate ful +28 1 +Ä Or che +Ä Murd och +down s +Ä as ymm +G ER +Al ways +Ä inform s +Ä W M +Ä P ony +Ä App endix +Ä Ar lington +J am +Ä medic inal +Ä S lam +IT IES +Ä re aff +Ä R i +F G +S pring +b ool +Ä thigh s +Ä mark ings +Ä Ra qqa +Ä L ak +p oll +ts ky +Ä Mort y +Ä Def inition +Ä deb unk +end ered +Ä Le one +a vers +Ä mortg ages +App arently +N ic +ha us +Ä Th ousands +au ld +Ä m ash +sh oot +Ä di arr +Ä conscious ly +H ero +e as +Ä N aturally +Ä Destroy er +Ä dash board +serv ices +R og +Ä millenn ials +Ä inv ade +- ( +Ä comm issions +Ä A uckland +Ä broadcast s +Ä front al +Ä cr ank +Ä Hist oric +Ä rum ours +CT V +Ä ster il +Ä boost er +rock et +ÃŖÄ¤ Âŧ +ut sche +Ä P I +Ä 2 33 +Ä Produ cer +Ä Analy tics +Ä inval uable +Ä unint ention +Ä C Y +Ä scrut in +Ä g igg +Ä eng ulf +Ä prolet ariat +Ä h acks +Ä H ew +ar ak +Ä Sl ime +ield ing +ag her +Ä Ell iot +Ä tele com +Ä 2 19 +ult an +Ä Ar bor +Ä Sc outs +B an +Ä lifes pan +Ä bl asp +38 8 +Ä jud iciary +Ä Contin ental +ask ing +Mc C +L ED +Ä bag gage +Ä Sorce rer +Ä rem nants +Ä Griff ith +ets u +Ä Sub aru +Ä Person ality +des igned +ush ima +agn ar +Ä rec oil +Ä pass ions +\ ": +Ä te e +Ä abol ition +Ä Creat ing +j ac +Ä 19 4 +01 9 +Ä pill ars +ric hed +/ " +t k +Ä live lihood +Ä ro asted +ah on +Ä H utch +ass ert +Ä divid end +Ä kn it +Ä d aunting +Ä disturb ance +Ä sh ale +Ä cultiv ated +Ä refriger ator +L B +Ä N ET +Ä commercial s +Ä think ers +45 5 +Ä ch op +B road +Ä suspic ions +Ä tag ged +l ifting +Ä sty lish +Ä Shield s +Short ly +Ä t ails +A uth +ST E +Ä G AME +Ä se ism +Ä K is +olog ne +Ä cow ork +Ä forc ibly +Ä thy roid +Ä P B +AN E +mar ried +h orse +Ä poly mer +Ä Ch al +od or +DE BUG +Ä Con text +Ä bl iss +Ä pin point +Ä Mat hemat +leg ram +Ä Week end +Ä lab elled +Ä b art +it les +Ä est rogen +ÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļ ÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļÃĸÄĸÄļ +" ' +Ä vis ibly +Ä outs ider +aid a +Are a +Ä disse min +Ä dish onest +Ä Cl osed +Ä Bullet in +Ä Ram sey +sw ord +Ä X I +our ced +S ame +34 6 +Ä Re pe +Ä K ou +c ake +em is +C ache +Ä Me aning +Ä En light +onom y +Ä manifest ation +sw orth +J ay +Ä ch ore +ÃÂļ r +D ream +Ä sanction ed +Ä cult urally +Ä A ra +N av +Ä the ological +Ä str ut +Ä V O +Ä Hand book +Ä construct ing +Ġ Âļ +Ä Benef its +Ä Psych ological +s ac +ÃĨ ¸ +p olicy +Ä Mat ters +Ä Report ed +Ä By te +Ä vit ro +Ä M aiden +Ä l am +Ä Jenn ings +Ä gar ment +Ä Rut gers +Ä Staff ord +Ä Well ington +Ä inter mitt +Ä n pm +Ä ord eal +Ä plug ged +o oming +in ished +fram ework +Ä tim ber +Ä c ass +Ä 8 50 +il ess +Ä Red ux +7 68 +St re +Ä surpass ed +w hel +Ä paralle ls +Ä ve il +Ä G I +Ä R EST +Ä read iness +s ort +Ä mod ifying +Ä Sl ate +ru ff +Ä mar ble +Ä inf rared +Ä aud itor +Ä FANT ASY +Ä P overty +Ä S PD +Ä " ( +K y +RA Y +Ä execut ions +Ä Bever ly +Ä Marx ism +Ä Bur st +Ä K ali +est ones +Clear ly +E ll +ÃŖÄŖ § +Ä Proceed ings +T oken +IF IC +ÃƒÂą a +Cent ral +Ä H aley +Ä D rama +Ä form ations +OR N +Book s +Ä dom inating +Ä Fly ers +Ä Compan ion +Ä discipl ined +Ä Yug oslav +Ä Spell s +Ä v engeance +Ä land lords +L en +Ä O gre +ano ia +Ä pier cing +Ä con greg +Ä score r +ob ia +Ä nic kel +Ä Lear ns +Ä re jo +Ä master piece +Fl ash +Ä inhab ited +Ä Open GL +Ä D ud +Ä I CO +Ä ar ter +Ä pl ur +Ä master y +Ä long standing +st ed +Ä w ines +Ä telev ised +Ä Sh rine +Ä Bay ern +Ä Ãĸ ÄĩÄē +Ä encl osure +j ohn +Ä prophe ts +Ä Res urrection +Ä Ord ers +Ä un even +r als +Ä d wind +Ä L ah +Ä Sl oven +37 8 +Ä ins istence +aff le +Ä Cl one +Ä hard ship +Ä Congress man +Ä ple ad +Ä review ers +Ä c ured +Ä 19 35 +as ley +f ake +Ä Th inking +yd ia +P ART +Ä D ota +o it +Ä wh ipped +Ä b ouncing +Ä Hispan ics +com ings +Ä cann abin +Ä Ch ambers +Ä Z ack +Option al +Ä co ats +Ä prow ess +Ä Nort on +Ä plain ly +Ä fre ight +Ä inhib ition +Ä cl am +Ä 30 3 +ke f +ale igh +L uke +Ä psych o +ator ium +M ED +Ä treat ies +Ä ind isc +Ä d c +OP S +Ä resil ient +Ä Inter state +Ä sl ack +Ä mund ane +Ä estab lishes +35 9 +Ä str ained +Ä n ond +S us +Ä cast e +ar ate +ie ving +Ä unfair ly +Ä pars er +on ial +urs ive +V ia +Ä Ott o +Ä Author ities +stro ke +K R +Ä Mer cy +Ä furn ished +Ä out set +Ä met ic +19 82 +olith ic +Ä T ent +og ical +Ä A ircraft +Ä h ides +Ä Bec ame +Ä educ ators +re aching +Ä vol atility +Ä todd ler +Ä NAS CAR +Ä Tw elve +Ä High lights +Ä gra pe +Ä spl its +Ä pe asant +Ä re neg +Ä MS I +Tem p +st ars +Ä tre k +Ä Hy de +b inding +Ä real ism +Ä ox ide +Ä H os +Ä mount s +Ä bit ing +Ä collaps ing +Ä post al +Ä muse ums +Ä det ached +Ä respect ing +Ä monop ol +Ä work flow +Ä C ake +Tem plate +Ä Organ isation +Ä pers istence +36 9 +C oming +B rad +Ä redund ant +Ä G TA +Ä b ending +Ä rev oked +Ä off ending +Ä fram ing +Ä print f +Comm un +mem bers +Out side +Ä const rued +Ä c oded +F ORE +Ä ch ast +Ch at +Ind ian +Ä Y ard +? !" +Ä P orts +Ä X avier +Ä R ET +' ." +Ä Bo at +iv ated +ich t +umer able +D s +Ä Dun n +Ä coff in +Ä secure ly +Ä Rapt ors +Ä B es +Install ation +Ä in ception +Ä Health y +end ants +Ä psych ologists +Ä She ikh +c ultural +Ä Black Berry +sh ift +F red +oc he +Ä c akes +Ä S EO +Ä G ian +Ä As ians +og ging +e lement +Ä pund its +Ä V augh +Ä G avin +Ä h itter +Ä drown ed +Ä ch alk +Ä Z ika +Ä meas les +80 2 +ÃĸÄĸÂĻ .. +Ä AW S +] " +Ä dist ort +Ä M ast +Ä antib odies +Ä M ash +Mem ory +Ä Ug anda +Ä Pro b +Ä vom iting +Ä Turn s +Ä occup ying +Ä ev asion +Ä Ther apy +Ä prom o +Ä elect r +Ä blue print +Ä D re +pr iced +Ä Dep ot +Ä allev iate +Ä Som ali +m arg +n ine +Ä nostalg ia +Ä She pherd +Ä caval ry +Ä tor ped +Ä Blood y +x b +Ä s ank +Ä go alt +report print +embed reportprint +clone embedreportprint +Ä In itially +Ä F ischer +Ä not eworthy +c ern +Ä in efficient +raw download +rawdownload cloneembedreportprint +c ation +Ä D ynasty +l ag +D ES +Ä distinct ly +Ä Eston ia +Ä open ness +Ä g ossip +ru ck +W idth +Ä Ib rahim +Ä pet roleum +Ä av atar +Ä H ed +ath a +Ä Hog warts +Ä c aves +67 8 +Ä safegu ard +Ä M og +iss on +Ä Dur ham +sl aught +Ä Grad uate +Ä sub conscious +Ä Ex cellent +Ä D um +---- - +Ä p iles +Ä W ORK +Ä G arn +Ä F ol +Ä AT M +Ä avoid s +Ä T ul +Ä ble ak +EL Y +iv ist +light ly +P ers +Ä D ob +Ä L S +Ä ins anity +Î Âĩ +atal ie +En large +Ä tw ists +Ä fault y +Ä pir acy +Ä imp over +Ä rug ged +Ä F ashion +Ä s ands +' ? +sw ick +Ä n atives +Ä he n +Ä No ise +ÃŖÄĨ Äš +Ä g reens +Ä free zer +Ä d ynasty +Ä Father s +Ä New ark +Ä archae ological +Ä o t +ob ar +Ä block ade +Ä all erg +L V +Ä deb it +Ä R FC +Ä Mil ton +Ä Press ure +Ä will ingly +Ä disproportion ate +Ä opp ressive +Ä diamond s +Ä belong ings +19 70 +Ä bell s +Ä imperial ism +Ä 2 27 +Ä expl oding +Ä E clipse +Ä 19 19 +Ä r ant +Ä nom inations +34 7 +Ä peace fully +ric a +Ä F UCK +Ä vib ration +mal ink +Ä ro pes +Ä Iv anka +Ä Brew ery +Ä Book er +Ä Ow ens +go ers +Serv ices +Ä Sn ape +Ä 19 1 +39 5 +Ä 2 99 +just ice +Ä b ri +Ä disc s +Ä prom inently +Ä vul gar +Ä sk ipping +l ves +Ä tsun ami +37 4 +Ä U rug +Ä E id +rec ated +p hen +Ä fault s +Ä Start ed +9 50 +Ä p i +Ä detect or +Ä bast ard +Ä valid ated +Space Engineers +OUR CE +Ä ( ~ +Ä uns ur +Ä aff irmed +Ä fasc ism +Ä res olving +Ä Ch avez +Ä C yn +Ä det ract +L ost +Ä rig ged +Ä hom age +Ä Brun o +55 5 +ec a +Ä press es +Ä hum our +Ä sp acing +Ä ' / +olk ien +C oun +OP ER +T re +S on +Ä Cambod ia +ier re +m ong +o zy +Ä liquid ity +Ä Sov iets +Ä Fernand o +Ä 2 29 +Ä sl ug +Ä Catal an +elect ric +Ä sc enery +Ä H earth +Ä const rained +Ä goal ie +Ä Gu idelines +Ä Am mo +Ä Pear son +Ä tax ed +Ä fet us +Resp onse +Ä Alex is +th ia +G uy +Ä recon struct +Ä extrem es +Ä conclud ing +Ä P eg +ook s +Ä ded uctions +R ose +Ä ground breaking +Ä T arg +ÃŖÄĨ ÄŖ +Ä Re ve +res ource +Ä mo ons +Ä electrom agnetic +Ä amid st +Ä Vik tor +N ESS +B ACK +Ä comm ute +Ä Ana heim +Ä fluct uations +6 40 +Ä nood les +Ä Cop enhagen +Ä T ide +Ä Gri zz +Ä S EE +Ä pip elines +Ä sc ars +end o +ag us +Ä E TF +/ # +Ä Bec ome +44 8 +Ä vis c +Ä Recomm ended +Ä j umper +Ä cogn ition +Ä assass in +Ä witness ing +Ä Set up +Ä l ac +v im +IS M +p ages +SS L +35 8 +Ä ad ject +indust rial +l ore +cher y +Ä gl itter +Ä c alf +Flor ida +Ä spoil ers +Ä succeed s +Ä ch anting +Ä slog ans +Ä Tr acy +Vis it +rol ogy +Ä m ornings +Ä line age +Ä s ip +Ä intense ly +Ä flour ish +Ä Sle eping +Ä F em +or por +Ä K lan +Ä Dar th +h ack +Ä Ni elsen +Ä tum ors +Ä procure ment +Ä Y orkshire +Ä ra ided +K Y +An na +Ä // [ +Ä Dis order +Ä Must ang +Ä W en +Ä Try ing +s q +Ä deliver ies +Ä shut ter +Ä cere bral +Ä bip olar +Ä C N +l ass +j et +Ä deb ating +> : +Ä e agle +gr ades +Ä D ixon +UG C +M AS +Ä Dr aco +Ä Mach ines +aff er +Ä em an + ² +pr on +Ä G ym +Ä compar atively +Ä Trib unal +PR O +Ä le x +Ä fert ile +Ä dep ressing +Ä superf icial +ess ential +Ä Hun ters +g p +Ä prom inence +L iber +Ä An cest +ote chnology +Ä m ocking +Ä Tra ff +ĸ Äŧ +Med ium +I raq +Ä psychiat rist +Quant ity +Ä L ect +Ä no isy +5 20 +G Y +Ä sl apped +Ä M TV +Ä par a +p ull +Mult iple +as her +Ä n our +Ä Se g +Spe ll +v ous +ord ial +Sen ior +Ä Gold berg +Ä Pl asma +ne ed +Ä mess enger +ere t +Ä team ed +Ä liter acy +Ä Le ah +Ä D oyle +Ä em itted +U X +Ä ev ade +Ä m aze +Ä wrong ly +Ä L ars +Ä stere otype +Ä pled ges +Ä arom a +Ä M ET +Ä ac re +Ä O D +Ä f f +Ä brew eries +Ä H ilton +und le +Ä K ak +Ä Thank fully +Ä Can ucks +in ctions +Ä App ears +Ä co er +Ä undermin ed +ro vers +And re +Ä bl aze +um ers +Ä fam ine +amp hetamine +ulk an +Am ount +Ä desper ation +wik ipedia +develop ment +Ä Cor inth +uss ia +Jack son +L I +N ative +R s +Oh io +Ä Kath leen +F ortunately +Ä attend ant +Ä Pre ferred +Ä Did n +Ä V s +M is +Ä respond ent +Ä b oun +st able +Ä p aved +Ä unex pl +Ä Che ney +L M +Ä C ull +bl own +Ä confront ing +oc ese +serv ing +W i +Ä Lith uania +ann i +Ä st alk +h d +Ä v ener +AP H +ynchron ous +UR R +um ably +hist oric +H alf +H ay +Ä resil ience +spe ction +Ä abandon ing +O bs +Ä Deb bie +Ä grad ient +Ä Pl aint +Ä Can al +AR CH +Ä expans ive +Ä fun g +Ä b ounced +U nd +Ä prec autions +Ä clar ification +Ä d agger +Ä gri ps +Ġ Âĩ +Ä River a +Ä Und ead +is ites +Ä FIR ST +ÃƒÂą o +aud i +Ä host ages +Ä compl iant +Ä al umni +Se ven +Ä cyber security +e ither +Col lect +Ä invari ably +Ä S oci +Ä law maker +Ä a le +Ä Person ally +N azi +Ä custom ization +Ä Pro c +Ä Sask atchewan +eat uring +Ä sp ared +Ä discontin ued +Ä comput ational +Ä Motor ola +Ä suprem acist +government al +Ä parad ise +Ä Down ing +Ä Nik on +Ä cat alyst +ber ra +Tor onto +8 75 +bet a +Ä Mac ron +Ä unreal istic +ve ctor +Ä Veh icles +it iveness +Ä R V +Ä Col bert +s in +o ji +ent in +Ä Kr ish +hell o +ff ield +ok y +Ä T ate +Ä map le +Ä a ids +chem ical +33 4 +n uts +Ä War p +Ä x x +Ä Rob b +umer ous +_- _ +ft ime +Ä V W +Ä w inger +Ä D ome +t ools +Ä P V +Ä Ge orgetown +Ä g eared +Ä jihad ists +Ä c p +Ä ster oids +M other +cler osis +Ä DR M +nes ia +Ä l inger +Ä imm ersive +Ä C OUN +Ä outwe igh +ens ual +B and +Ä transform s +mat ched +ps ons +Ä Jud icial +f actor +Ä refer ral +Ä odd ly +Ä W enger +B ring +Ä B ows +60 2 +IC LE +Ä l ions +Ä Acad emic +Ä Th orn +Ä Ra ider +kef eller +St orage +L ower +Ä Or t +Ä Equ ality +AL T +Ä S OC +T ypes +Ä l yn +Ä Ass et +co at +TP P +C VE +Ä Pione er +app lication +Mod ern +Ä H K +En vironment +Al right +R ain +IP P +Ä Shi ite +Ä m ound +Ä Ab ilities +cond ition +St aff +Ä compet ence +Ä M oor +Ä Di ablo +Ä with held +Ä ost ensibly +Ä B rom +Ä ms g +Ä den omin +Ä Ref erences +Ä F P +Ä plun ged +Ä p amph +m oving +cent ral +Ä down right +Ä f ading +T al +T yp +Ä Th y +uk es +it he +Ä o ve +Ä batt led +Ä seaf ood +Ä fig ur +Ä R D +c rop +Ä squ ads +{ \ +à š +Ä E h +Ä interview ing +Ä Q in +Ä as piring +PL IC +Ä cla uses +Ä G ast +Ä N ir +Ä l uggage +Ä h ose +Ä system d +Ä desc ending +Ä Rev ised +Ä R ails +al ign +70 9 +33 7 +Ä f ug +charg ing +t ags +Ä ut er +k ish +WAR NING +49 0 +prof its +Ä voy age +Ä a ce +Ä V anguard +Ä T anks +Ä M uk +Ä 2 26 +S afe +Ar mor +Ä volcan ic +Ä wom b +Ä M IL +Ä begin ner +Ä Rec ogn +Ä A AP +PL AY +) ! +Ä detect ing +c n +Ä bre aches +Bas ically +Ä P ag +Ä Municip al +Ä Ind ie +Ä L af +Ä Dis able +Ä Ol son +Ä rest rained +Ä rul ings +Ä hum ane +ev ents +Ä Cinem a +display Text +Ä H atch +action Date +onna issance +Ä assault ing +Ä L ug +CH AT +Ä vig orous +Ä Per se +Ä intoler ance +Ä Snap chat +Ä Sh arks +Ä d ummy +Ä Di agn +Ä Gu itar +im eters +40 3 +RE G +A x +Ä separ ates +Ä Mah m +Ä t v +j ah +O OL +C irc +Ä Winds or +uss ian +Ä intu ition +Ä dis dain +Ä Don ovan +Ä 2 21 +E mb +Ä condem ning +Ä gener osity +zz y +Ä pant ies +Ä Pre vent +Action Code +AN A +34 2 +external ActionCode +Ä spec ifying +Ä cryst all +J ere +Ä ru pt +Ä App rentice +Ä prof iling +Ð Âē +St rike +Ä sid eline +Ä oblig ated +Ä occ ult +Ä bureaucr atic +ant ically +rupt ed +neg ative +Ä Ethiop ia +Ä C ivic +Ä ins iders +el igible +Ä TV s +Ä B AR +Ä T I +i ologist +Ä A IR +Ä substit uted +Ar ab +Ä S aul +Ä Y og +p rem +Ä build ers +Ä station ary +Ä doubt ful +Ä vig orously +Ä thr illing +Ph ysical +Ä Care y +Ä Hyd ra +geon ing +Ä S ly +y ton +Ä borrow ers +Ä Park inson +Ä  ÃĢ +Ä Jama ica +Ä sat ir +Ä insurg ents +Ä F irm +Ä is ot +Ä K arn +our ning +ak ens +doc s +l ittle +Ä Mon aco +CL ASS +Tur key +L y +Ä Con an +ass ic +Ä star red +Ä Pac ers +et ies +Ä t ipping +M oon +Ä R w +s ame +Ä cav ity +Ä go of +Ä Z o +Sh ock +um mer +Ä emphas izes +Ä reg rett +Ä novel ty +Ä en vy +Ä Pass ive +r w +50 5 +Ä ind ifferent +Ä R ica +Ä Him self +Ä Fred die +Ä ad ip +ä¸ Äĸ +Ä break out +Ä hur ried +Ä Hu ang +Ä D isk +Ä ro aming +?????- ?????- +U V +Ä Rick y +Ä S igma +Ä marginal ized +Ä ed its +Ä 30 4 +mem ory +Ä spec imen +29 3 +ÃŖÄŖ ¯ +Ä vert ically +Ä aud ition +Ä He ck +Ä c aster +Ä Hold ings +ad al +Ä C ron +Ä L iam +Ä def lect +P ick +Ä Deb ug +RE F +Ä vers atility +ot hes +class ified +Ä Mah ar +Ä H ort +C ounter +st asy +not iced +33 1 +Ä Sh im +f uck +Ä B ie +Ä air ing +Ä Pro tein +Ä Hold ing +Ä spect ators +ili ated +Ä That cher +n osis +ÃŖÄĨÂŧ ÃŖÄĨÂŗ +Te le +B oston +Ä Tem pl +st ay +Ä decl arations +47 9 +Vol ume +Ä Design er +Ä Over watch +id ae +Ä on wards +Ä n ets +Ä Man ila +part icularly +Ä polit ic +o other +Ä port raits +Ä pave ment +c ffff +Ä s aints +Ä begin ners +ES PN +Ä short comings +ÃĸġIJ ÃĸġIJ +Ä com et +Ä Organ ic +qu el +Ä hospital ized +Bre ak +Ä pe el +dyl ib +asp x +ur ances +Ä T IM +P g +Ä read able +Ä Mal ik +Ä m uzzle +Ä bench marks +d al +Ä V acc +Ä H icks +60 9 +Ä B iblical +he ng +Ä over load +Ä Civil ization +Ä imm oral +Ä f ries +ÃŖÄ¤ Ä´ +Ä reprodu ced +Ä form ulation +j ug +ire z +g ear +Ä co ached +Mp Server +Ä S J +Ä K w +In it +d eal +Ä O ro +Ä L oki +Ä Song s +Ä 23 2 +Ä Lou ise +asion ally +Ä unc ond +olly wood +Ä progress ives +Ä En ough +Ä Do e +Ä wreck age +Ä br ushed +Ä Base Type +Ä z oning +ish able +het ically +Ä C aucus +Ä H ue +Ä k arma +Ä Sport ing +Ä trad er +Ä seem ing +Ä Capt ure +4 30 +b ish +Ä t unes +Ä indo ors +Ä Sp here +Ä D ancing +TER N +Ä no b +Ä G ST +m aps +Ä pe ppers +F it +Ä overse es +Ä Rabb i +Ä R uler +vert ising +off ice +xx x +Ä ra ft +Ch anged +Ä text books +L inks +Ä O mn +ÃŖÄĸ Äŗ +Ä inconven ience +Ä Don etsk += ~ +Ä implicit ly +Ä boost s +Ä B ones +Ä Bo om +Cour tesy +Ä sens ational +AN Y +Ä gre edy +ed en +Ä inex per +Ä L er +Ä V ale +Ä tight en +Ä E AR +Ä N um +Ä ancest or +S ent +Ä H orde +urg ical +all ah +Ä sa p +amb a +Ä Sp read +tw itch +Ä grand son +Ä fract ure +Ä moder ator +Ä Se venth +Ä Re verse +Ä estim ation +Cho ose +Ä par ach +Ä bar ric +ÃŖÄĸ IJ +Ä comp ass +Ä all ergic +ÃĸÄĸ ġ +OT HER +err illa +Ä w agon +Ä z inc +Ä rub bed +Ä Full er +Ä Luxem bourg +Ä Hoo ver +Ä li ar +Ä Even ing +Ä Cob b +est eem +Ä select or +Ä B rawl +is ance +Ä E k +Ä tro op +Ä g uts +Ä App eal +Ä Tibet an +Ä rout ines +Ä M ent +Ä summar ized +steam apps +Ä tr anqu +Ä 19 29 +or an +Ä Aut hent +Ä g maxwell +Ä appre hens +Ä po ems +Ä sa usage +Ä Web ster +ur us +Ä them ed +Ä l ounge +Ä charg er +Sp oiler +Ä sp illed +h og +Ä Su nder +Ä A in +Ä Ang ry +Ä dis qual +Ä Frequ ency +Ä Ether net +Ä hel per +Per cent +Ä horr ifying +Ä a il +Ä All an +EE E +Ä Cross ing +44 9 +Ä h olog +Ä Puzz les +Ä Go es +eren n +60 4 +ÃŖÄŖ Äą +Ä Raf ael +Ä att en +Ä E manuel +Ä up ro +Ä Sus p +P sych +Ä Tr ainer +Ä N ES +Ä Hun ts +bec ue +Ä counsel or +R ule +Ä tox ins +Ä b anners +r ifice +Ä greet ing +Ä fren zy +Ä all ocate +Ä * ) +ex pr +50 3 +Ä Ch ick +Ä T orn +Ä consolid ation +Ä F letcher +sw itch +fr ac +cl ips +Ä McK in +Ä Lun ar +Mon th +IT CH +Ä scholar ly +rap ed +39 8 +Ä 19 10 +Ä e greg +Ä in secure +Ä vict orious +cffff cc +Ä sing led +Ä el ves +Ä W ond +bur st +Ä cam oufl +Ä BL ACK +Ä condition ed +ç ÄĢ +ans wered +Ä compuls ory +asc ist +Ä podcast s +Ä Frank furt +bn b +Ä ne oliberal +Ä Key board +Ä Bel le +w arm +Ä trust s +Ä ins ured +Ä Bu cc +us able +60 7 +Ä Pl ains +Ä 18 90 +Ä sabot age +Ä lod ged +f elt +Ä g a +Ä N arc +Ä Sal em +Ä sevent y +Ä Bl ank +p ocket +Ä whis per +Ä m ating +om ics +Ä Sal man +Ä K ad +Ä an gered +Ä coll isions +Ä extraord inarily +Ä coerc ion +G host +b irds +è Äĸ +k ok +Ä per missible +avor able +Ä po inters +Ä diss ip +ac i +Ä theat rical +Ä Cos mic +Ä forget ting +Ä final ized +ÃĨ¤ § +y out +l ibrary +Ä bo oming +Ä Bel ieve +Ä Te acher +Ä L iv +Ä GOOD MAN +Ä Domin ican +OR ED +Ä Part ies +Ä precip itation +Ä Sl ot +R oy +Ä Comb ined +Ä integ rating +Ä ch rome +Ä intest inal +Ä Re bell +Ä match ups +Ä block buster +Ä Lore n +Ä Le vy +Ä pre aching +Ä S ending +Ä Pur pose +ra x +f if +Ä author itative +Ä P ET +ast ical +Ä dish on +Ä chat ting +Ä "$ :/ +Connect ion +Ä recre ate +Ä del inqu +Ä bro th +Ä D irty +Ä Ad min +z man +Ä scholars hips +Ä 25 3 +cont act +als a +7 67 +c reen +abb age +Ä 19 15 +Ä bl ended +Ä al armed +L anguage +35 6 +Ä bl ends +Ä Ch anged +W olf +Ä he pat +Creat ing +Ä per secut +Ä sweet ness +art e +Ä forfe iture +Ä Rober to +im pro +N FL +Ä Mag net +Det ailed +Ä insign ificant +Ä POL IT +Ä BB Q +Ä C PS +Ä se aw +amin er +m L +end if +f inals +Ä 26 5 +u ish +Ä } ) +Ä Pro blems +Ä em blem +Ä serious ness +Ä pars ing +Ä subst itution +Ä press ured +Ä recy cled +ale b +Rub y +Ä prof iciency +Dri ver +Ä W ester +: ' +AF TA +Ä m antle +Ä Clay ton +fl ag +Ä practition er +c overed +Ä St ruct +add afi +4 25 +Ä Town ship +Ä Hyd ro +Lou is +34 3 +Ä cond o +Ä T ao +Ä util ization +Ä nause a +Ä Dem s +rid ges +p ause +Ä form ulas +Ä chall enger +37 6 +Ä defect ive +Ä Rail way +Ä Pub Med +Ä yog urt +l bs +Ä Nor folk +OP E +Ä Mood y +Ä distribut or +Ä scroll s +Ä extract s +St an +Ä v iability +Ä exp oses +Ä star vation +Ä Step s +Ä D odd +f ew +ST D +33 2 +Ä clos ures +Ä complement ary +Ä S asha +ump y +Ä mon et +Ä artic ulate +Ä Do ct +k iller +Ä sc rim +Ä 2 64 +Ä prost itutes +Ä se vered +Ä attach ments +Ä cool ed +L ev +Ä F alk +f ail +Ä polic eman +Ä D ag +Ä pray ed +Ä K ernel +Ä cl ut +Ä c ath +Ä an omaly +St orm +em aker +Ä Break fast +ul i +o ire +J J +h z +Oper ation +Ä S ick +35 4 +Ä Guatem ala +R ate +Ä exp osures +f aces +Ä Arch ae +ra f +Ä M ia +Ä 20 25 +Ä op aque +Ä disgu ised +Ä Head quarters +S ah +Ä p ots +9 78 +Ä M alf +Ä frown ed +Ä poison ous +Ä Con vers +ee ks +Ä cr ab +." " +Ä tre ason +Ä r anc +Ä escal ating +Ä war r +Ä mob s +Ä l amps +Ä Sun shine +Ä Brun swick +Ph ones +Ä spe lled +Ä Sk ip +Ä 20 50 +Ä 19 11 +Ä Pl uto +Ä Am end +Ä me ats +38 7 +Ä st omp +Ä Zh ou +Ä Levi athan +Ä Haz ard +ad v +Ä Or well +Ä al oud +Ä b umper +Ä An arch +ub untu +Ä Ser ious +f itting +Ä Option al +Ä Cec il +RE AM +Ä ser otonin +Ä cultiv ate +ag ogue +} \ +Ä mos ques +Ä Sun ny +Ä re active +rev olution +Ä L up +Ä Fed ora +Ä defense man +Ä V ID +ist ine +Ä drown ing +Ä Broad casting +Ä thr iller +Ä S cy +Ä acceler ating +Ä direct s +od ied +b ike +d uration +Ä pain fully +R edd +Ä product ions +Ä g ag +Ä wh ist +Ä s ock +Ä inf initely +Ä Conc ern +Ä Cit adel +Ä lie u +Ä cand les +ogene ous +arg er +Ä heaven ly +inflamm atory +Per formance +C s +ruct ose +az aki +Ä p essim +Ä inf erence +Ä pow d +Ä Z oe +Ä pain ts +Ä d azz +pt a +-------- --- +Ä ins pir +Ä Exper imental +Ä Kn ife +reg or +b ors +Ä show ers +rom eda +Ä s aint +Ä ben ign +Ä J iang +Ä envision ed +Ä sh roud +IF T +H O +Ä sh uff +Ä I CC +Ä se greg +Ä revis it +ighth ouse +L i +Ä sub strate +Ä Se as +Ä Rew ard +Ä H ep +Ä Br ass +s bm +Ä elim inates +Ä st amina +Ä V AT +Ä Lo an +Ä const raint +Ä appropri ated +Ä p es +Ä A LE +r anging +Ä 40 4 +39 2 +Ä intellectual s +ach u +Ä restruct uring +Ä Le vin +Ä run es +Ä delight ful +Ä carbohyd rates +Ä Mod els +Ä Exp o +Ä transport ing +all oc +Ä ring ing +S amsung +Ä scarce ly +Ä URL s +Ä M AS +Ä prot otypes +Ä narr ator +Ä CPU s +cd n +Ä Bart on +Ä decided ly +Ä Sh u +ix ir +oc ious +Ä My st +N intendo +Ä re use +Ä forg iven +F ew +in ical +n at +Ä seam less +Ä Ev a +Ä E VE +Ä J O +land ers +Ä so fter +neg ie +Ä trans ient +Ä orb ital +Ä fulf il +Ä K om +Hop efully +Ä dynam ically +Ä Hun ger +ÃĨ ÄŊ +Ä Armen ia +el man +ber to +Ä p ige +Ä ID s +lim it +Ä ve ins +Ä so aring +p acks +Gold en +Ä Cr ab +ist or +Ä R PM +Ä $ $ +g ression +Ä jihad ist +Ä gam ble +Ä care g +Ä inf lated +F ace +Ä Fire arms +Ä Em manuel +Ãĸ Äŋ +Ä sh ocks +gr ab +Ä spl end +Ä HP V +ab ortion +Ab ove +Ent ity +play ers +Ä comm enced +ul ence +Ä fulfill ment +Ä embod iments +Ä W elfare +Ä ha il +Ä < @ +tt en +Ä cat cher +Ä J azeera +Ä volcan o +Ä stabil ize +Ä Hand ler +Ä intens ified +Ä Ab rams +Ä hum iliation +p aced +60 5 +Ä Cent OS +Spe cific +Ä he ed +Ä C AM +Ä Gal ile +D ie +Ä abol ished +Ä Thom son +Ä Te achers +Ä W ass +j ong +Ä IS BN +Ä All ies +sh ake +ÃĨ ¡ +v ict +How ard +Ä de em +Ä exceed ingly +Ä Smart stocks +ib e +Ä door way +Ä compet ed +ig mat +Ä national ists +Ä g room +Ä Ke en +Ä dispos able +de cl +Ä T olkien +Ä Sche me +Ä b iod +Ä av id +Ä El on +ag ar +Ä T SA +R oman +Ä artific ially +Ä advis ors +X L +Ä Inf erno +36 6 +Ä ted ious +Ä Phot ography +Ä Car rie +Ä tro pe +Ä Sand ra +Ä dec imal +Que en +Ä Gund am +Ä O M +ote ch +N BA +Ä 19 32 +Ä ent renched +Ä Mar ion +Ä fr aternity +Lab our +Hen ry +Ä lat itude +E ither +Ä enh ances +Ä Pot ential +Ä sh ines +id ad +Ä bread th +Ä capac ities +ĠðŁ ÄģĤ +Ä Bron x +Ä sex es +Ä different iation +Ä heavy weight +Ä T aj +d ra +Ä migr ate +Ä exhaust ion +Ä R UN +els ius +Ä Cu omo +Ä gu itars +Ä cl ones +Ä Som ew +Ä P ry +------------ - +Ä warr anted +cy cles +Ä salv age +Ä dis ks +R ANT +Ä NGO s +Ä Mart ian +":[ {" +Ä add icts +oj ure +il let +Ä amazing ly +art ments +p ixel +Ä GPU s +Lay out +è ÂŖ +Ä Tam il +Ä Bas il +Ä impart ial +Ä St ructure +f ork +b ryce +Ä r idge +Ä Hamb urg +ri ous +Ä bl itz +cig arettes +Ä can ned +40 2 +Ä iron ically +Ä compassion ate +Ä Haw kins +. # +Ä Cat hedral +Ä rall ied +in ternal +Ä qu ota +st akes +T EXT +m om +Ä comple tes +Ä 23 8 +Ä sh rug +ÃŖÄĨ Äŗ +Ä N inth +Ä rev ise +Ä Prov ider +Ä tre acher +Ä qu asi +Ä PR ES +Ä dep osition +Ä confidential ity +iss ors +Ä im balance +Ä span ning +Ä ang ular +Ä C ul +commun ication +Ä Nor a +Ä Gen ius +op ter +Ä s acked +Sp ot +Ä fine ly +Ä CH R +28 2 +w aves +Pal est +Ä Ro hing +N L +è Âŋ +Ä sh itty +Ä Sc alia +4 75 +Pro gress +Ä referen cing +Ä class rooms +ab ee +Ä s od +hes ion +70 8 +Ä Zucker berg +Ä Fin ish +Ä Scot ia +Ä Sav ior +Ä Install ation +an tha +( - +Ä 30 2 +Ä P unk +Ä cr ater +yout u +Ä ro ast +Ä influ encing +Ä d up +Ä J R +Ä G rav +Ä stat ure +Ä bath rooms +A side +W iki +me an +Ä Z ak +Ä On es +Ä N ath +Ä hyper t +Ä commence ment +C ivil +Ä moder ately +Ä distribut ors +Ä breast feeding +Ä 9 80 +Ä S ik +Ä C ig +Ä AM ER +R IP +Ä Care er +ust ing +Ä mess ed +Ä e h +Ä J ensen +/ $ +Ä black mail +Ä convers ions +Ä scientific ally +Ä mant ra +p aying +Ä iv ory +Ä Cour ts +OU GH +aunt let +Ser ial +B row +Ä H undreds +3 23 +Ä pe e +Ä lin ux +Ä sub mer +Ä Princ ipal +48 5 +Ä D SL +Ä Cous ins +Ä doctr ines +Ä Athlet ics +Ä 3 15 +Ä K arma +Ä att ent +ur ger +Ä presc ribe +Ä enc aps +Ä C ame +Ä secret ive +Ä Cr imes +d n +C lean +Ä Egypt ians +Ä Car penter +Ä  ll +H um +Ä Mil o +Ä capital ists +Ä brief ed +T we +Ä Bas in +elve t +M os +Ä plun ge +Ä Ka iser +Ä Fu j +ill in +Ä safegu ards +Ä o ste +Ä Opportun ity +Ä M afia +Ä Call ing +ap a +ur ban +br ush +ill ard +c Ê +int elligence +Ä L ob +Ä Dru id +Ä sm oother +Ä foot ing +Ä motor ists +arc ity +Ä mascul inity +Ä m ism +Ä abdom inal +Ä Ta vern +Ä R oh +Ä esc apes +s igned +Anth ony +Ä sacrific ing +Ä intim acy +Ä an terior +Ä K od +Ä mot if +Ä g raz +Ä visual ization +Ä guitar ist +Ä Tro tsky +m agic +D ar +Ä Mor i +Ä w ards +Ä toile ts +l est +Ä tele port +Ä Sund ays +Ä Pl at +ET S +Ä e Sports +Pat rick +Ä K atherine +en ko +Ä has sle +Ä M ick +gg les +Ä h ob +aint ain +Ä air borne +Ä sp ans +Ä ch ili +Ä a perture +Ä volunte ered +Ä Inc ident +Ä F res +Ä Veter an +augh tered +ing o +Ä un insured +CL OSE +Ä f use +Ä er otic +Ä advert ise +ra ising +Text ure +Ä att ends +Ä RE AL +udd led +Ä sm oot +Ä 30 5 +Ä Will is +Ä bl ond +An alysis +Ä V T +on ica +Ä strongh old +R F +N M +. >> +Ä prosper ous +Ä bo asted +29 2 +Ä Manufact uring +PR ESS +g ren +Ä pharm acy +Ä Roc kefeller +k ai +Ä th umbs +Ä H ut +Ä mother board +Ä guard ians +Ä Al ter +ll ular +Ä sh ack +Ä wise ly +Ä back bone +erv a +Ä su icides +Ä McG regor +ij ah +E mer +Ä B rav +Ä design ate +P OST +produ ced +Ä cleans ing +irl wind +ex istent +Ä Hum ph +Ä Pay ne +Ä v ested +Å ÂĄ +Ä string ent +ion a +Ä uns ub +Ä sum med +Ä Her cules +sub ject +Ä R agnar +Ä N os +Ä character ization +Ä sav vy +Ä Daw son +Ä Cas ino +Ä f ri +Ä Bar rier +Ä mis information +Ä ins ulation +Ä corrid ors +Ä air planes +Ä No ct +ah i +Ä 19 16 +k b +arm ac +Ä sh un +Ä sche ma +Ä horr ified +Ä 23 9 +aund ers +N B +i ates +er ity +Ä Sh ard +Ä r arity +Ä group ed +Ä Gh ana +again st +Ä Bi ological +Ä A ware +ow ell +Ï ÄĻ +Ä Be au +sh aw +H ack +Ä Jul ius +US S +ol son +aun a +c ru +Ä Maur ice +Ä I k +Ä sequ encing +Ä radical s +Ä ( ?, +v irtual +Ä any ways +Ä reper c +Ä hand lers +Ä hes itant +Ê ÄĨ +Ä M F +ple mentation +ass ociated +Ä campaign ed +Ä Y ue +ut ations +Ä Y oga +Ä sim mer +Ä ro ds +Ä mel ody +Ä conv oy +v ideos +Ä screen ed +N eg +ochem ical +Ä ( )) +Ä ultr as +Ä ant ip +Ä Island ers +70 4 +Ä fet ish +Ä ridic ulously +Ä K art +Ä mitochond rial +Ä interf ering +Build er +Ä over fl +Ä ac ne +Ä M ud +Ä K err +f lex +Ä Post al +Ä Balt ic +47 7 +Ä Pers ons +our age +H B +Ä M use +Ä Imm ortal +Ä Dri ving +Ä pet itions +Ä subsc ript +Ä s orce +Ä Process or +ut on +S ony +Ä ph on +Ä r aced +Ä Anth rop +Ä day time +Ä Ex ercise +Add ing +Ä eng ages +Ä Qual comm +Ä mir acles +Ä mem es +Ä Dr ink +Ä Ori oles +Ä hair s +Ä Pol ar +ath om +Ä sl ippery +Ä R emy +Ä car amel +Ä Y EAR +Ä al k +I gn +a ution +Ä Mer lin +Ä C ran +Ä ap ologies +Ä 4 10 +Ä out ing +Ä Mem ories +app ointed +Ä count ered +u ld +pos ing +Ä fire wall +Ä W ast +Ä W et +work ed +se ller +Ä repe aled +ere o +ass uming +BL IC +m ite +Ä CEO s +Ä Chap el +ellig ent +________________ ________ +D og +Ä w art +Ä subsc riber +s ports +Ä be gged +Ä M V +Ä sem if +eth ical +Ä pre ach +Ä rev ital +Ä pun itive +Ä short cuts +Ä instit uted +Ä Wars aw +Ä abdom en +Ä K ING +Ä super intendent +Ä f ry +Ä Ge o +T OR +Ä contrad ictions +apt ic +Ä landsc apes +b ugs +Ä cl ust +Ä vol ley +c ribed +Ä t andem +Ä rob es +WH AT +Ä promot er +Ä el oqu +review ed +Ä D K +Ä Pl ato +Ä f ps +T ank +Ä Der rick +Ä priorit ize +as per +Ä Hond uras +Ä Com pleted +ne c +Ä m og +n ir +Ä May o +DE F +st all +in ness +Ä Volks wagen +Ä prec aution +Ä M ell +i ak +ist ries +Ä 24 8 +Ä overl apping +Sen ate +Ä Enh ance +res y +rac ial +OR TS +Ä M ormons +Str ong +Ä Co ch +Mex ico +Ä Mad uro +Ä j ars +Ä can e +W ik +oll a +iff erence +Ä physic ist +Ä Mag gie +Ä 28 5 +Ä dep iction +Ä McL aren +J u +Ä sl ows +Ä commission ers +Ä Will ow +Ä Expl os +hov ah +Ä techn ician +Ä hom icides +Ä Fl av +Ä Tr uman +Ä 100 00 +u ctor +Ä sh ader +News letter +45 7 +Ä re ver +Ä hard ened +Ä where abouts +Ä rede velop +Ä car bs +Ä tra vers +Ä squ irrel +Ä foll ower +Ä s ings +50 8 +Ä rabb its +emon ium +Ä document ing +Ä misunder stood +) ' +R ick +gg ies +Ä prem ie +Ä sk ating +Ä pass ports +Ä f ists +aged don +H aw +AC P +0 80 +Ä Though ts +Ä Carl son +Ä priest hood +h ua +Ä dun geons +Ä Lo ans +Ä ant is +Ä familiar ity +Ä S abb +op al +Ä In k +st rike +Ä c ram +Ä legal ized +Ä cu isine +Ä fib re +Tra vel +Ä Mon ument +OD Y +eth y +Ä inter state +Ä P UR +em porary +Ä Arab ian +develop ed +Ä sadd le +Ä g ithub +Ä Off er +Ä IS P +ro let +Ä SUP ER +Ä Den is +Ä multipl ier +Ä stir red +Interest ingly +Ä custom ary +Ä bill ed +he x +Ä multipl ied +Ä fl ipping +Ä Cros by +Ä fundament als +ia e +Ä Play ed +Ä At om +am azon +Ä Fl am +ee z +activ ated +Ä tables poon +Ä liberal ism +Ä Pal in +Ä P atel +N um +Ä T AM +Ä s urn +Ä Rel oaded +Ä co ined +" ], +Ä Cl ash +Ä Ag u +Ä prag matic +Ä Activ ate +Ä 8 02 +Ä trail ers +Ä sil hou +Ä prob es +Ä circ us +Ä B ain +Ä Lind say +Ä Ab bey +Del ivery +Ä concess ion +Ä gast ro +Ä Spr ite +Ä Ł +and el +Ä g imm +Ä aut obi +Ä T urtle +Ä wonder fully +Ä Har am +Ä World wide +Ä Hand le +Ä theor ists +Ä sle ek +Ä Zh u +ograph ically +EG A +Ä Own ers +ath s +Ä Antar ctic +n atal +=" " +fl ags +`` `` +Ä s ul +K h +Ä pot assium +Ä linem an +Ä cere al +Ä Se asons +Ä 20 22 +Ä mat hematic +Ä astron omers +prof essional +Ä f ares +cknow led +Ä ch i +Ä young sters +Ä mistaken ly +Ä hem isphere +Ä Div inity +r one +Ä " , +r ings +Ä attract s +v ana +ÃĨ š +C AP +Ä play list +Ä por ch +ÃŖÄŖ ÂŖ +Ä incorpor ates +Ä so ak +Ä assert ing +Ä Terror ism +Ä P ablo +J a +ces ter +Ä fear ing +Ä Pr ayer +Ä escal ated +G W +Ä ro be +Ä Bright on +ac ists +Ä Sym phony +Ä Dwar f +Ä Par ade +Ä Le go +Ä inex pl +Ä l ords +le af +RA G +l iber +Ä cig ars +Ä Je hovah +60 6 +WIND OWS +Ä Liber ia +eb us +He avy +Ä l ubric +Ä R W +angu ages +Ä narrow ed +com puter +Ä E mber +Ä murder ing +Ä down stream +Ä T uls +Ä T ables +Top ic +Ä Acc uracy += / +l ost +Ä Re i +Ä progress es +b ear +Ä establish ments +Just in +Ä Pe ach +Ä G omez +ÃĨ Âŋ +Ä Tri angle +Id ent +Ä H ive +Res ources +Ä mix es +Ä Ass uming +M u +Ä hyp oc +Ä s ane +Ä W an +id ious +Su ccess +Ä  io +Ang el +Ä danger ously +Ä Creat ure +W ORK +: [ +Ä Kat rina +List ener +M iller +Ä Id lib +h ang +Ä circum vent +h ref +Ä cel estial +Ä We eks +Ä P ug +Ä Dal ton +Ä subpoen a +uk u +Ä pers isted +pe i +old ing +Ä Doc uments +Ä H ast +Ä C ENT +Ä prim er +Ä syn onymous +Ä n ib +om bs +Ä not ation +Ä D ish +Ä At mosp +Ä forb id +Ä AN G +pat tern +l os +Ä project iles +b rown +." , +Ä Ven om +Ä fierce ly +ub lished +Ä U ran +Ä Nic arag +4 10 +Ä C AL +OT OS +Ä Mir acle +Ä En chant +Ä guard ing +app end +Att ach +Ä level ed +Ä cond oms +ih ilation +64 9 +Ä night mares +Ä THE Y +Ä ST ART +Ä K inn +Ä roomm ate +Ä hy giene +o pping +J ob +Ä l vl +Ä V ER +Ä Ke eping +ab etic +Ä format ting +eral a +Ä rev isions +Ä res urg +T el +Ä Good man +35 3 +p od +Ä ind isp +Ä Trans lation +Ä g own +Ä M und +Ä c is +Ä by stand +col lect +Ä Pun jab +act ively +Ä G amb +te ll +Ä import ing +g encies +Ä loc om +Ä Br ill +H oly +Ä Ber ger +Ä show down +Ä respond ers +IL Y +Ä t akedown +le ted +Ä mat tered +Ä predict ive +Ä over lay +G PU +Ä V ick +Ä convey ed +T ab +pe er +Sc an +Ä defensive ly +v ae +Ä appro ving +Ä t iers +Ä V ia +quer ade +Ä Saud is +Ä demol ished +Ä Prop he +Ä mon o +Ä hospital ity +H AM +Ä Ari el +M OD +Ä Tor ah +Ä bl ah +Ä Bel arus +erent ial +Ä T uc +Ä bank er +39 7 +Ä mosqu it +Ä Scient ist +Ä Mus ical +Ä h ust +Sh ift +Ä tor ment +Ä stand off +E duc +Ä F og +Ä ampl ifier +Sh ape +Inst ance +Ä Crit ics +Ä da emon +H ouston +Ä matt ress +Ä ID F +Ä obsc ene +Ä A mer +hett i +Ä comp iling +35 2 +vere tt +Ä Red uction +ist ration +Ä Bl essed +Ä B achelor +3 16 +Ä pr ank +Ä Vul can +dd ing +Ä m ourning +Ä Qu int +Ä Bl aster +test ing +Ä sed iment +>> > +Ä E ternity +Ä WH ERE +Ä M aze +Ä react ing +Ä Al v +oms day +Ä C RA +Ä transl ator +Ä bog us +at u +We bsite +oll s +Ä bapt ism +Ä s ibling +Ä Aut umn +ve z +ÃŖÄŖÂŽ Ê +gu ards +Ge org +assad ors +Ä Fre ud +Ä contin ents +Ä Reg istry +Bern ie +ĸÄŧ ÃĨÂŖÂĢ +Ä toler ant +Ä U W +Ä hor ribly +99 5 +Ä MID I +Ä impat ient +oc ado +er i +Ä Wor st +Ä Nor ris +Ä Talk ing +Ä def ends +ens able +Ä 20 21 +Ä anat omy +L ew +Ä draw er +Ä Can berra +Ä patri otic +ʞįÃĨ ĸÄŧÃĨÂŖÂĢ +Ä Av g +AR M +Ä undis closed +Ä fare well +45 9 +b able +Ä All ison +OL OG +Ä con co +t ight +Ä AC PI +Ä M ines +l ich +Ä ÃĸÄļ Äž +represent ed +200 000 +Ä enthusi ast +OT S +b il +Ä Ing redients +Ä invent or +Ä My SQL +³³ Âł +Ä AB OUT +with in +Ä m k +B ul +Ä F ake +Ä dracon ian +W a +hel m +Ä Ter ran +erv ille +Ä common place +SI ZE +Ä " < +re place +ograph s +Ä SE LECT +inc ible +Ä Most ly +Ä She ffield +Ä ID E +ugg le +Ä cit ations +h urst +Ä Un ix +Ä unle ash +Ä P iper +Ä N ano +Ä succ umb +Ä reluct ance +Ä 25 00 +Ä Mer chant +Ä wire t +Ä comb os +Ä Birth day +Ä char coal +Ä U PS +Ä Fair fax +Ä drive way +Ä T ek +Ä P itch +ove re +Ä techn icians +Ä Act ual +fl ation +Ä F iscal +Ä Em pty +an amo +Ä mag nesium +Ä sl ut +Ä grow ers +Invest igators +( ): +Ä S atellite +Ä Ke ynes +miss ive +l ane +Ä b orough +3 44 +Ä TE AM +Ä Bet hesda +C V +h ower +Ä R AD +Ä ch ant +Ä R iy +Ä compos itions +Ä mild ly +Ä medd ling +Ä ag ility +ane ers +5 01 +Ä syn th +ling er +29 1 +Ä ex claimed +Part y +Ä cont amin +Ä Man or +Ä Resp ond +Ä pra ising +Ä man ners +fle et +Sum mer +Ä Ly nd +Ä Def initely +gr im +Ä bow ling +st ri +ç ÄŊ +y nt +Ä mand ates +D IV +Ä reconc ile +view s +Ä Dam on +vet te +F lo +Ä Great est +il on +ic ia +Ä portray al +Ä cush ion +50 4 +19 79 +oss al +App lic +sc ription +Ä mit igation +AT S +p ac +Ä er ased +Ä defic iencies +Ä Holland e +Ä X u +Ä b red +Ä pregn ancies +f emin +Ä em ph +Ä pl anners +Ä out per +utter ing +Ä perpet rator +Ä m otto +Ä Ell ison +Ä NE VER +Ä admitted ly +AR I +Ä Azerbai jan +Ä mill isec +Ä combust ion +Ä Bott le +Ä L und +Ä P s +Ä D ress +Ä fabric ated +Ä bat tered +Ä s idel +Ä Not ting +Fore ign +Ä Jer ome +0 20 +Ä Ar bit +Ä kn ots +Ä R IGHT +M oving +ÃŖÄŖ Äģ +Ä sur geries +Ä cour thouse +Ä m astered +Ä hover ing +Ä Br an +Ä Al ison +Ä saf est +m ilitary +Ä bull ied +Ä bar rage +Read er +ES E +Ä Ge ographic +T ools +3 14 +Ä Ge ek +ro th +gl ers +Ä F IN +Ï ÄŖ +Ä A ston +al tern +48 8 +Ä veter in +G amer +Ä int el +ren ches +Sh ield +Ä am nesty +Ä B har +Ä p iled +Ä honor able +Ä Inst itutes +Ä so aked +Ä com a +Ä E FF +34 1 +by tes +Ä G mail +le in +Ä Canad iens +m aterial +I l +Ä instruct ors +Ä K Y +Ä conce ive +ub b +Ä P ossible +Ä eas ing +Ä Christ ina +Ä car ic +Ä HD R +R OM +Ä sho vel +de lete +Ä p uff +Ä Ch anging +Ä seam lessly +Att ribute +Ä acqu isitions +ak ery +Ä E F +Ä aut istic +Ä T akes +Ä Pow der +Ä St ir +5 10 +Ä Bub ble +sett ings +Ä F owler +Ä must ard +Ä more over +Ä copyright ed +Ä LED s +15 00 +ÃĻ ÄĢ +Ä H IS +en f +Ä cust od +Ä H uck +G i +Ä im g +An swer +C t +j ay +Ä Inf rastructure +Ä feder ally +L oc +Ä micro bes +Ä over run +dd s +ot ent +adi ator +>>>> >>>> +Ä torn ado +Ä adj ud +Ä intrig ued +Ä s i +Ä Revel ation +pro gress +Ä burgl ary +Ä Sai yan +Ä K athy +Ä ser pent +Ä Andre as +Ä comp el +ess ler +Ä Pl astic +Ä Ad vent +Ä Pos itive +Ä Q t +Ä Hind us +reg istered +ular ity +Ä righteous ness +Ä demon ic +u itive +Ä B DS +Ä Gre gg +c ia +Ä Crus ade +Ä Sina i +W ARE ++ ( +Ä me ll +Ä der ail +y ards +A st +Ä notice ably +Ä O ber +R am +Ä un noticed +Ä se q +av age +T s +Ä 6 40 +Ä conced e +Ä ] ) +F ill +Ä capt ivity +Ä Improve ment +Ä Crus ader +ara oh +M AP +ÃĻ Äš +Ä str ide +al ways +F ly +N it +Ä al gae +Ä Cook ing +Ä Do ors +Mal ley +Ä polic emen +ÃŖÄŖ į +Ä astron aut +access ible +49 5 +Ä R AW +cl iffe +udic rous +Ä dep ended +al ach +Ä vent ures +ra ke +Ä t its +Ä H ou +Ä cond om +ormon al +Ä ind ent +Ä upload ing +Foot note +Import ant +Ä 27 1 +Ä mind ful +Ä cont ends +C ra +Ä cal ibr +Ä O ECD +plug in +F at +Ä IS S +Ä Dynam ics +ans en +68 6 +' ), +Ä sp rite +Ä hand held +Ä H ipp +=~ =~ +Tr ust +Ä sem antics +Ä Bund es +Ä Ren o +Ä Liter ature +s ense +G ary +Ä A eg +Ä Tr in +EE K +Ä cler ic +Ä SS H +Ä ch rist +Ä inv ading +ib u +Ä en um +aur a +Ä al lege +Ä Inc redible +B BC +Ä th ru +Ä sa iled +Ä em ulate +Ä in security +Ä c rou +Ä accommod ations +Ä incompet ent +Ä sl ips +Ä Earth qu +s ama +IL LE +Ä i Phones +as aki +Ä by e +Ä ar d +Ä ext ras +Ä sl aughtered +Ä crowd funding +res so +Ä fil ib +Ä ER ROR +Ä T LS +e gg +Ä It al +Ä en list +Ä Catal onia +Ä Sc ots +Ä ser geant +Ä diss olve +N H +Ä stand ings +ri que +I Q +Ä benef iciary +Ä aqu arium +You Tube +Ä Power Shell +Ä bright est +Ä War rant +S old +Writ ing +Ä begin nings +Ä Res erved +Ä Latin os +head ing +Ä 4 40 +Ä rooft op +AT ING +Ä 3 90 +VP N +G s +k ernel +turn ed +Ä prefer able +Ä turn overs +Ä H els +S a +Ä Shin ji +ve h +Ä MOD ULE +V iol +Ä ex iting +Ä j ab +Ä Van illa +Ä ac ron +Ä G ap +ber n +A k +Ä Mc Gu +Ä end lessly +Ä Far age +Ä No el +V a +M K +Ä br ute +Ä K ru +Ä ES V +Ä Ol ivia +ÃĸÄĸ ł +Ä K af +Ä trust ing +Ä h ots +3 24 +Ä mal aria +Ä j son +Ä p ounding +ort ment +Count ry +Ä postp oned +Ä unequ iv +? ), +Ä Ro oney +udd ing +Ä Le ap +ur rence +sh apeshifter +Ä H AS +os ate +Ä ca vern +Ä conserv atism +Ä B AD +Ä mile age +Ä arrest ing +V aults +Ä mix er +Dem ocratic +Ä B enson +Ä auth ored +8 000 +Ä pro active +Ä Spirit ual +t re +Ä incarcer ated +Ä S ort +Ä pe aked +Ä wield ing +re ciation +×Äģ × +P atch +Ä Em my +Ä ex qu +tt o +Ä Rat io +Ä P icks +Ä G ry +ph ant +Ä f ret +Ä eth n +Ä arch ived +% - +c ases +Ä Bl aze +Ä im b +c v +y ss +im ony +Ä count down +Ä aw akening +Ä Tunis ia +Ä Re fer +Ä M J +Ä un natural +Ä Car negie +iz en +Ä N uggets +he ss +Ä ev ils +64 7 +Ä introdu ctory +l oving +Ä McM ahon +Ä ambig uity +L abel +Ä Alm ighty +Ä color ing +Ä Cl aus +set ting +N ULL +Ä F avorite +Ä S IG +> ( +Ä Sh iva +Ä May er +Ä storm ed +Ä Co verage +we apons +igh am +Ä un answered +Ä le ve +Ä c oy +c as +b ags +as ured +Se attle +Ä Sant orum +ser ious +Ä courage ous +Ä S oup +Ä confisc ated +Ä // / +Ä uncon ventional +Ä mom s +Ä Rohing ya +Ä Orche stra +Ä Pot ion +Ä disc redit +Ä F IL +f ixed +Ä De er +do i +Ä Dim ension +Ä bureaucr ats +et een +Ä action Group +oh m +Ä b umps +Ä Ut ility +Ä submar ines +ren heit +re search +Ä Shap iro +Ä sket ches +Ä de ceptive +Ä V il +es ame +Ä Ess entially +Ä ramp age +isk y +Ä mut tered +th ritis +Ä 23 6 +f et +b ars +Ä pup il +Ä Th ou +o S +s ong +Ä fract ured +Ä re vert +pict ure +Ä crit erion +us her +Ä reperc ussions +Ä V intage +Ä Super intendent +Offic ers +Ä flag ged +Ä bl ames +Ä in verse +ograp hers +Ä makes hift +Ä dev oid +Ä foss ils +Ä Arist otle +Ä Fund s +Ä de pleted +Ä Fl u +Ä Y uan +Ä w oes +Ä lip id +Ä sit u +requ isites +Ä furn ish +Ä Sam ar +Ä shame ful +Ä adverse ly +Ä ad ept +Ä rem orse +Ä murder ous +uck les +Ä E SL +Ä 3 14 +s ent +Ä red ef +Ä C ache +Ä P urs +ig ans +Ä 4 60 +Ä pres criptions +Ä f res +F uck +ocr ates +Tw enty +Ä We ird +Ä T oggle +Ä C alled +itiz ens +Ä p oultry +Ä harvest ing +ÃŖÄ¤ÂĻ ÃŖÄ¤Âš +Bott om +Ä caution ed +t n +39 6 +Ä Nik ki +Ä eval uations +Ä harass ing +Ä bind ings +Ä Mon etary +Ä hit ters +Ä advers ary +un ts +Ä set back +Ä enc rypt +Ä C ait +Ä l ows +eng es +Ä N orn +Ä bul bs +Ä bott led +Ä Voy ager +3 17 +Ä sp heres +p olitics +Ä subt ract +Ä sens ations +Ä app alling +Ä 3 16 +Ä environment ally +Ä ST EM +Ä pub lishes +5 60 +Ä dilig ence +48 4 +Ä adv ises +Ä pet rol +Ä imag ining +Ä patrol s +Ä Int eger +Ä As hes +act us +Ä Rad iant +Ä L T +it ability +ht aking +Set ting +Ä nu anced +Ä Re ef +Ä Develop ers +N i +pie ces +99 0 +Lic ense +Ä low ers +Ä Ott oman +3 27 +oo o +Ä qu itting +mark ets +Beh ind +Ä bas in +Ä doc s +an ie +fl ash +ct l +Ä civil ized +Ä Fuk ushima +"] ," +Ä K S +Ä Honest ly +ar at +Ä construct s +Ä L ans +Ä D ire +Ä LI KE +Ä Trou ble +Ä with holding +Ä Ob livion +Ä san ity +any a +Con st +Ä gro cer +Ä C elsius +Ä recount ed +Ä W ife +B order +ate red +h appy +Ä spo iler +Ä log ically +H all +Ä succeed ing +Ä poly morph +Ä ax es +Ä Shot gun +Ä S lim +Ä Prin ciples +Ä L eth +art a +Ä sc or +Sc reenshot +Ä relax ation +#$ #$ +Ä deter rent +idd y +Ä power less +Ä les bians +Ä ch ords +Ä Ed ited +se lected +Ä separat ists +000 2 +Ä air space +Ä turn around +Ä c unning +P ATH +P oly +Ä bomb ed +Ä t ion +x s +Ä with hold +Ä w aged +Ä Liber ties +Fl ag +Ä comfort ing +45 4 +Ä I ris +are rs +Ä r ag +Ä rel ocated +Ä Gu arant +Ä strateg ically +Ä gam ma +uber ty +Ä Lock heed +g res +Ä gr illed +Ä Low e +st ats +Ä R ocks +Ä sens ing +Ä rent ing +Ä Ge ological +ا Ø +ot rop +Ä se w +Ä improper ly +48 6 +Ä Ãĸĸ ł +Ä star ving +Ä B j +Disc ussion +3 28 +Ä Com bo +Ä Fix es +N AT +Ä stri ving +th ora +Ä harvest ed +Ä P ing +Ä play ful +Ä aven ues +Ä occup ational +Ä w akes +Ä Cou rier +Ä drum mer +Ä Brow ser +Ä H outh +it u +Ä app arel +p aste +Ä hun ted +Ä Second ly +l ain +X Y +Ä P IN +ic ons +Ä cock tails +Ä s izable +Ä hurd les +est inal +Ä Recre ation +Ä e co +64 8 +Ä D ied +m int +Ä finger prints +Ä dis pose +Ä Bos nia +ts y +22 00 +Ä ins pected +Ä F ou +Ä f uss +Ä amb ush +Ä R ak +Ä manif ested +Pro secut +Ä suff ice +ren ces +Ä compens ated +Ä C yrus +Ä gen us +Ä Wolver ine +Ä Trend s +Ä h ikes +Ä Se en +Ä en rol +C old +Ä pol itely +Ä Sl av +Ä Ru pert +Ä ey ewitness +Ä Al to +Ä un comp +Ä poster ior +M ust +Ä Her z +Ä progress ively +Ä 23 4 +Ä ind ifference +Ä Cunning ham +Ä academ ia +Ä se wer +Ä ast ounding +Ä A ES +r ather +Ä eld est +Ä clim bs +Ä Add s +Ä out cry +Ä cont ag +Ä H ouses +Ä pe pt +Ä Mel ania +interest ed +Ä U CH +Ä R oots +Ä Hub bard +Ä T BD +Ä Roman ian +fil ename +St one +Ä Im pl +Ä chromos ome +C le +d x +Ä scram bled +Ä P t +Ä 24 2 +OP LE +Ä tremend ously +St reet +Ä cra ving +Ä bund led +Ä R G +p ipe +Ä inj uring +Ä arc ane +Part icip +Ä Hero ic +st y +Ä to pping +Ä Temp est +rent ices +b h +Ä par anoia +Ä Unic ode +Ä egreg ious +Ä \ ' +Ä Osw ald +Ä gra vel +Ä Sim psons +Ä bl and +Ä Guant anamo +Writ er +lin ers +Ä D ice +J C +Ä par ity +Ä s ided +Ä 23 7 +Ä Pyr rha +at ters +d k +F ine +comp an +Ä form ulated +Ä Id ol +il ers +hem oth +Ä F av +Ä intr usion +Ä car rots +Ä L ayer +Ä H acker +Ä  ---------------- +Ä moder ation +Ê ÄŖ +oc oc +Ä character ize +Ä Te resa +Ä socio economic +Ä per k +Ä Particip ation +tr aining +Ä Paul o +ph ys +Ä trust worthy +Ä embod ied +Ä Mer ch +c urrency +Ä Prior ity +Ä te asing +Ä absor bing +Ä unf inished +Ä Compar ison +Ä dis ple +writ ers +Ä profess ions +Ä Pengu in +Ä ang rily +Ä L INK +68 8 +Ä Cor respond +Ä prev ailed +Ä cart el +l p +as ms +Ä Red emption +Ä Islam ists +effect s +d ose +Ä L atter +Ä Hal ifax +Ä v as +Ä Top ics +Ä N amed +advert ising +zz a +IC ES +Ä ret arded +ach able +Ä Pupp et +Ä Item Level +Ä ret ract +Ä ident ifiable +A aron +Ä B uster +s ol +hel le +as semb +H ope +r anged +B a +Ä P urch +Ê Äĸ +Ä Sir i +Ä arri vals +Ä 19 12 +Ä short ened +Ä 3 12 +Ä discrep ancy +Ä Tem perature +Ä Wal ton +Ä kind erg +p olit +Ä rem ix +Ä connect ors +ÃŖÄĨÄē ÃŖÄĨŠ +Ä Kazakh stan +dom inated +Ä su gars +im ble +Ä Pan ic +Ä Dem and +Ä Col ony +on en +Ä M ER +7 75 +ur ia +aza ar +Ä Deg ree +P ri +Ä sun shine +Ä 25 1 +Ä psychedel ic +Ä digit ally +Ä Bra un +Ä sh immer +Ä sh ave +Ä Tel esc +Ä Ast ral +Ä Venezuel an +Ä O G +Ä c rawling +Int eg +Ä Fe ather +Ä unfold ing +Ä appropri ation +Ä Ã¨ÂŖÄą è +Ä Mob ility +Ä N ey +- . +b ilt +L IN +Ä T ube +Ä Con versely +Ä key boards +Ä C ao +Ä over th +Ä la ure +>> \ +Ä V iper +ach a +Off set +Ä R aleigh +Ä J ae +J ordan +j p +Ä total itarian +Connect or +Ä observ es +Ä Spart an +Ä Im mediately +Ä Sc al +C ool +Ä t aps +Ä ro ar +P ast +Ä ch ars +Ä B ender +Ä She ldon +Ä pain ter +Ä be acon +Ä Creat ures +Ä downt urn +Ä h inder +Ä And romeda +à ÄŊ +cc oli +Ä F itness +et rical +Ä util izes +Ä sen ate +Ä en semble +Ä che ers +T W +Ä aff luent +k il +ry lic +ord ering +Com puter +Ä gru esome +ost ics +Ä Ub isoft +Ä Kel ley +Ä w rench +Ä bourgeois ie +IB LE +Ä Prest on +w orn +ar ist +reat ing +Ä st ained +ar ine +Ä sl ime +EN N +Ä che sts +Ä ground water +ann ot +Ä Tr ay +Ä Loc ke +Ä C TR +Ä d udes +Ä Ex ternal +Ä Dec oder +Ä par amed +Ä Med line +80 9 +Ä D inner +rup al +g z +Ä G um +Ä Dem o +j ee +Ä d h +ber man +arch s +Ä en qu +Ä Ep stein +Ä devast ation +Ä friends hips +Ä Ar d +Ä 23 1 +Ä Rub in +Ä Dist ance +Ä sp urred +Ä d ossier +Ä over looking +\\\\\\\\ \\\\\\\\ +Fore st +Ä Com es +\ ", +Ä Iran ians +Ä f ixtures +L aughs +Ä cur ry +Ä King ston +Ä squ ash +Ä cat alogue +Ä abnormal ities +Ä digest ive +.... ..... +Ä subord inate +og ly +Ä 24 9 +M iddle +Ä mass ac +Ä burg ers +Ä down stairs +Ä 19 31 +39 4 +Ä V G +Ä l asers +Ä S ikh +Ä Alex a +der ived +Ä cycl ist +ÃŖÄŖÂŽ ÊŃÄļ +onel iness +!!!! !!!! +Ä buff s +leg ate +Ä rap ing +Ä recomm ending +ro red +Ä mult icultural +un ique +Ä business men +Ä une asy +Ä M AP +Ä disp ersed +cipl ine +J ess +Ä K erala +ÃĨ § +Ä abst raction +Sur v +U h +Ä prin ters +ij a +ow der +Ä analog ous +Ä A SP +af er +Ä unfold ed +Ä level ing +Ä bre ached +Ä H earing +Ä n at +Ä transl ating +crit ical +Ä ant agonist +Ä Yes terday +Ä fuzz y +w ash +m ere +Ä be wild +Ä M ae +V irgin +ph rase +Ä sign aled +Ä H IGH +Ä prot ester +Ä gar ner +unk nown +Ä k ay +Ä abduct ed +Ä st alking +am n +Ä des erving +Ä R iv +Ä J orge +Ä scratch ing +Ä S aving +ip ing +Ä te ase +Ä mission ary +Ä Mor row +T IME +P resent +Ä chem otherapy +tern ess +Ä H omes +Ä P urdue +Ä st aunch +Ä Whit ney +Ä TH ERE +Î Âŧ +iat us +Ä Ern est +Ä De ploy +Ä cove ted +F ML +Ä Dial ogue +Ä ex ited +f ruit +Ä ner d +":" "," +Ä v ivo +ru ly +4 60 +Ä Am en +rehens ible +Ä Ãĸ Äē +D IR +Ä ad herence +Ä che w +Ä Co ke +Ä Serge i +dig ital +Ä Ne ck +g ently +enth al +/ ) +Ä we ary +Ä gu ise +Ä Conc ord +Ä On ion +at cher +Ä b inge +Ä Direct ive +Ä man ned +ans k +Ä ill usions +Ä billion aires +38 3 +oly n +odynam ic +Ä Whe at +Ä A lic +Ä col oured +Ä N AFTA +ab o +Ä mac ros +ind ependent +s weet +Ä sp ac +Ä K abul +Ä  Ä +em e +Ä dict ated +Ä sh outs += { +Ä r ipping +Ä Sh ay +Ä Cr icket +direct ed +Ä analys ed +Ä WAR RANT +ag ons +Ä Blaz ers +Ä che ered +Ä ar ithmetic +Ä Tan z +37 3 +Ä Fl ags +Ä 29 5 +Ä w itches +Ä In cluded +Ä G ained +Ä Bl ades +G am +Ä Sam antha +Ä Atl antis +Ä Pr att +Ä spo iled +Ä I B +Ä Ram irez +Pro bably +re ro +Ä N g +Ä War lock +t p +Ä over he +Ä administr ations +Ä t int +Ä reg iment +Ä pist ols +Ä blank ets +Ä ep ist +Ä bowl s +Ä hydra ulic +Ä de an +Ä j ung +Ä asc end +70 5 +Ä Sant iago +à Ž +Ä un avoid +Ä Sh aman +re b +Ä stem ming +99 8 +Ä M G +st icks +esthes ia +ER O +Ä mor bid +Ä Gr ill +Ä P oe +any l +Ä dele ting +Ä Surve illance +Ä direct ives +Ä iter ations +Ä R ox +Ä Mil ky +F ather +Ä pat ented +44 7 +Ä prec ursor +Ä m aiden +Ä P hen +Ä Ve gan +Ä Pat ent +K elly +Redd itor +Ä n ods +Ä vent ilation +Ä Schwar z +Ä w izards +Ä omin ous +Ä He ads +Ä B G +Ä l umber +Ä Sp iel +Ä is Enabled +Ä ancest ral +Ä Sh ips +Ä wrest ler +ph i +Ä y uan +Ä Rebell ion +Ä ice berg +Ä mag ically +Ä divers ion +ar ro +yth m +Ä R iders +Ä Rob bie +Ä K ara +Ä Main tenance +Ä Her b +Ä har ms +p acked +Ä Fe instein +Ä marry ing +Ä bl ending +Ä R ates +Ä 18 80 +Ä wr ink +Ä Un ch +Ä Tor ch +desc ribed +Ä human oid +ilit ating +Ä Con v +Ä Fe ld +IGH TS +Ä whistlebl ower +ort mund +ets y +arre tt +Ä Mon o +Ä I ke +Ä C NBC +Ä W AY +Ä MD MA +Ä Individual s +Ä supplement al +Ä power house +Ä St ru +F ocus +aph ael +Ä Col leg +att i +Z A +Ä p erenn +Ä Sign ature +Ä Rod ney +Ä cub es +idd led +Ä D ante +Ä IN V +iling ual +Ä C th +Ä so fa +Ä intimid ate +Ä R oe +Ä Di plom +Ä Count ries +ays on +Ä extrad ition +Ä dis abling +Ä Card iff +Ä memor andum +Ä Tr ace +Ä ?? ? +se ctor +Ä Rou hani +Ä Y ates +Ä Free ze +Ä bl adder +M otor +Ä Prom ise +ant asy +Ä foresee able +Ä C ologne +cont ainer +Ä Tre es +Ä G ors +Ä Sin clair +Ä bar ring +key e +Ä sl ashed +Ä Stat istical +Ê ÄŠ +Ä Ãĸĸ Âē +All ows +Ä hum ility +Ä dr illed +Ä F urn +44 3 +Ä se wage +Ä home page +Ä cour tyard +Ä v ile +Ä subsid iaries +aj o +direct ory +Ä am mon +V ers +charg es +Ä } } +Ä Ch ains +Ä 24 6 +n ob +Ä per cept +Ä g rit +Ä fisher men +Ä Iraq is +Ä DIS TR +Ä F ULL +Ä Eval uation +g raph +at ial +Ä cooper ating +Ä mel an +Ä enlight ened +Ä al i +t ailed +Ä sal ute +Ä weak est +Ä Bull dogs +U A +Ä All oy +Ä sem en +oc ene +Ä William son +s pr +, ÃĸÄĸÄļ +Ä G F +itt ens +Be at +Ä J unk +iph ate +Ä Farm ers +Ä Bit coins +ig ers +d h +Ä L oyal +p ayer +Ä entert ained +Ä penn ed +Ä coup on +Que ue +Ä weaken ing +c arry +Ä underest imate +Ä shoot out +Ä charism atic +Ä Proced ure +Ä prud ent +in ances +Ä ric hes +Ä cort ical +Ä str ides +Ä d rib +Ä Oil ers +5 40 +Ä Per form +Ä Bang kok +Ä e uth +S ER +Ä simpl istic +t ops +camp aign +Q uality +Ä impover ished +Ä Eisen hower +Ä aug ment +Ä H arden +Ä interven ed +Ä list ens +Ä K ok +Ä s age +Ä rub bish +Ä D ed +Ä m ull +pe lling +Ä vide ot +Produ ction +D J +m iah +Ä adapt ations +Ä med ically +Ä board ed +Ä arrog ance +Ä scra pped +Ä opp ress +FORM ATION +Ä j unction +4 15 +EE EE +S kill +Ä sub du +Ä Sug gest +Ä P ett +Ä le tt +Ä Man ip +Ä C af +Ä Cooper ation +T her +Ä reg ained +Âļ ÃĻ +ref lect +Ä th ugs +Ä Shel by +Ä dict ates +Ä We iner +Ä H ale +Ä batt leground +s child +Ä cond ol +h unt +osit ories +Ä acc uses +Fil ename +Ä sh ri +Ä motiv ate +Ä reflect ions +N ull +Ä L obby +ÂĨ Âĩ +Ä S ATA +Ä Back up +Ñ ÄĨ +n in +Ä Cor rection +Ä ju icy +ut ra +Ä P ric +Ä rest raining +Ä Air bnb +Ä Ar rest +Ä appropri ations +Ä sl opes +Ä mans laughter +Ä work ings +Ä H uss +Ä F rey +Le ave +Ä Harm ony +Ä F eder +Ä 4 30 +Ä t rench +Ä glad ly +Ä bull pen +Ä G au +b ones +Ä gro ove +Ä pre text +ÃŖ ħĭ +Ä transm itter +Ä Comp onent +Ä under age +Ä Em pires +T ile +Ä o y +Ä Mar vin +Ä C AS +Ä bl oss +Ä repl icated +Ä Mar iners +Marc us +Ä Bl ocks +Ä liber ated +Ä butter fly +Fe el +Ä fer mentation +Ä you tube +Ä off end +Ä Ter m +res ist +Ä cess ation +Ä insurg ency +Ä b ir +Ä Ra ise +59 5 +Ä hypothes es +50 2 +Ä pl aque +ocr at +Ä jack ets +Ä Huff Post +am ong +Ä conf er +48 7 +Ä L illy +Ä adapt ing +Ä F ay +Ä sh oved +ve c +Ä ref ine +Ä g on +Ä gun men +z ai +Ä Shut tle +Ä I zan +Ä 19 13 +Ä ple thora +Ã‚Âˇ Ã‚Âˇ +Ä 5 10 +Ä p uberty +Ä 24 1 +Ä We alth +Ä Al ma +Ä M EM +Ä Ad ults +C as +pr ison +R ace +Ä water proof +Ä athlet icism +Ä capital ize +Ä Ju ice +Ä illum inated +Ä P ascal +Ä irrit ation +Ä Witness es +ad le +Ä Ast ro +Ä f ax +Ä El vis +Prim ary +Ä L ich +Ä El ves +Ä res iding +Ä st umble +3 19 +Ä P KK +Ä advers aries +D OS +Ä R itual +Ä sm ear +Ä ar son +ident al +Ä sc ant +Ä mon archy +Ä hal ftime +Ä resid ue +Ä ind ign +Ä Sh aun +Ä El m +aur i +A ff +W ATCH +Ä Ly on +hel ps +36 1 +Ä lobby ist +Ä dimin ishing +Ä out breaks +Ä go ats +f avorite +Ä N ah +son ian +Ä Bo oster +Ä sand box +Ä F are +Ä Malt a +Ä att Rot +Ä M OR +ld e +Ä navig ating +T ouch +Ä unt rue +Ä Dis aster +Ä l udicrous +Pass word +Ä J FK +blog spot +4 16 +Ä UN DER +ern al +Ä delay ing +T OP +Ä impl ants +Ä AV G +Ä H uge +att r +Ä journal istic +Ä Pe yton +Ä I A +R ap +go al +Ä Program me +Ä sm ashing +w ives +print ln +Ä Pl ague +in us +EE P +Ä cru iser +Ä Par ish +umin ium +Ä occup ants +Ä J ihad +m op +Ä p int +Ä he ct +Ä Me cca +direct or +Ä Fund ing +Ä M ixed +Ä st ag +T ier +Ä g ust +Ä bright ly +ors i +Ä up hill +R D +Ä les ions +Ä Bund y +liv ious +Ä bi ologist +Ä Fac ulty +Ä Author ization +Ä 24 4 +All ow +ï ¸ +Ä Gi ul +Ä pert inent +ot aur +es se +Ä Ro of +Ä unman ned +35 1 +Ä Sh ak +Ä O rient +Ä end anger +D ir +Ä repl en +ed ient +Ä tail or +Ä gad gets +Ä aud ible +ÃĸÄē Ĩ +N ice +Ä bomb ard +Ä R ape +Ä def iance +Ä TW O +Ä Filip ino +Ä unaff ected +erv atives +Ä so ared +Ä Bol ton +Ä comprom ising +Ä Brew ers +R AL +Ä A HL +icy cle +Ä v ampires +Ä di pped +oy er +Ä X III +Ä sidew ays +Ä W aste +Ä D iss +Ä ÃĸÄļÄž ÃĸÄļÄĸÃĸÄļÄĸ +$ . +Ä habit ats +Ä Be ef +tr uth +tr ained +spl it +R us +And y +Ä B ram +RE P +p id +Ã¨ÂŖ ħ +Ä Mut ant +An im +Ä Mar ina +Ä fut ile +hig hest +f requency +Ä epile psy +Ä cop ing +Ä conc ise +Ä tr acing +Ä S UN +pan el +Ä Soph ie +Ä Crow ley +Ä Ad olf +Ä Shoot er +Ä sh aky +Ä I G +Ä L ies +Ä Bar ber +p kg +Ä upt ake +Ä pred atory +UL TS +/ ** +Ä intox icated +Ä West brook +od der +he ment +Ä bas eman +AP D +st orage +Ä Fif ty +ed itor +G EN +UT ION +ir ting +Ä se wing +r ift +Ä ag ony +Ä S ands +Ä 25 4 +C ash +Ä l odge +Ä p unt +N atural +Ä Ide as +Ä errone ous +Ä Sens or +Ä Hann ity +Ä 19 21 +Ä m ould +Ä G on +kay a +Ä anonym ously +Ä K EY +Ä sim ulator +W inter +Ä stream ed +50 7 +? ", +Ä te ased +Ä co efficient +Ä wart ime +Ä TH R +' '. +Ä Bank ing +mp ire +Ä f andom +Ä l ia +G a +Ä down hill +Ä interpre ting +Ind ividual +N orm +Ä jealous y +bit coin +Ä ple asures +Ä Toy s +Ä Chev rolet +Ä Ad visor +IZ E +Ä recept ions +70 6 +C ro +Ä 26 2 +Ä cit rus +ir u +Review er +ject ed +U ES +an z +19 81 +Ä Work er +Ä compl ied +ores cent +contin ental +T on +Ä Pr ism +Ä She ep +Ä 28 8 +n ox +Ä V og +O rd +Ä real ms +te k +Ä irrig ation +Ä bicy cles +Ä electron ically +p oly +t all +() ); +Ä aest hetics +Ä Integ rated +Expl ore +Ä d unk +47 6 +p ain +Ä Jac ques +Ä D mit +Fram es +Ä reun ited +Ä hum id +D ro +P olitical +Ä youth ful +Ä ent ails +Ä mosqu ito +36 3 +spe cies +Ä coord inating +Ä May hem +Ä Magn us +M ount +Impro ved +Ä ST ATE +ATT LE +Ä flow ed +Ä tack led +Ä fashion ed +Ä re organ +iv ari +f inger +Ä reluct antly +et ting +Ä V and +you ng +Ä Gar land +Ä presum ption +Ä amen ities +Ä Ple asant +on ential +Ä O xy +Ä mor als +Ä Y ah +Read y +Sim on +En h +D emon +Ä cl ich +Mon itor +Ä D U +Ä wel comes +Ä stand out +Ä dread ful +Ä ban anas +Ä ball oons +h ooting +bas ic +Ä suff ix +Ä d uly +can o +Ch ain +at os +Ä geop olitical +Ä ( & +Ä Gem ini +ÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤ ÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤÃÄĨÃĤ +Ä acqu itted +L uck +prot ect +10 24 +Ä sc arcity +Ä mind fulness +ec ided +D N +pr ime +Ä Pres idents +Ä VID EO +Ä ( ÃĸÄĒÄ´ +add ock +N OR +Ä P ru +p un +Ä L OL +)) )) +Ä L iqu +Ä S AS +Ä sty ling +Ä punish ments +Ä num b +Ä asc ertain +Ä Rock ies +f lu +Th umbnail +Ä perpet rated +Ä Sem i +Ä dis arm +Ä Old er +Ä Ex ception +Ä exponent ially +Ä Commun ities +Ä abol ish +Ä Part ner +pt oms +Ä 7 77 +Ä Fo ley +Ä C ases +Ä gre ase +Ä Reb irth +G round +Ä ; ) +Ä Doct rine +ik ini +Y e +Ä Bl ossom +Ä pers ists +b ill +Ä inf usion +Ä bud dies +9 11 +Ä Pat ient +Ä dem os +Ä acquaint ance +Ä P aw +at ari +Ä x ml +Ä fasc ination +Ä Ser ve +Ï Ĥ +br anded +Ä a z +Return s +Ä over shadow +Ä ro am +Ä speed y +n umbered +hel ial +Ä disc iple +Ä ass urances +g iven +pect ing +Ä N atalie +çÄļ ° +Ä mosquit oes +rote in +Ä numer ic +Ä independ ents +Ä trans itional +Ä reaction ary +Ä Mech dragon +do ctor +Ä short est +Ä sequ ential +Ä B ac +Ä Account s +ÃŖÄŖ ÄŽ +ach y +ract ive +Ä Reg iment +Ä breat htaking +ffic iency +Ä B ates +Ä 3 11 +Ä ward robe +ft s +Ä Ber k +Sim ply +Ä Rivers ide +iver ing +ident ial +lu cent +Ä en riched +Ä Con ver +Ä G iving +ÃŖÄĨ Äģ +Ä legal ize +Ä F TC +Ä fre aking +M ix +Ä ter restrial +es ian +ci ents +W ing +LO AD +Ä led ge +Ä Viol ent +Ä Met all +Ä 30 8 +Ä s outheastern +hett o +M eat +Ä slow down +Ä ret reated +Jere my +end as +**** * +er ic +Ä re ins +opp able +Ä Human ity +ear ances +rig an +C amera +Ä wa ivers +s oc +Ä alter ation +trans form +Ä C emetery +50 6 +Ä indef inite +Ä stim ulating +y g +60 3 +Ä S op +Ä descript ive +Ph ase +Ä Ed mund +Ä pneum onia +vent us +A mb +Ä labor atories +Ä Ex clusive +ug ar +W ere +Ä malf unction +Ä homosexual s +Ä ---- --- +un i +Ä turb ines +Ä Equ ity +D u +Ä mind ed +Ä R H +Ä Black hawks +Ä fe ats +Ä 17 00 +re pl +36 2 +lad en +Ä indisp ensable +ly ss +tt i +Ä re el +Ä diver ted +Ä lik eness +Ä subscript ions +Ä fing ert +Ä fil thy +dest ruct +d raft +Ä Bernard ino +l aunch +Ä per plex +Ä S UM +car b +Ä swe ater +Ä Vent ure +Ä J ag +Ä Cele b +Ä V oters +Ä stead fast +Ä athlet ics +Ä Hans on +Ä Dr ac +Tr acker +Ä comm end +Ä Pres idency +Ä D ID +in formed +Ä web page +P retty +Ä force fully +ÃŖÄĨÄĨ ÃŖÄ¤Â¯ +Ä rel ocation +Ä sat ire +Ãĸ ÄĢ +Ä Sunder land +ÃĻ ÄĻ +V oice +???? ???? +Ä inform ant +Ä bow el +Ä Un iform +Ä  ..." +Ä pur ge +Ä pic nic +Ä U mb +Ä U PDATE +Ä Sapp hire +Ä St all +le arn +Ä object ively +Ä ob liter +Ä looph ole +Ä jour neys +Ä o mission +Pro s +Ä Sid ney +pl oma +Ä spray ed +Ä g uru +Ä tra itor +Ä tim et +Ä sn apping +Ä Se vent +urn al +Ä Uk ip +Ä b owed +por al +l iberal +R os +Quest ions +i OS +Ä summar ize +ST AT +Ä 18 50 +ap est +Ä l ender +Ä Vari able +br inging +Ä L ORD +, ) +Ä collaps es +x iety +Ä N ed +Y D +Ä Sch a +Ä antib ody +Ä dis band +y re +ill usion +Ä ro ver +s hed +Ä Hiro sh +cc i +Ä cal am +Ä Mort on +P interest +Ä 19 28 +Ä E uras +ord es +Ä f ences +Ä In ventory +Ä Val encia +Ä U d +Ä T iff +Ä squ e +Ä qu otation +Ä troubles ome +er ker +QU EST +Ä King doms +s outh +Ä le vy +Pr ince +Ä St ing +Ä nick named +Ä app e +Ä phot ographic +Ä corp us +re ference +Ä T rog +U nt +) =( +Ä Lat via +Ä activ ating +Ä license e +Ä dispar ities +Ä News letter +ÃŖÄĨÄĨ ÃŖÄĨÄĒ +Ä free ing +Ä Je ep +Ä Per ception +ins k +Ä sil icone +Ä Hay den +Le an +Ä Suz uki +ibr arian +66 8 +Ä sp or +Ä correl ations +ag hetti +Ä tu ber +Ä IP CC +il us +Ä V u +Ä wealth iest +Ä Carb uncle +an za +Ä fool ed +Ä Z ur +Ä d addy +ran o +il ian +Ä knock out +f man +requ ired +Ä Wik ileaks +Ä D uffy +ON T +Ä ins ol +Ä Object s +Ä b ou +Ä Nord ic +Ä Ins ert +sc an +Ä d ancers +Ä id iots +major ity +Ä Nev ille +Ä Free BSD +Ä t art +pan ic +69 0 +Ä coc oa +Ä sam pled +Ä look up +Ind ust +Ä inject ions +gen re +Ä a u +Ä road way +Ä gen itals +K ind +Ä Ex aminer +Ä Y az +F resh +Ä par alysis +Ä Al uminum +Ä re ap +ok Ê +Ä sl oppy +Ä Tun nel +pos ium +ner y +en ic +Ä her bal +Ä Out er +Ä Build er +Ä inc ur +Ä ide ologies +Ä back ups +cons uming +Ä Det ect +de ck +Ä KN OW +Ä G ret +Ä M IC +Ä tough ness +Ä Ex hibit +Ä h ive +L es +Ä SCH OOL +Ä At ari +ald e +Ä N ull +and estine +m ouse +Ä brig ade +48 9 +Ä rev ol +Ä Law son +Ä W ah +op oly +eb ted +Ä S aunders +Ä 3 13 +Ä W inc +Ä tab oo +Ä Hel met +Ä w edge +ch ip +Ä T ina +b g +Ä inf uri +r n +Ä anomal ies +Ä Sy nc +Ä Ex am +Ä Comm it +Ä Di ary +Ä ALS O +Ä De bor +omed ical +Ä comprehens ion +6 55 +Ä empower ing +Ä  ire +Ä ju ices +Ä E TH +Ä Box ing +=" / +Ä facilit ated +p oke +Ä Pars ons +Ä Mod er +tra vel +Ä civil izations +Ä liber tarians +Ä run e +Ä Cl arks +at hed +Ä campaign ers +Ä Dis patch +Ä Fah renheit +Ä Cap com +-------- -- +Ä l ace +Ä dr aining +Ä l iner +Ä Art ificial +Ê n +t ask +] ). +Ä GM O +Ä Oper ator +ord inary +Ä Inf luence +Ä U ps +Ä pot ency +uss en +osp ons +Ä Sw im +Ä Dead line +Un ity +Ä cul inary +Ä enlight enment +Ä we arer +Ä min ed +Ä p ly +Ä inc est +Ä DVD s +W alk +B TC +Tr ade +Ä dev al +ib and +Ä Overs ight +Palest inian +Ä d art +Ä m ul +L R +Ä rem ovable +Ä Real ms +ÃŦ Äŋ +Ä misc ar +Ä V ulkan +68 5 +è re +Ä S ap +Ä mer ging +Ä Car ly +che ster +Ä br isk +Ä lux urious +Ä Gener ator +Ä bit terness +Ä ed ible +Ä 24 3 +T G +Ä rect angle +With No +bel ow +J enn +Ä dark est +Ä h itch +Ä dos age +Ä sc aven +Ä K eller +Ä Illust rated +Certain ly +Ä Maver icks +Marg inal +Ä diarr hea +Ä enorm ously +Ä 9 99 +sh r +qu art +Ä adam ant +Ä M ew +Ä ren ovation +Ä cerv ical +Ä Percent age +en ers +Ä Kim ber +Ä flo ats +Ä de x +Ä W itcher +Ä Swan sea +d m +Ä sal ty +y ellow +Ä ca pe +Ä Dr ain +Ä Paul a +Ä Tol edo +les i +Mag azine +Ä W ick +Ä M n +Ä A ck +Ä R iding +AS ON +Ä hom ophobic +AR P +Ä wand ered +C PU +ood oo +Ä P ipe +Ä tight ening +Ä But t +3 18 +Ä desert ed +S ession +Ä facilit ating +J ump +Ä emer gencies +OW ER +Ä exhaust ive +Ä AF TER +Ä heart beat +Ä Lab el +ack y +Ä Cert ified +ilt ration +Z e +Ä U tt +Ä 13 00 +Ä pres ume +Ä Dis p +Ä sur ged +Ä doll s +Col umb +Ä chim pan +Ä R azor +Ä t icks +Ä councill or +Ä pilgr image +Ä Reb els +Ä Q C +Ä A uction +x ia +ik k +b red +Ä insert ion +Ä co arse +d B +SE E +Ä Z ap +Ä F oo +Ä contem por +Ä Quarter ly +ot ions +Ä Al chemist +Ä T rey +Ä Du o +S weet +80 4 +Ä Gi ov +Ä fun n +N in +h off +Ä ram ifications +Ä 19 22 +Ä Exper ts +az es +Ä gar ments +ar ial +Ä N ab +Ä 25 7 +Ä V ed +Ä hum orous +Ä Pom pe +Ä n ylon +Ä lur king +Ä Serge y +Ä Matt is +Ä misogyn y +Ä Comp onents +Ä Watch ing +Ä F olk +ract ical +B ush +Ä t aped +Ä group ing +Ä be ads +Ä 20 48 +Ä con du +quer que +Read ing +Ä griev ances +Ult ra +Ä end point +H ig +Ä St atic +Ä Scar borough +L ua +Ä Mess i +a qu +Ä Psy Net +Ä R udd +Ä a venue +v p +J er +Ä sh ady +Ä Res ist +Ä Art emis +Ä care less +Ä bro kers +Ä temper ament +Ä 5 20 +T ags +Ä Turn ing +Ä ut tered +Ä p edd +Ä impro vised +Ä : ( +Ä tab l +Ä pl ains +16 00 +press ure +Ä Ess ence +marg in +friend s +Ä Rest oration +Ä poll ut +Ä Pok er +Ä August ine +Ä C IS +Ä SE AL +or ama +Ä th wart +se ek +Ä p agan + Âē +cp u +Ä g arn +Ä ass ortment +Ä I LCS +t ower +Recomm ended +Ä un born +Ä Random Redditor +Ä RandomRedditor WithNo +Ä paraly zed +Ä eru ption +Ä inter sect +Ä St oke +Ä S co +B ind +ÃĨ ž +Ä P NG +Ä Neg ative +Ä NO AA +Le on +Ä all oy +Ä L ama +Ä D iversity +5 75 +Ä underest imated +Ä Sc or +Ä m ural +Ä b usted +so on +l if +Ä none x +Ä all ergy +Ä Under world +Ä R ays +Ä Bl asio +Ä h rs +Ä D ir +Ä 3 27 +by ter +Ä repl acements +Ä activ ates +ri ved +M H +Ä p ans +Ä H I +Ä long itudinal +Ä nu isance +al er +Ä sw ell +Ä S igned +s ci +Ä Is les +Ä A GA +Ä def iant +Ä son ic +oc on +K C +Ä A im +t ie +ah ah +Ä m L +D X +Ä b isc +Ä Bill board +Ä SY STEM +NE Y +ga ard +Ä dist ressed +former ly +Al an +Ä che fs +Ä opt ics +Ä C omet +Ä AM C +Ä redes igned +irm ation +Ä sight ings +38 2 +3 11 +Ä W B +Ä cont raction +Ä T OTAL +D ual +Ä start led +Ä understand ably +Ä sung lasses +ETH OD +Ä d ocker +Ä surf ing +Ä H EL +Ä Sl ack +ton es +Ä sh alt +Vis ual +49 8 +Dep artment +c ussion +Ä unrest ricted +Ä t ad +Ä re name +employ ed +Ä educ ating +Ä grin ned +bed room +Ä Activ ities +Ä V elvet +Ä SW AT +Ä sh uffle +ig or +Ä satur ation +F inding +c ream +ic ter +Ä v odka +tr acking +te c +Ä fore ground +iest a +Ä ve hement +Ä EC B +Ä T ie +E y +Ä t urtles +Ä Rail road +Ä Kat z +Ä Fram es +Ä men ace +Ä Fell owship +Ä Ess ential +ugg ish +Ä dri p +ch witz +Ä Ky oto +s b +Ä N ina +Param eter +Ä al arms +Ä Cl aud +Ä pione ering +Ä chief ly +Ä Sc ream +Col lection +Ä thank fully +Ä Ronald o +ÃĨŃ IJ +st rip +Ä Disney land +com mercial +See ing +S oul +Ä evac uate +Ä c iv +Ä As he +Ä div ides +Ä D agger +rehens ive +Ä ber ries +Ä D F +Ä s ushi +Ä plur ality +W I +Ä disadvant aged +Ä batt alion +ob iles +45 1 +Ä cl ing +Ä unden iable +Ä L ounge +Ä ha unt +p he +Ä quant ify +Ä diff ered +Ä [* ] +Ä V iz +c um +sl ave +Ä vide og +Ä qu ar +Ä bund les +Ä Al onso +t ackle +Ä neur onal +Ä landsl ide +conf irmed +Ä Dep th +Ä renew ables +B ear +Ä Maced onia +Ä jer seys +Ä b unk +Ä Sp awn +Ä Control s +Ä Buch anan +Ä robot ics +Ä emphas izing +Ä Tut orial +h yp +ist on +Ä monument al +ÃĻ Â° +Ä Car ry +Ä t bsp +en ance +H ill +art hed +Ä ro tten +De an +Ä tw isting +Ä good will +Ä imm ersion +L iving +Ä br ushes +Ä C GI +Ä At k +tr aditional +Ä ph antom +Ä St amina +Ä expans ions +Ä Mar in +Ä embark ed +Ä E g +int estinal +Ä PE OPLE +Ä Bo oth +Ä App alach +Ä releg ated +V T +M IT +Ä must er +Ä withdraw ing +Ä microsc ope +Ä G athering +Ä C rescent +Ä Argent ine +Ä Dec re +Ä Domin ic +Ä bud s +ant age +Ä I on +Ä wid ened +ONS ORED +Ä Gl oves +iann opoulos +raz en +fe el +Ä repay ment +Ä hind sight +Ä RE ALLY +Ä Pist ol +Ä Bra h +Ä wat ts +Ä surv ives +Ä fl urry +iss y +Al ert +Ä Urug uay +Ph oenix +S low +Ä G rave +Ä F ir +Ä manage able +Ä tar iff +Ä U DP +Ä Pist ons +Ä Niger ian +Ä strike outs +Ä cos metics +whel ming +f ab +c ape +pro xy +Ä re think +Ä over coming +sim ple +Ä w oo +Ä distract ing +Ä St anton +Ä Tuls a +Ä D ock +65 9 +Ä disc ord +Ä Em acs +Ä V es +Ä R OB +Ä reass uring +Ä cons ortium +Muslim s +3 21 +Ä prompt s +se i +Ä H itch +imp osed +Ä F ool +Ä indisc rim +wr ong +bu querque +D avis +! ] +Ä tim eless +Ä NE ED +Ä pestic ide +Ä rally ing +Ä Cal der +Ä ÃĨ ¤ +Ä x p +Ä Un le +Ä Ex port +lu aj +B uff +) [ +Ä sq or +S audi +Ä is tg +Ä indul ge +pro c +Ä disg usted +Ä comp ounded +Ä n em +Ä school ing +Ä C ure +process ing +S ol +Ä pro verb +it ized +Ä Alv arez +Ä scar f +Ä rect angular +re ve +Ä h ormonal +Ä St ress +itiz en +Ä 4 25 +girl s +Ä No ir +Ä R app +Ä mar ches +ch urch +Ä Us es +Ä 40 5 +Ä Ber m +Ä ord inances +Ä Jud gment +Charg es +Ä Z in +Ä dust y +Ä straw berries +Ä per ce +Ä Th ur +Ä Debor ah +net flix +Ä Lam bert +Ä am used +Ä Gu ang +Y OU +R GB +Ä C CTV +Ä f iat +r ang +Ä f ederation +Ä M ant +Ä B ust +Ä M are +respect ive +Ä M igration +Ä B IT +59 0 +Ä patriot ism +Ä out lining +reg ion +Ä Jos Ê +Ä bl asting +Ä Ez ra +B s +Ä undermin es +Ä Sm ooth +Ä cl ashed +rad io +Ä transition ing +Ä Bucc aneers +Ä Ow l +Ä plug s +Ä h iatus +Ä Pin ball +Ä m ig +Ä Nut r +Ä Wolf e +Ä integ ers +Ä or bits +Ä Ed win +Ä Direct X +b ite +Ä bl azing +v r +Ed ge +Ä P ID +ex it +Ä Com ed +Ä Path finder +Ä Gu id +Ä Sign s +Ä Z er +Ä Ag enda +Ä reimburse ment +M esh +i Phone +Ä Mar cos +Ä S ites +h ate +en burg +Ä s ockets +p end +Bat man +v ir +Ä SH OW +Ä provision al +con n +Ä Death s +AT IVE +Pro file +sy m +J A +Ä nin ja +inst alled +id ates +eb ra +Ä Om aha +Ä se izing +Ä Be asts +Ä sal ts +M ission +Gener ally +Ä Tr ilogy +he on +leg ates +Ä d ime +Ä f aire +par able +G raph +Ä total ing +Ä diagram s +Ä Yan uk +ple t +Ä Me h +Ä myth ical +Ä Step hens +aut ical +ochem istry +Ä kil ograms +Ä el bows +anc ock +Ä B CE +Ä Pr ague +Ä impro v +Ä Dev in +Ä " \ +par alle +Ä suprem acists +Ä B illion +Ä reg imen +inn acle +Ä requ isite +ang an +Ä Bur lington +ain ment +Ä Object ive +oms ky +G V +Ä un ilateral +Ä t c +Ä h ires +ment al +Ä invol untary +Ä trans pl +Ä ASC II + ¨ +Ev ents +Ä doub ted +Ä Ka plan +Ä Cour age +ig on +Ä Man aging +Ä T art +Ä false hood +Ä V iolet +Ä air s +Ä fertil izer +Brit ain +Ä aqu atic +ou f +W ords +Ä Hart ford +Ä even ings +Ä V engeance +qu ite +G all +Ä P ret +Ä p df +Ä L M +Ä So chi +Ä Inter cept +9 20 +Ä profit ability +Ä Id le +Ä Mac Donald +Ä Est ablishment +um sy +Ä gather ings +Ä N aj +Charl ie +Ä as cent +Ä Prot ector +Ä al gebra +Ä bi os +for ums +EL S +Introdu ced +Ä 3 35 +Ä astron omy +Cont ribut +Ä Pol ic +Pl atform +Ä contain ment +w rap +Ä coron ary +Ä J elly +man ager +Ä heart breaking +c air +Ä Che ro +c gi +Med ical +Ä Account ability +! !" +oph ile +Ä psych otic +Ä Rest rict +Ä equ itable +iss ues +Ä 19 05 +Ä N ek +c ised +Ä Tr acking +Ä o zone +Ä cook er +ros is +Ä re open +Ä inf inity +Ä Pharm aceutical +ens ional +Att empt +Ä R ory +Mar co +Ä awa its +H OW +t reated +Ä bol st +Ä reve red +Ä p ods +opp ers +00 10 +Ä ampl itude +ric an +SP ONSORED +Ä trou sers +Ä hal ves +Ä K aine +Ä Cut ler +Ä A UTH +Ä splend id +Ä prevent ive +Ä Dud ley +if acts +umin ati +Ä Y in +Ä ad mon +Ä V ag +Ä in verted +Ä hast ily +Ä H ague +L yn +Ä led ger +Ä astron omical +get ting +Ä circ a +Ä C ic +Ä Tenn is +Lim ited +Ä d ru +Ä BY U +Ä trave llers +Ä p ane +Ä Int ro +Ä patient ly +Ä a iding +Ä lo os +Ä T ough +Ä 29 3 +Ä consum es +Source File +Ä "" " +Ä bond ing +Ä til ted +Ä menstru al +Ä Cel estial +UL AR +Plug in +Ä risk ing +N az +Ä Riy adh +Ä acc redited +Ä sk irm +Ê ÄŊ +Ä exam iner +Ä mess ing +Ä near ing +Ä C hern +Ä Beck ham +Ä sw apped +Ä go ose +K ay +Ä lo fty +Ä Wal let +Ä [ ' +Ä ap ocalypse +Ä b amboo +Ä SP ACE +Ä El ena +Ä 30 6 +ac ons +Ä tight ened +Ä adolesc ence +Ä rain y +Ä vandal ism +Ä New town +Ä con ject +c akes +Ä che ated +Ä moder ators +par ams +E FF +Ä dece it +Ä ST L +Ä Tanz ania +Ä R I +Ä 19 23 +Ä Ex ile +the l +Ä the olog +Ä quir ky +Ä Ir vine +Ä need y +or is +U m +K a +Ä mail box +3 22 +Ä b os +Ä Pet ra +K ING +Ä enlarg ed +O ften +Ä bad ass +Ä 3 43 +Ä Pl aces +Ä C AD +Ä pr istine +Ä interven ing +d irection +Ä l az +Ä D SM +Ä project ing +Ä F unk +ag og +pay ment +n ov +Ä ch atter +AR B +Ä exam inations +Ä House hold +Ä G us +F ord +4 14 +B oss +Ä my stic +Ä le aps +Ä B av +ul z +b udget +Foot ball +Ä subsid ized +Ä first hand +Ä coinc ide +oc ular +Con n +Ä Coll abor +Ä fool s +am ura +ah ar +r ists +Ä sw ollen +Ä exp ended +Ä P au +s up +Ä sp ar +Ä key note +s uff +Ä unequ al +Ä progress ing +str ings +Ä Gamer gate +Dis ney +Ä Ele ven +om nia +Ä script ed +Ä ear ners +bro ther +Ä En abled +ÃĻ Âŗ +Ä lar vae +Ä L OC +m ess +Wil son +Ä Tem plate +success fully +Ä param ount +Ä camoufl age +Ä bind s +Ä Qu iet +Ä Sh utterstock +r ush +Ä masc ot +fort une +Ä Col t +Ä Be yon +hab i +Ä ha irc +Ä 26 7 +Ä De us +Ä tw itch +Ä concent rating +Ä n ipples +c ible +Ä g ir +N Z +M ath +n ih +Requ ired +Ä p onder +Ä S AN +Ä wedd ings +Ä l oneliness +N ES +Ä Mah jong +69 5 +add le +Ä Gar ner +Ä C OUR +Br idge +Ä sp ree +Ä Cald well +Ä bri bery +ĠïÂŋÂŊïÂŋÂŊïÂŋÂŊïÂŋÂŊ ïÂŋÂŊïÂŋÂŊïÂŋÂŊïÂŋÂŊ +plug ins +Ä r acket +Ä champ agne +vers ible +V ote +Ä mod ifiers +May or +6 80 +Ä assemb lies +Ä S ultan +Ä N ing +Ä Lad ies +Ä sulf ur +Ä or bs +Ä ---- - +____ ___ +Ä Journal ism +Ä es ports +Ä l ush +Ä h ue +Ä spect ral +H onest +ÃŖÄĨ Äą +Ä bus hes +Ä rein forcement +Ä re opened +Ä Whe els +Ä M org +rie ving +Ä aux iliary +Ä j Query +Ä B AT +tes que +Ä ver tex +p ure +f rey +ÃŖÄ¤ Âē +d os +Ä ty ph +Ä c ull +Ä e q +Ä dec on +Ä toss ing +Ä dispar ate +Ä Br igham +print f +led ged +Ä su nd +Ä co zy +Ä hepat itis +per forming +Ä av al +Ä G G +f uture +Ä pet ertodd +Ä Kos ovo +Ä magn ets +Al ready +Ä Ed ison +Ä Ce res +Ä RA ID +Ä brill iance +57 6 +Ä der ives +Ä hypert ension +ĠÎ Äļ +Ä lamb da +Ä fl air +Ä mission aries +Ä rap es +Ä St arter +Ä Mon ths +Ä def y +Ä seism ic +Ä R aphael +Ä euro zone +65 6 +z sche +Ä scr atched +Ä b ows +Ä Lenn on +Ä Ga ia +Ä dri pping +f acts +A le +Ä frog s +Ä Bre ast +ogene ity +Ä Prosecut or +Ä ampl ified +Ä Hod g +Ä F n +Th ousands +Ä NI H +Ä Monitor ing +FT WARE +Ä Pri ebus +Ä G rowing +hun ter +Ä diagn ose +Ä M ald +Ä L R +Ä crown ed +Ä burst ing +Ä diss olution +j avascript +Ä useful ness +Ä Exec ution +: ( +Ä Iv ory +a ah +Ä persecut ed +viol ence +ist as +Ä Cr ate +Ä impuls es +Ä Sp ani +ed es +Hand le +Ä Z erg +think able +Last ly +Ä spont aneously +Ä inconven ient +Ä dismiss ing +Ä pl otted +Ä eight y +Ä 7 37 +r ish +Ä Thor nton +ath am +Ä sit com +V en +Rec ipe +t el +l und +Ä cle ars +Ä Sas uke +Ä 25 8 +Ä opt ing +Ä en raged +est hetic +Ä A e +uch s +Pre p +Fl ow +Ä run off +Ä E ating +Ä G iles +Ä Act ing +res ources +ib aba +Ä r pm +Ä ske wed +Ä Bl anc +Ä S akuya +Ä hot ter +Ä 19 24 +op ian +ck o +Ä cr umbling +Ä capt ains +Ä Appropri ations +le aders +dro pping +an uts +Ä revers ing +Ä P ose +Ä S ek +Sc ot +Ä Ide a +c ise +Ä Sloven ia +Ä 3 17 +Do ctor +Ä cro cod +ald i +Se a +Ä Far rell +Ä merc enaries +Ä R NC +Ä Gu ess +Ä p acing +M achine +Streamer Bot +Ä Char ity +Ä 29 8 +Ä cann ons +Ä Tob y +TPP StreamerBot +Ä Pass ion +cf g +Th om +Ä bad ges +Ä Bern stein +. ÃĸÄĸÄĩ +Ä P OP +Ä Con j +Ä initial ization +Ä biod iversity +D ub +Ä feud al +Ä disclaim er +Ä c row +Ä ign ition +ar f +S HA +Ä k Hz +h azard +Ä Art ists +oe uv +67 9 +Ä Rud y +N ine +Ä Ram adan +ÃĨ ÂŊ +itt o +Ä adren aline +C ert +Ä smell ed +Ä imp unity +Ä ag endas +Ä Re born +Ä Con cent +Ä Se ems +Ä o mega +Ä Dust in +Ä back er +Ä Sau ce +Ä Boy le +W IN +Ä sp ins +Ä pa uses +u pt +Ä shred ded +Ä stra pped +Ä Cor ruption +Ä scr atches +Ä n i +Ä att ire +Ä S AF +Factory Reloaded +Ä I PS +Ä ( % +Ä sem inar +f ocus +c ivil +Ä 18 60 +int osh +Ä contin ual +Ä abbre vi +Ä S ok +oc obo +X M +Ä fr antic +Ä unavoid able +Ä ar tery +Ä annot ations +b ath +Cl imate +Ä d ors +Ä Sl ide +co ord +Ä Rel oad +Ä L DL +Ä Love craft +Ä unim agin +Ä resemb led +Ä barr acks +n p +Ä surrog ate +Ä categor ized +ÃŖÄ¤ Š +Ä vacc inated +Ä drain age +Ä ind ist +Ä Whats App +Ä 18 70 +oler ance +inv oke +am orph +Ä recon nect +Ä em anc +Ä blind ness +Ä 12 80 +intern et +c ollar +Ä alt ru +Ä ab yss +Ä T RI +65 7 +Ä inf used +HE AD +Ä forest ry +Ä Wood y +Ä C i +w i +s am +78 4 +hol iday +Ä mog ul +Ä F ees +Ä D EN +In ternal +ur bed +f usc +at om +Ä Ill usion +Ä poll ed +Ä fl ap +Ä co ax +L GBT +An aly +Ä Sect ions +Ä Calif orn +em n +Ä h ither +Ä N IGHT +Ä n ailed +Ä Pip eline +39 1 +o of +Ä Pr imal +vere nd +Ä sl ashing +Ä ret ri +avi our +Ä depart ing +g il +IS C +Ä mid way +Ä ultras ound +Ä beh aving +Ä T ara +class es +V irtual +Ä Colon ial +Ä stri pping +Ä orchestr ated +Ä Gra ves +45 2 +Ä Iron ically +Ä Writ ers +Ä l ends +Ä Man z +Ä ra ven +Ä oxid ative +Ä 26 6 +EL F +act ually +asc ar +D raft +Ä favour able +Ä humili ating +Ä f idelity +Ä H of +Ä X uan +49 6 +Ä lay ered +at is +79 0 +Ä pay check +it on +K ar +Ä VM ware +Ä Far mer +Ä serv ic +gl omer +Ä sl ump +Ä Fab ric +Ä D OC +est ing +Ä reass ure +Ä ph yl +v olt +it ory +R ules +Ä oxid ation +Ä pri zed +Ä mist ress +Ä Dj ango +WAR N +ÃĨ Äŗ +Ä enc ode +Ä Feed back +Ä stupid ity +I an +Ä Yugoslav ia +× ¨ +ac l +UT E +19 77 +Ä qual ifies +Ä puls es +pret ty +Ä fro ze +Ä s s +Iter ator +Ä ur gently +Ä m ailed +Ä Ch am +Ä sust aining +Ä bas il +Ä pupp ies +il ant +Ä P LEASE +l ap +ace ous +F ear +Ä Master y +aut omatic +Ä T AG +Ä ant im +ag les +47 3 +fram es +Ä wh ispers +Ä Who ever +Ä bra very +Ä UK IP +ract ions +"" " +Ä t ame +Ä part ed +every thing +CON T +Ä ind ebted +Ä add r +re k +IR ED +Ä em inent +cl inton +Ä o usted +Ä review er +Ä melt down +Ä re arr +Ä Y ao +the real +aby te +Ä st umbling +Ä bat ches +Ä 25 9 +Ä contrace ptive +Ä prost itute +ens is +De cl +Ä St rikes +M ilitary +Ä O ath +v acc +pp ings +05 2 +Ä part Name +amp ing +Rep orts +K I +CH R +Ä subt ly +sw ers +Bl ake +us ual +Ä contest ants +Ä cart ridges +Ä GRE AT +Ä bl ush +Ä ÃĸÄĸ Âē +47 2 +Ä reason ed +ÃŖÄĨ ¤ +paralle led +Ä d yn +ag ate +Ä night ly +ÃĨ Ĩ +55 6 +Ä sem antic +Ä Adv oc +Ä  !! +Ä disag rees +Ä B W +V eh +Ä harm ing +Ä embr aces +Ä stri ves +Ä in land +Ä K ard +Ä he ats +Ä Gin ny +ut an +ern aut +yl ene +Ä E lev +J D +Ä h ars +Ä Star r +Ä sk ysc +Ä collabor ators +Us ually +Ä rev olutions +Ä STAT S +Ä dism antle +Ä confident ly +Ä kin etic +Al i +Ä percent ile +Ä extract ing +ill ian +est ead +Ä physic ists +Ä Marsh al +Ä fell owship +Ä d ashed +Ä U R +Ä Si oux +Ä Comp act +am ide +P ython +Ä Le igh +Ä Pharm ac +ist rates +her ical +Ä f ue +Ä E min +Ä ( { +Ä Neighbor hood +Ä disrupt ing +Ä D up +Ä g land +Ä Se v +Ä Mar ian +arg on +Ä D und +Ä < !-- +Ä str and +Ä stadium s +z os +Ä psych osis +Ä R ack +Ä brilliant ly +ï¸ Äą +Ä submer ged +Ä Inst it +Ä Ch ow +Ä c ages +Ä H ats +Ä U rs +Ä dil uted +us at +ien ne +Ä Members hip +Ä Bur k +Ä  ie +Ä arche type +D rug +ult on +Ä Sp ock +Ä McK ay +Ä Dep end +F eatured +S oc +19 78 +Ä B ere +Ä relent lessly +Ä cripp ling +Ä ar thritis +çÄļ Ł +Ä Trop ical +Ä Bul g +Ä Cher yl +Ä adm irable +Ä sub title +Over ride +Ä orig inating +Ä C CP +Ä sw ore +Ä So le +Ä Dis orders +3 29 +Ä process ion +Ä ref urb +Ä imm ersed +requ ently +Ä skept ics +Ä cer amic +m itter +en stein +b elt +Ä T IT +b idden +Ä f ir +m ist +> ] +Ä we ave +Ä Parad ox +Ä entr usted +Ä Barcl ays +Ä novel ist +og ie +80 6 +Ä nin ety +Ä disag reements +@@@@ @@@@ +Ä Aus chwitz +c ars +Ä L ET +t ub +arant ine +P OS +Ä back story +Ä cheer ful +Ä R ag +ek a +bi ased +Ä inexper ienced +ak ra +Ä W itt +t an +Ä rap ist +Ä plate au +ch al +Ä Inqu is +exp ression +Ä c ipher +Ä sh aving +add en +re ly +( \ +ism a +Ä Reg ulatory +CH AR +ily n +N VIDIA +G U +Ä mur m +la us +Christ opher +Ä contract ual +Ä Pro xy +Ä Ja ime +Ä Method ist +Ä stew ards +st a +per ia +Ä phys iology +Ä bump ed +Ä f ructose +Austral ian +Ä Met allic +Ä Mas querade +ar b +Ä prom ul +Ä down fall +Ä but cher +Ä b our +Ä IN FORMATION +Ä B is +pect s +ad ena +Ä contempl ating +ar oo +cent ered +Ä Pe aks +Us ed +Ä mod em +Ä g enders +Ä 8 000 +37 1 +Ä m aternity +Ä R az +Ä rock ing +Ä handgun s +Ä D ACA +Aut om +Ä N ile +Ä tum ult +Ä Benef it +Ä Appro ach +works hop +Ä Le aving +G er +inst ead +Ä vibr ations +Ä rep ositories +49 7 +Ä A unt +Ä J ub +Ä Exp edition +Al pha +Ä s ans +Ä overd ue +Ä overc rowd +Ä legisl atures +Ä p aternal +Ä Leon ardo +Ä exp ressive +Ä distract ions +Ä sil enced +tr ust +Ä b iking +Ä 5 60 +Ä propri et +Ä imp osition +Ä con glomer +Ä = ================================================================ +Ä Te aching +Ä Y ose +int ensive +T own +Ä troll ing +Ä Gr ac +Ä AS US +Y o +Ä special s +Ä Nep h +Ä God zilla +Dat abase +Ä He gel +Ä 27 2 +19 76 +Ä Gl oria +Ä dis emb +Ä Investig ations +Ä B ane +ag ements +St range +Ä tre asury +Ä Pl ays +Ä undes irable +Ä wid ening +Ä verb ally +Ä inf ancy +Ä cut ter +f ml +Ä 21 00 +prot otype +f ine +Ä dec riminal +Ä dysfunction al +Ä bes ie +Ä Ern st +z eb +Ä nort heastern +Ä a ust +por ate +Ä Mar lins +Ä segreg ated +ew orld +Ä Ma her +Ä tra verse +Ä mon astery +ur gy +G ear +s and +Com pl +Ä E MP +Ä pl ent +Ä Mer cer +Ä 27 6 +TA BLE +Config uration +H undreds +Ä pr ic +Ä collabor ating +Ä Par amount +Ä Cumm ings +Ä ( < +Ä record er +Ä fl ats +Ä 4 16 +wh ose +Font Size +Ä Or bit +Y R +Ä wr ists +Ä b akery +) } +Ä B ounty +Ä Lanc aster +Ä end ings +acc ording +Ä Sal am +e asy +75 5 +Ä Bur r +Ä Barn ett +onom ous +Un ion +Ä preced ence +Ä Scholars hip +Ä U X +Ä roll out +Ä bo on +al m +Ä Can ter +ÃĻ Âĩ +Ä round ing +Ä cl ad +Ä v ap +Ä F eatured +is ations +Ä 5 40 +pol ice +Ä unsett ling +Ä dr ifting +Ä Lum ia +Ä Obama Care +Ä F avor +Hy per +Ä Roth schild +Ä Mil iband +an aly +Ä Jul iet +H u +Ä rec alling +a head +69 6 +Ä unf avorable +Ä d ances +O x +Ä leg ality +Ä 40 3 +rom ancer +Ä inqu ire +Ä M oves +\ "> +Ä Vari ant +Ä Mess iah +Ä L CS +Ä Bah ÃƒÂĄ +75 6 +Ä eyeb row +Ġ ÂĨ +Ä Mc F +Ä Fort y +M as +Ä pan icked +Ä transform ations +q q +Ä rev olves +ring e +Ä A i +ax e +Ä on ward +Ä C FR +Ä B are +log in +Ä liqu ids +Ä de comp +second ary +il an +Ä Con vert +ami ya +Ä prosecut ing +Ä ÃĸÄĢ ÂĄ +Ä York ers +Ä Byr ne +sl ow +aw ei +J ean +Ä 26 9 +Ä Sky dragon +Ä  Ê +Ä Nicarag ua +Ä Huck abee +Ä High ly +Ä amph ib +Ä Past or +Ä L ets +Ä bl urred +Ä visc eral +Ä C BO +Ä collabor ated +z ig +Leg al +Ä apart heid +Ä br id +Ä pres et +Ä D ET +Ä AM A +× Äļ +arch ing +auc uses +build er +Ä po etic +Ä em ulator +Ä Mole cular +Ä hon oring +ise um +Ä tract or +Ä Cl uster +Ä Cal m +ared evil +Ä sidew alks +Ä viol in +Ä general ized +Ä Ale c +Ä emb argo +Ä fast ball +Ä HT TPS +Ä L ack +Ä Ch ill +ri ver +C hel +Ä Sw arm +Ä Lev ine +ro ying +L aunch +Ä kick er +Ä add itive +Ä De als +W idget +cont aining +Ä escal ate +Ä OP EN +Ä twe aked +Ä st ash +Ä sp arks +Ä Es sex +Ä E cc +Ä conv ict +Ä blog ging +I ER +Ä H L +Ä murd erers +75 9 +Ä H ib +Ä de pl +Ä J ord +S ac +Ä dis sect +Ä How e +os her +Ä custom izable +Ä Fran z +Ä at ro +Ä ÄŠ +Ä 000 4 +Ä out post +R oss +Ä glyph osate +Ä Hast ings +Ä BE FORE +Ä sh ove +o pped +Ä Sc ala +Ä am ulet +an ian +Ä exacerb ated +Ä e ater +47 1 +UM E +Ä pul p +izont al +Ä Z am +Ä AT I +imm une +aby tes +Ä unnecess arily +Ä C AT +Ä Ax is +Ä visual ize +à ÄĢ +Ä Rad ical +f m +Doc uments +Ä For rest +Ä context ual +Ä Sy mbol +Ä tent ative +Ä DO ES +Ä Good s +Ä intermitt ent +} : +medi ated +Ä ridic ule +Ä athe ism +Ä path ogens +Ä M um +Ä re introdu +Ä 30 7 +i HUD +Ä flash light +Ä sw earing +Ä p engu +B u +Ä rot ated +Ä Cr ane +Ä () ); +Ä fashion able +Ä endors ing +46 3 +) [ +Ä ingest ion +Ä cook s +Ä 9 50 +ot omy +Ä Im am +Ä k a +Ä te aser +Ä Ghost s +Ä ÃŖÄ¤ Âĩ +19 69 +Ï ÄĨ +ub by +Ä conver ter +zan ne +end e +Ä Pre par +Ä Nic kel +Ä Chim era +h im +Ä Tyr ann +Ä Sabb ath +Ä Nich ols +Ä ra pt +ih ar +Ä she lling +Ä illum inate +Ä dent ist +ut or +Ä Integ ration +Ä wh ims +Ä Liter ary +Be aut +Ä p archment +ag ara +Br and +Ä der og +ÃĸÄĸÂĻ ) +Ä Nor se +Ä unw itting +Ä c uc +Ä border line +Ä upset ting +Ä rec ourse +Ä d raped +Ä Rad ar +Ä cold er +Ä Pep si +im inary +], [ +65 8 +V i +Ä F rem +Ä P es +Ä veter inary +Ä T ED +Ä Ep idem +n ova +k id +Ä dev out +o ct +j ad +M oh +Ä P AY +Ä ge ometric +Ä 3 23 +Ä circum ference +ich ick +19 75 +Ä Y uri +Ä Sh all +Ä H over +un in +S pr +Ä g raft +Ä Happ iness +Ä disadvant ages +att acks +Ä hub s +Ä Star Craft +Ê ĸ +Ä gall eries +Ä Kor ra +Ä grocer ies +Ä Gors uch +Ä rap ists +Ä fun gi +Ä Typh oon +V ector +Ä Em press +b attle +4 68 +Ä paras ite +Ä Bom ber +S G +ex ist +Ä P f +Ä un se +Ä surge ons +B irth +Ä Un sure +Ä Print ed +Ä Behavior al +Ä A ster +Pak istan +Ä un ethical +Ä s v +Ä Io T +Ä lay outs +P ain +Ä const ants +Ä L W +Ä B ake +Ä tow els +Ä deterior ation +Ä Bol ivia +Ä blind ed +Ä W arden +Ä Mist ress +Ä on stage +Ä cl ans +Ä B EST +19 60 +Ä ant ique +Ä rhet orical +Ä Per cy +Ä Rw anda +, . +B ruce +Ä tra umat +Ä Parliament ary +Ä foot note +id ia +Ä Lear ned +se eking +gen ic +Ä dim ensional +H ide +èÄĸ ħ +Ä intrig ue +in se +Ä le ases +Ä app rentices +w ashing +Ä 19 26 +V ILLE +Ä sw oop +s cl +Ä bed rooms +on ics +Ä Cr unch +comp atible +Ä incap ac +Ä Yemen i +ash tra +z hou +d anger +Ä manifest ations +Ä Dem ons +AA F +Secret ary +ACT ED +L OD +Ä am y +ra per +eth nic +4 17 +Ä pos itives +Ä 27 3 +Ä Refuge es +Ä us b +Ä V ald +odd y +Ä Mahm oud +As ia +Ä skull s +Ä Ex odus +Ä Comp et +Ä L IC +Ä M ansion +Ä A me +Ä consolid ate +storm s +ont ent +99 6 +Ä cl en +Ä m ummy +fl at +75 8 +Ä V OL +oter ic +n en +Ä Min ute +S ov +Ä fin er +R h +ly cer +Ä reinforce ments +Ä Johann es +Ä Gall agher +Ä gym n +S uddenly +Ä ext ortion +k r +i ator +T a +Ä hippocamp us +N PR +Ä Comput ing +Ä square ly +Ä mod elling +Ä For ums +Ä L isp +Ä Krish na +Ä 3 24 +Ä r ushes +Ä ens ued +Ä cre eping +on te +n ai +il ater +Ä Horn ets +Ä ob livious +IN ST +55 9 +Ä jeopard y +Ä distingu ishing +j ured +Ä beg s +sim ilar +ph ot +5 30 +Ä Park way +Ä s inks +Ä Hearth stone +ib ur +Ä Bat on +Av oid +Ä d ancer +Ä mag istrate +ary n +Ä disturb ances +Ä Rom ero +Ä par aph +Ä mis chief +Ãĸĸ Äĩ +Ä Sh aria +Ä ur inary +r oute +iv as +f itted +Ä eject ed +Ä Al buquerque +Ä 4 70 +Ä irrit ated +Ä Z ip +Ä B iol +à į +Ä den ounce +Ä bin aries +Ä Ver se +Ä opp os +Ä Kend rick +Ä G PL +Ä sp ew +Ä El ijah +Ä E as +Ä dr ifted +so far +Ä annoy ance +Ä B ET +47 4 +Ä St rongh +it ates +Ä Cogn itive +oph one +Ä Ident ification +ocr ine +connect ion +Ä box er +Ä AS D +Ä Are as +Y ang +t ch +ull ah +Ä dece ive +Comb at +ep isode +cre te +W itness +Ä condol ences +ht ar +Ä he als +Ä buck ets +Ä LA W +B lu +Ä sl ab +Ä OR DER +oc l +att on +Ä Steven son +Ä G inger +Ä Friend ly +Ä Vander bilt +sp irit +ig l +Ä Reg arding +Ä PR OG +Ä se aling +start ing +Ä card inal +Ä V ec +Ä Be ir +Ä millisec onds +we ak +per se +Ä ster ile +Ä Cont emporary +Ä Ph ant +Ä Cl o +Ä out p +Ä ex iled +Ä 27 7 +Ä self ie +Ä man ic +Ä n ano +ter ms +Alex ander +Ä res olves +Ä millenn ia +Ä expl odes +Ä const ellation +Ä adul tery +m otion +D OC +Ä broad casters +Ä kinderg arten +Ä May weather +Ä E co +ich o +Ä 28 7 +l aun +Ä m ute +Ä disc reet +Ä pres chool +Ä pre empt +De lete +Ä Fre ed +P i +H K +Ä block er +Ä C umber +Ä w rought +d ating +Ä ins urer +Ä quot as +Ä pre ached +Ä ev iction +Ä Reg ina +Ä P ens +Ä sevent een +Ä N ass +D ick +Ä fold s +Ä d otted +Ä A ad +Un iversal +Ä p izz +Ä G uru +Ä so ils +Ä no vice +Ä Ne ander +Ä st ool +Ä deton ated +Ä Pik achu +Ä Mass ive +IV ER +Ä Ab del +Ä subdu ed +Ä tall est +Ä prec arious +Ä a y +r ification +Ä Ob j +c ale +Ä un question +cul osis +ad as +igr ated +D ays +Ä que ens +Ä Gaz ette +Ä Col our +Ä Bow man +Ä J J +ï ve +Ä domin ates +Stud ent +Ä m u +Ä back log +Ä Elect ro +Tr uth +48 3 +Ä cond ensed +r ules +Ä Cons piracy +Ä acron ym +hand led +Ä Mat te +j ri +Ä Imp ossible +l ude +cre ation +Ä war med +Ä Sl ave +Ä mis led +Ä fer ment +Ä K ah +ink i +ke leton +cy l +Ä Kar in +Hun ter +Reg ister +Ä Sur rey +Ä st ares +Ä W idth +Ä N ay +Ä Sk i +Ä black list +uck et +Ä exp ulsion +im et +Ä ret weet +vant age +Fe ature +Ä tro opers +Ä hom ers +9 69 +Ä conting ency +Ä W TC +Ä Brew er +fore ign +W are +S olar +Ä und ue +RE C +ulner able +path ic +Ä Bo ise +Ä 3 22 +Ä arous ed +Ä Y ing +ä¸ į +uel ess +Ä p as +Ä mor p +Ä fl oral +Ex press +ud ging +k B +Ä Gr anted +Ø ¯ +Ä Mich a +Ä Goth ic +Ä SPEC IAL +Ä Ric ardo +F ran +Ä administer ing +6 20 +por a +Ġ Ž +Ä comprom ises +Ä b itten +Ac cept +Th irty +Ð ² +Ä mater ially +Ä Ter r +ig matic +ch ains +Ä do ve +stad t +Mar vel +FA ULT +Ä wind shield +Ä 3 36 +ad ier +Ä sw apping +Ä flaw less +Ä Pred ator +Ä Miche le +Ä prop ulsion +Ä Psych ic +Ä assign ing +Ä fabric ation +Ä bar ley +l ust +Ä tow ering +Ä alter cation +Ä Bent ley +Sp here +Ä tun a +Ä Class es +Fre edom +un er +L ady +v oice +Ä cool est +or r +Ä pal p +$ { +Ä hyster ia +Ä Met atron +p ants +Ä spawn ing +Exper ts +Ä Invest ors +Ä An archy +Ä shr unk +Ä Vict im +Ä 28 9 +Ä ec stasy +Ä B inding +58 5 +Ä Mel ody +57 8 +ot ally +Ä E tsy +lig a +Ä applaud ed +Ä swe ating +Ä redist ributed +Ä pop corn +Ä sem inal +f ur +Ä Neuro science +R and +Ä O st +Ä Madd en +Ä Incre asing +Ä Daw kins +Ä Sub way +Ä ar sen +cons erv +B UR +Ä sp iked +Ä Ly ft +Ä Imper ium +Ä Drop box +Ä fav oured +Ä encomp asses +gh ost +Ä ins pires +Ä bur geoning +Ä Y oshi +Ä Vert ical +Ä Aud itor +Ä int ending +Ä filib uster +Bl oom +f ac +Ä Cav s +ign ing +Ä cowork ers +Ä Barb arian +rem ember +FL AG +Ä audit ory +ason ry +Col lege +Ä mut ed +gem ony +ob in +Ä Psych o +9 68 +Ä lav ish +Ä hierarch ical +Ä Dr one +ou k +Ä cripp led +Ä Max im +Sl ot +Ä qu iz +Ä V id +if ling +Ä archae ologists +Ä abandon ment +d ial +le on +Ä F as +T ed +Ä r aspberry +Ä maneu vers +Ä behavi ours +Ä ins ure +Ä rem od +Sw itch +h oe +Ä sp aced +Ä afford ability +Ä F ern +not ation +Ä Bal anced +Ä occup ies +en vironment +Ä neck lace +Ä sed an +F U +Ä Brav o +Ä ab users +Ä An ita +met adata +Ä G ithub +ait o +Ä F aster +Ä Wass erman +Ä F lesh +Ä th orn +r arily +Ä Mer ry +w ine +Ä popul ace +Ä L ann +Ä repair ing +Ä psy che +Ä mod ulation +aw aru +ÃĸÄĸÄ­ ÃĸÄĸÄ­ +ari j +Ä decor ations +Ä apolog ise +Ä G arg +app ly +Ä give away +Ä Fl an +Ä Wy att +U ber +Ä author ised +Ä Mor al +HAHA HAHA +activ ate +Ä torped o +Ä F AR +Ä am assed +Ä A ram +ark in +Ä Vict ims +st ab +Ä o m +Ä E CO +Ä opio ids +Ä purpose ly +Ä V est +Ä er g +at an +Ä Sur gery +Ä correct ing +Ä Ort iz +Ä Be et +Ä rev oke +Ä fre eway +Ä H iggins +F ail +Ä Far ms +Ä AT P +h ound +Ä p oking +Ä Commun ists +mon ster +iment ary +Ä unlock ing +Ä unf it +we ed +en ario +at ical +Ä Enlight enment +Ä N G +Ä Comp ensation +de en +Ä Wid ow +Ä Cind y +Ä After wards +Ä 6 000 +ikh ail +ag ically +Ä rat ified +Ä casual ty +H OME +p sey +f ee +Ä spark ling +Ä d Ê +Ä concert ed +C atal +Ä comp lying +Ä A res +Ä D ent +Sh ut +Ä sk im +ad minist +Ä host ilities +Ä G ins +Ä 6 08 +Ä m uddy +Ä Mc Int +Ä Dec ay +5 25 +Ä conspic uous +Ä Ex posure +Ä resc ind +Ä wear able +Ä 3 28 +our met +ah s +Ä Rob ots +Ä e clips +inst ance +Ä RE PORT +Ä App l +0 30 +Ä Sk ies +01 00 +Ä fall acy +S ocket +Ä Rece iver +Ä sol ves +Ä Butter fly +Ä Sho pping +Ä FI RE +65 4 +Med ic +Ä sing ers +Ä Need less +'' '' +isher s +Ä D ive +58 8 +Ä select ively +Ä cl umsy +88 9 +Ä purch aser +ear ned +ard y +Ä benef iting +eng lish +Ä yield ing +Ä P our +Ä spin ach +Ä del ve +Ä C rom +6 10 +Ä export ing +Ä MA KE +Ä 26 3 +Ä g rop +Ä env oy +Ä Inqu iry +Ä Lu igi +d ry +Ä T uring +Thumbnail Image +Ä Var iety +Ä fac et +Ä fl uffy +Ä excerpt s +Ä sh orth +Ä Ol sen +CL UD +Ä rel iant +Ä UN C +T our +Ä bat hing +Comp any +Ä global ization +P red +Ä Malf oy +Ä h oc +j am +craft ed +Ä Bond s +Ä Kiss inger +Eng land +Ä order ly +cat entry +Ä 26 1 +Ä exch anging +Ä Int ent +Ä Amend ments +D OM +Ä st out +³³³³³³³³ ³³³³³³³³ +Ä Air bus +Ä 27 8 +hy de +P oll +Item ThumbnailImage +Ä looph oles +Ä Pill ar +Ä expl or +St retch +A part +Ä un married +Lim it +Ä Transform ers +Ä intellect ually +unct ure +18 00 +Ä d arn +B razil +Ä left over +ber us +f red +Mine craft +3 26 +Ä Form s +Ä proof s +Ä Des igned +Ä index es +Ä Supp ose +EM S +Ä L oving +Ä Bon nie +im ating +OT US +Ä conduct or +Ä behav ed +Ä F ren +Ä sy nerg +Ä millenn ium +Ä cater ing +Ä L auder +W r +Ä Y iannopoulos +Ä AT F +Ä ensl aved +Ä awaken ed +D VD +Ä ED ITION +Ä Conc ert +Ä Chall enger +Ä H aku +umer ic +Ä dep recated +Ä SH AR +4 12 +Ä dy stop +Ä tremb ling +Ä dread ed +Ä Sp ac +p adding +Re pl +Ä G arrison +M ini +Ä un paralleled +am ar +URR ENT +w reck +c ertain +t al +Ä C LS +app ings +Ä sens ed +Ä f encing +Ä Pas o +Ä Des k +Ä sc off +Ä contem plate +Ä L iga +l iquid +75 7 +Ä app rentice +Ä UCH IJ +5 70 +Ä Th ousand +Ä Ill um +Ä champion ed +ÃŖÄ¤ ÄŽ +Ä elect ors +Ä 3 98 +Ä H ancock +round ed +Ä J OHN +Ä uns atisf +Ä qual ifier +Ä Gad get +EN E +Ä dead liest +Ä Pl ants +Ä  ions +Ä acc ents +Ä twe aking +Ä sh aved +F REE +Ä Ch aser +Again st +9 60 +Ä meth amphetamine +Ä normal ized +Ä $ \ +Ä Pre cision +Ä Gu am +Ä ch oked +Ä X II +Ä Cast ing +Tor rent +Ä scal p +Ä Jagu ar +w it +Ä sem ic +ix ie +Ä G ould +Ä conf ines +N usra +Ä L on +Ä J ugg +y cle +Ä Cod ec +E gypt +Ä rest rain +Ä Al iens +Ä ch oking +Ä D unk +Ä Bell a +ab c +Ä sl ang +Ä neuro trans +s av +Ä empower ment +Ãĸ ĨĴ +Ä clim bers +Ä M im +Ä F ra +ros se +Cap ital +Ä Cth ulhu +Inter face +Ä prof icient +Ä IN TO +Ä 3 18 +ront al +5 80 +Ä Des pair +K enn +Ä scrim mage +Ä Co at +as ions +Ä wall paper +Ä J ol +Ä resurg ence +Ä ant iv +Ä B alls +² ž +Ä buff ers +Ä sub system +Ä St ellar +Ä L ung +A IDS +Ä erad icate +Ä blat antly +Ä behav es +Ä N un +Ä ant ics +ex port +DE V +w b +Ä ph p +Ä Integ rity +Ä explore r +Ä rev olving +auth ored +g ans +Ä bas k +Ä as ynchronous +ÃĨ į +TH ING +69 8 +G ene +Ä R acer +Ä N ico +iss ued +Ä ser mon +p ossibly +Ä size of +Ä entrepreneur ial +ox in +Ä Min erva +Ä pl atoon +n os +ri ks +A UT +Ä Aval anche +Ä Des c +Äŗ ÃĨÂŖÂĢ +Ä P oc +Ä conf erred +Î Âģ +Ä pat ched +F BI +66 2 +Ä fract ures +Ä detect s +Ä ded icate +Ä constitu ent +Ä cos mos +W T +Ä swe ats +Ä spr ung +b ara +s olid +Ä uns us +Ä bul ky +Ä Philipp e +Ä Fen rir +Ä therap ists +ore al +^^ ^^ +Ä total ed +Ä boo ze +Ä R PC +Prosecut ors +Ä dis eng +Ä Sh ared +Ä motor cycles +Ä invent ions +Ä lett uce +Ä Mer ge +Ä J C +Ä spiritual ity +Ä WAR NING +Ä unl ucky +Ä T ess +Ä tong ues +Ä D UI +T umblr +Ä le ans +Ä inv aders +Ä can opy +Ä Hur ricanes +Ä B ret +Ä AP PLIC +id ine +ick le +Reg arding +Ä ve ggies +Ä e jac +ju ven +F ish +D EM +Ä D ino +Th row +Ä Check ing +be ard +( & +Ä j ails +Ä h r +trans fer +iv ating +Ä fle ets +Ä Im ag +Ä Mc Donnell +Ä snipp et +Is a +Ä Ch att +Ä St ain +Ä Set FontSize +Ä O y +Ä Mathemat ics +49 4 +Ä electro ly +Ä G ott +Ä Br as +B OOK +Ä F inger +d ump +Ä mut ants +Ä rent als +Ä inter tw +Ä c reek +ail a +Bro ther +Ä Disc ord +pe e +raw ler +Ä car p +Ä 27 9 +ÃŖÄ¤Âˇ ÃŖÄĨÂŖ +rel ations +Ä contr asts +Col umn +Ä rec onnaissance +Ä un know +Ä l ooting +Ä regul ates +Ä opt imum +Ä Chero kee +Ä A ry +Lat est +Ä road side +Ä d anced +Ä Unic orn +A cknowled +Ä uncont roll +Ä M US +at io +ch ance +ha ven +VAL UE +Ä favour ites +Ä ceremon ial +b inary +pe ed +wood s +EM P +Ä v ascular +Ä contempl ated +Ä bar ren +Ä L IST +Y ellow +ospons ors +Ä whisk y +Ä M amm +Ä DeV os +min imum +H ung +44 2 +P ic +Ä Snap dragon +77 6 +Ä car ving +Ä und ecided +Ä advantage ous +Ä pal ms +Ä A Q +Ä st arch +L oop +Ä padd le +Ä fl aming +Ä Hor izons +An imation +bo ost +Ä prob abilities +Ä M ish +Ä ex odus +Ä Editor ial +Ä fung us +Ä dissent ing +Ä Del icious +rog ram +Ä D yn +d isk +t om +Ä fab rics +Ä C ove +Ä B ans +Ä soft en +Ä CON S +Ä in eligible +Ä estim ating +Ä Lex ington +pract ice +of i +Ä she dding +Ä N ope +Ä breat hed +Ä Corinth ians +y ne +ek i +B ull +Ä att aching +reens hots +Ä analy se +Ä K appa +Ä uns ustainable +Ä inter pol +ank y +he mer +Ä prot agonists +Ä form atted +Ä Bry ce +Ä Ach illes +Ä Ab edin +sh ock +Ä b um +b os +qu a +Ä W arn +q t +Ä Di abetes +8 64 +Ä In visible +Ä van ish +Ä trans mitting +Ä mur ky +Ä Fe i +Ä awa ited +Ä Jur assic +umm ies +Ä men acing +g all +C ath +B uilt +ild o +Ä V otes +Ä on t +Ä mun itions +Ä Fre em +ÃŃ n +Ä dec ency +lo pp +ie ved +Ä G ord +Ä un thinkable +Ä News week +Ä 3 21 +He at +Ä present er +ji ang +Ä pl ank +Ä Aval on +Ä ben z +Ä R out +Ä slam ming +Ä D ai +ou ter +Ä Cook ie +Ä Alic ia +ge y +Ä van ity +Ä ow l +ÃĄ Âĩ +t ested +Ä Aw akens +Ä can v +Ä blind ly +Ä Rid ley +Ä Em ails +Requ ires +Ä Ser bian +ograp hed +if rame +eter ia +Ä altern ating +qu iet +Ä soc iology +Ä Un lock +Ä Commun ism +Ä o ps +Ä att ribution +Ä ab duction +Ä Ab ram +Ä sidel ined +Ä B OOK +Ä ref ining +Ä Fe eling +Ä Os lo +Ä Pru itt +r ack +ang ible +Ä caut iously +Ä M ARK +eed s +M ouse +Ä Step h +Ä P air +S ab +99 7 +Ä Ba al +B ec +Ä comm a +Ä P all +Ä G ael +Ä misunder stand +Ä P esh +Order able +Ä dis mal +Ä Sh iny +% " +Ä real istically +Ä pat io +Ä G w +Ä Virt ue +Ä exhaust ing +wh atever +oph ys +y ip +4 18 +Ad just +Ä Wa iting +ess on +Ä Maz da +Ä Do zens +Ä stream lined +Ä incompet ence +Ä M eth +Ä eth os +ON ES +Ä incent iv +Ä gr itty +Ä But cher +Head er +Ä exp onential +Ã Ł +Ä correl ate +Ä cons ensual +s ounding +R ing +Orig in +Ä con clusive +fe et +ac ly +Ä F ernandez +Buy able +Ä d ucks +aunt lets +Ä el ong +Ä 28 6 +Ä sim ul +G as +Ä K irst +Ä prot r +Ä Rob o +Ä Ao E +op ol +Ä psych ologically +sp in +ilater ally +Ä Con rad +W ave +44 1 +Ä Ad vertisement +Ä Harm on +Ä Ori ental +is Special +Ä presum ptive +Ä w il +Ä K ier +ne a +Ä p pm +Ä har bour +Ä W ired +comp any +Ä cor oner +atur days +Ä P roud +Ä N EXT +Ä Fl ake +val ued +ce iver +Ä fra ught +Ä c asing +Ä run away +Ä g in +Ä Laure nt +Ä Har lem +Ä Cur iosity +qu ished +Ä neuro science +Ä H ulu +Ä borrow er +Ä petition er +Ä Co oldown +W ARD +Ä inv oking +conf idence +For ward +Ä st s +pop ulation +Delivery Date +Fil m +Ä C ov +quick Ship +quickShip Available +prim ary +isSpecial Orderable +inventory Quantity +channel Availability +BO X +Ä Multi player +Ä Jen ner +77 8 +Ä M d +Ä ~ /. +M N +Ä child ish +Ä antioxid ant +Ä Chrom ebook +Ä 27 4 +Ä screen play +Ä advent urous +Ä Relations hip +respons ive +ming ton +Ä corner stone +Ä F ey +F IR +Ä rook ies +Ä F eaturing +Ä orig inate +Ä electro des +ant es +Ä script ures +Ä gl ued +Ä discont ent +Ä aff licted +lay out +B rave +Ä m osa +Ä Quant ity +Ä H ik +w inner +H ours +Ä ent ail +Ä Cell s +olog ue +Ä v il +Ä pre acher +Ä decor ative +d ifferent +Ä prejud ices +Ä Sm oking +Ä Notting ham +so Type +Ä rhyth ms +Ä Al ph +bl ast +Ste el +Ä Daniel le +Ä str ife +Ä rem atch +so DeliveryDate +Ä F ork +t rip +ol ulu +hes es +C G +Ä POLIT ICO +ost a +Ä Dr ift +ʞįÃĨ ÂĨ +ʞįÃĨÂĨ ÄŗÃĨÂŖÂĢ +Ä vet ting +Ä Jin ping +Ä Rec ession +Min or +Ä F raud +enf ranch +Ä conven ed +Ä NA ACP +Ä Mill ions +Ä Farm ing +Ä W oo +Ä Fl are +rit o +imm igrant +Ä vac ancy +Ä HE AD +Ä V aj +eg al +Ä V igil +Stud y +Ä ru ining +Ä r acks +Ä he ater +Ä Rand olph +Ä Br ush +Ä T ir +Ø ¨ +Ä c ov +% ] +Ä recount s +Ä O PT +Ä M elt +Ä tr uce +Ä cas inos +Ä crus ade +Ä carn age +Ä stri pe +Ä K yl +Text ures +Ä 6 98 +Ä pro clamation +Ä good ies +Ä ........ .. +pro claimed +P olit +Ä top ical +Ä special ize +Ä A min +g m +Ä anch ored +Ä bear ings +s ample +Ä High land +Ä Aut ism +Ä merc enary +Ä interview er +L ER +Ä Som ers +Ä embry o +Ä Ass y +Ä 28 1 +Ä Ed iting +Ä Ch osen +6 60 +Ä p ci +Ä Thunder bolt +BI LL +Ä chuck led +jri wal +h of +Ä earth ly +() { +ind ependence +Ä disp ers +Ä V endor +Ä G areth +Ä p als +P enn +Ä Sub mit +ic um +Th u +Ä cl andestine +Ä cann ibal +Ä Cl erk +E Stream +gal itarian +ÃĸÄģ ÂĨ +g ew +Ä hor rend +Ä L ov +Ä Re action +ocr in +Class ic +Ä echo ing +Ä discl osing +Ä Ins ight +og un +Ä Inc arn +upload s +pp erc +guy en +Ä 19 01 +Ä B ars +68 7 +Ä b ribes +Ä Fres no +ur at +Ä Re ese +Ä intr usive +Ä gri pping +Ä Blue print +Ä R asm +un ia +man aged +Ä Heb do +Ä 3 45 +Ä dec oding +Ä po ets +Ä j aws +Ä F IGHT +am eless +Ä Mead ows +Ä Har baugh +Inter view +Ä H osp +Ä B RA +Ä delet ion +m ob +W alker +Ä Moon light +Ä J ed +Ä Soph ia +Ä us ur +Ä fortun ately +Ä Put ting +Ä F old +Ä san itation +Ä part isans +IS ON +B ow +Ä CON C +Ä Red uced +Ä S utton +Ä touch screen +Ä embry os +ÃĸÄĸÂĸÃĸÄĸÂĸ ÃĸÄĸÂĸÃĸÄĸÂĸ +Ä K rug +com bat +Ä Pet roleum +Ä am d +Ä Cos mos +Ä presc ribing +Ä conform ity +ours es +Ä plent iful +Ä dis illusion +Ä Ec ology +itt al +Ä f anc +Ä assass inated +regn ancy +Ä perenn ial +Ä Bul lets +Ä st ale +Ä c ached +Ä Jud ith +Ä Dise ases +All en +Ä l as +Ä sh ards +Ä Su arez +Ä Friend ship +inter face +Ä Supp orters +add ons +46 2 +Ä Im ran +Ä W im +Ä new found +Ä M b +An imal +Ä d arling +and e +Ä rh y +Ä Tw isted +pos al +yn ski +Var ious +× Äž +Ä K iw +uy omi +Ä well being +Ä L au +an os +Ä unm ist +Ä mac OS +Ä rest room +Ä Ol iv +Ä Air ways +Ä timet able +9 80 +Ä rad ios +v oy +ias co +Ä cloud y +Ä Draw ing +Any thing +Sy ria +Ä H ert +st aking +Ä un checked +Ä b razen +Ä N RS +69 7 +onom ic +est ablish +Ä l eng +Ä di agonal +Ä F ior +L air +Ä St ard +Ä def icient +jo ining +be am +Ä omn ip +Ä bl ender +Ä sun rise +Mo ore +Ä F ault +Ä Cost ume +Ä M ub +Fl ags +an se +Ä pay out +Ä Govern ors +Ä D illon +Ä Ban ana +N ar +Ä tra iled +Ä imperial ist +um ann +ats uki +4 35 +Ä Road s +Ä sl ur +Ä Ide ally +Ä t renches +C trl +Ä mir rored +Ä Z el +Ä C rest +Comp at +Ä Roll s +sc rib +Ä Tra ils +omet ers +w inter +Ä imm ortality +il ated +Ä contrad icts +un iversal +ill ions +Ä M ama +opt im +AT URE +Ä ge o +et ter +Ä Car lo +4 24 +Ä canon ical +Ä Strongh old +n ear +Ä perf ume +Ä orche stra +od iac +Ä up he +Ä reign ing +vers ive +Ä c aucuses +Ä D EM +Ä insult ed +Ä ---- -- +Ä Cr ush +Ä root ing +Ä Wra ith +Ä wh ore +Ä to fu +C md +Ä B ree +Ä $ _ +Ä r ive +Ä Ad vertising +Ä w att +Ä H O +Ä persu asive +Ä Param eters +Ä observ ational +Ä N CT +Ä Mo j +Ä Sal on +Ä tr unc +Ä exqu isite +Ä Mar a +Ä po op +Ä AN N +Ex c +Ä Wonder ful +Ä T aco +Ä home owner +Ä Smith sonian +orpor ated +mm mm +Ä lo af +Ä Yam ato +Ä Ind o +Ä cl inging +ÃƒÂĄ s +Ä imm utable +h ub +Or ange +Ä fingert ips +Ä Wood en +Ä K idd +Ä J PM +Ä Dam n +C ow +c odes +48 2 +Ä initi ating +Ä El k +Ä Cut ting +Ä absent ee +Ä V ance +Ä Lil ith +G UI +Ä obsc ured +Ä dwar ves +Ä Ch op +Ä B oko +Val ues +Ä mult imedia +Ä brew ed +Reg ular +CRIP TION +Ä Mort al +Ä a pex +Ä travel er +Ä bo ils +Ä spray ing +Rep resent +Ä Stars hip +4 28 +Ä disappro val +Ä shadow y +Ä lament ed +Ä Re place +Ä Fran ç +67 7 +d or +Ä unst oppable +Ä coh orts +gy n +Ä Class ics +Ä Am ph +Ä sl uggish +Ä Add iction +Ä Pad res +Ä ins cription +Ä in human +min us +Ä Jere miah +at ars +Ter ror +Ä T os +Ä Sh arma +ast a +c atch +Ä pl umbing +Ä Tim bers +Sh ar +H al +Ä O sc +Ä cou pling +hum ans +Ä sp onge +Ä id ols +Ä Sp a +Ä Adv ocate +Ä Be ats +lu a +Ä tick ing +Ä load er +Ä G ron +8 10 +Ä stim ulated +Ä side bar +Ä Manufact urer +ore And +19 73 +Ä pra ises +Ä Fl ores +dis able +Ä Elect rical +ra ise +E th +Ä migr ated +Ä lect urer +K ids +Ä Ca vern +Ä k ettle +Ä gly c +Ä Mand ela +Ä F ully +ÃĨ§ ÂĢ +FIN EST +Ä squee zing +Ä Ry der +amp oo +oreAnd Online +Inst oreAndOnline +Buyable InstoreAndOnline +Ä commem orate +Ä Ramp age +Aust in +Ä Sh roud +Ä Ru ins +9 15 +Ä K H +Ä water front +Ä E SC +b aby +Ä C out +Ä Em blem +Ä equival ents +49 2 +Un ique +Ä Niet zsche +brow ser +Ä im itation +Ä Were wolf +Ä Kir in +ac as +' ," +Ġà ž +Review ed +Ä c unt +Ä vo ic +Ä Len ovo +Ä bond ed +48 1 +Ä inhib itors +Ä endeav ors +Ä Hav ana +Ä St out +Ä J olly +A ctor +*/ ( +Ä occur rences +Ä T ens +Incre ased +Ä ACT ION +Ä  ÃŖÄĸÄŽ +Ä Rank ings +Ä B reat +Ä 30 9 +D ou +Ä impact ing +Ä Duc hess +pre fix +Q B +Ä summon ing +Ä best owed +Ä Ke pler +Ä POW ER +c ube +Ä K its +Ä G rip +Ä op ium +Ä rep utable +t oc +ich ael +Ä R ipple +Ä caf Ê +Ä Z oom +Ä Bur ma +Ä wa ive +Ä st alls +Ä dem eanor +inc erity +Ä fluor ide +Ä SH OULD +Par is +Ä long ing +Ä pl at +Ä gross ly +Ä bull s +Ä showc asing +ex pected +Ä G addafi +engine ering +Re peat +Ä K ut +Ä conce ivable +Ä trim med +osc ope +Ä Cand idate +Ä T ears +rol og +Lew is +S UP +Ä road map +Ä sal iva +Ä trump et +Jim my +Ä mirac ulous +Ä colon ization +Ä am put +Ä GN OME +ate ch +D ifferent +Ä E LE +Ä Govern ments +Ä A head +ÃŖÄ§Ä­ ÃŖÄ§Ä­ +word press +L IB +Ä In clude +Ä Dor othy +0 45 +Ä Colomb ian +Ä le ased +88 4 +Ä de grading +Ä Da isy +i ations +Ä bapt ized +Ä surn ame +co x +Ä blink ed +ÃŖÄĨ Âĸ +Ä poll en +Ä der mat +Ä re gex +Ä Nich olson +Ä E ater +ç Äž +rad or +Ä narrow er +Ä hur ricanes +Ä halluc inations +r idden +ISS ION +Ä Fire fly +Ä attain ment +Ä nom inate +Ä av ocado +Ä M eredith +Ä t s +Ä reve rence +Ä e uph +Ä cr ates +Ä T EXT +Ä 4 43 +Ä 3 19 +J SON +iqu ette +Ä short stop +ic key +Ä pro pelled +Ä ap i +Ä Th ieves +77 9 +Ä overs aw +Ä col i +Ä Nic ola +Ä over cl +ik awa +Ä C yr +Ä 38 4 +78 9 +Ä All ows +10 27 +Det roit +TR Y +set up +Ä Social ism +Sov iet +s usp +Ä AP R +Ä Shut down +Ä al uminium +zb ek +Ä L over +GGGG GGGG +Ä democr acies +Ä 19 08 +Ä Mer rill +Ä Franco is +gd ala +Ä traff ickers +Ä T il +Ä Go at +Ä sp ed +Ä Res erv +Ä pro d +55 2 +Ä c ac +Ä Un iv +Ä Sch we +Ä sw irling +Ä Wild erness +Ä Egg s +Ä sadd ened +Ä arch aic +H yd +Ä excess ively +B RE +Ä aer ospace +Ä Vo ices +Cra ig +Ä ign ited +In itially +Ä Mc A +Ä hand set +Ä reform ing +Ä frust rations +Ä Dead pool +Ä Bel ichick +ract or +Ä Ragnar ok +Ä D rupal +Ä App roximately +19 20 +Ä Hub ble +arm or +Ä Sar as +Ä Jon as +Ä nostalg ic +Ä feas ibility +Sah aran +Ä orb iting +Ä 9 70 +R u +Ä sh in +Ä Investig ators +Ä inconsist encies +Ä P AN +B G +Ä graz ing +Ä detect ors +Ä Start up +Ä Fun ny +Ä Na omi +Consider ing +Ä h og +ut f +ce mic +Ä fort ified +Ä Fun ctions +Ä cod ec +nut rition +H at +" ! +micro soft +55 8 +Ä Th in +Ä A CE +Al ias +Ä O PS +p apers +P K +ÃŖÄĸ İ +Ä impro bable +N orthern +equ al +Ä look out +Ä ty res +Ä Mod ified +Ä K op +Abs olutely +Ä build up +sil ver +Ä aud i +Ä gro tesque +Ä Sab er +Ä Pres byter +ON Y +Ä glac iers +Ä Sho als +Ä K ass +Ä H RC +Ä Nic ol +Ä L unch +Ä F oss +Ãĸĸ Ä´ +AD RA +Ä One Plus +o ing +ground s +Ä incident al +Ä datas ets +68 9 +Ä Clarks on +Ä assemb ling +Ä Correct ions +Ä drink ers +Ä qual ifiers +Ä le ash +Ä unf ounded +Ä H undred +Ä kick off +T i +Ä recon cil +Ä Gr ants +Ä Compl iance +Ä Dexter ity +Ä 19 06 +w arn +D allas +Max imum +n ard +av ia +be aut +ens itivity +tr ace +Ä pione ers +Ä F ract +ÃŖÄĸ Äą +Ä pre cept +Ä gloss y +Ä I EEE +Ac ross +Ä 6 80 +S leep +che on +Ä satir ical +Ä Min otaur +Ä Cla ude +Ä r Ê +ape go +Ä car rot +Ä Sem in +ino a +Ä z o +Ind ependent +Ä diagn oses +Ä C ue +M AR +Ä rend ition +Ä K ik +Ä path ology +Ä select s +Link edIn +Ä ass ay +Ä D res +Ä text ual +post ed +IT AL +Ä M aul +N eal +Ä inter connected +Ä err atic +Ä Vir us +Ä 5 30 +Ä environmental ists +Ä P helps +Ä eng agements +Ä IN ST +Ä econom ical +nox ious +Ä g earing +izz y +Ä favor ably +Ä McG ill +T erm +Ä h anged +Ä ball park +Ä Re yes +Ä be ware +Ä P sal +Ä Mass acre +q i +Ä in accessible +acly sm +Ä fr ay +ill ac +Ä bitter ly +Ä Cert ification +Mich igan +Ä ir respective +al ore +Em pty +Ä endorse ments +Ä und et +f g +equ ipped +Ä merc iless +Ä C ust +Ä imm ature +Ä vou cher +Ä Black well +Ñ Äą +h awk +dis ciplinary +ile e +Ä Mak oto +Ä D ude +ÃŖÄĨÄŠ ÃŖÄ¤ÂŖ +Y ears +Ä in ver +Ä sh aman +Ä Y ong +ip el +ell en +Ä Cath y +br ids +Ä s arc +65 1 +N ear +Ä ground work +Ä am az +Ä 4 15 +Ä Hunting ton +hew s +Ä B ung +Ä arbit rarily +Ä W it +Ä Al berto +Ä dis qualified +best os +46 1 +Ä p c +Ä 28 4 +ro bat +Rob in +Ä h ugs +Ä Trans ition +Ä Occ asionally +Ä 3 26 +Ä Wh ilst +Ä Le y +Ä spaces hip +cs v +Ä un successfully +Ä A u +le ck +Ä Wing ed +Ä Grizz lies +. ïÂŋÂŊ +Ä ne arer +Ä Sorce ress +Ä Ind igo +El se +8 40 +let es +Co ach +Ä up bringing +Ä K es +Ä separat ist +Ä rac ists +Ä ch ained +Ä abst inence +lear ning +Ä rein stated +Ä symm etry +Ä remind ers +Ä Che vy +Ä m ont +Ä exempl ary +Ä T OR +Z X +Ä qual itative +Ä St amp +Ä Sav annah +Ä Ross i +Ä p aed +Ä dispens aries +Ä Wall s +Ä Ch ronic +Ä compliment ary +Ä Beir ut +Ä + --- +igs list +Ä crypt ographic +mas ters +Ä Cap itals +Ä max imal +Ä ent ropy +Point s +Ä combat ants +l ip +Ä Gl ob +Ä B MC +ph ase +th ank +HT TP +Ä comm uter +Ä \( \ +.. / +Ä Reg ener +Ä DO I +Ä Activ ision +Ä sl it +os al +RE M +Ä ch ants +Y u +Ke ys +Bre xit +Ä For ced +Ari zona +Ä squad ron +IS O +Ä Mal one +Ä 3 38 +Ä contrast ing +Ä t idal +Ä lib el +Ä impl anted +Ä upro ar +Ä C ater +Ä propos itions +M anchester +Ä Euro s +it amin +G il +Ä El ven +Ä Se ek +Ä B ai +Ä redevelop ment +Ä Town s +Ä L ub +! ", +al on +K rist +Ä meas urable +Ä imagin able +Ä apost les +Y N +7 60 +Ä ster oid +Ä specific ity +Ä L ocated +Ä Beck er +Ä E du +Ä Diet ary +uts ch +Ä Mar ilyn +Ä bl ister +Ä M EP +Ä K oz +Ä C MS +y ahoo +Ä Car ney +Ä bo asting +Ä C aleb +By te +read s +ad en +Pro blem +Ä Wood ward +S we +S up +Ä K GB +Set up +Ä tac it +Ä ret ribution +Ä d ues +Ä M ÃÂŧ +. ? +ä¸ Ń +p ots +Ä came o +Ä P AL +educ ation +A my +like ly +g ling +Ä constitution ally +Ä Ham m +Ä Spe ak +Ä wid gets +br ate +Ä cra ppy +Ä I ter +Ä anticip ating +Ä B out +P ixel +Ä Y ep +Ä Laur ie +Ä h ut +Ä bullet in +Ä Sal vation +Ä ch ats +ear able +Honest ly +AL TH +onse qu +c ult +isco very +ovy ch +Ä se lves +Ä Sat oshi +S ounds +Ä conver gence +Ä Rosen berg +19 74 +Ä nas al +Ä full est +Ä fer ocious +x us +ist e +AM S +Ä lobb ied +Ä so othing +Ä Gun n +t oday +0 24 +Ä inspir ational +Ä N BN +p b +g ewater +or ah +all owed +Ä Col iseum +Ä special izing +Ä insane ly +Ä T ape +del ay +Ä t arn +Ä P ound +Ä mel anch +Ä deploy ments +il and +Ä less en +Ä fur ry +Ä UE FA +Ä blood shed +Ä Me ier +ither ing +Ä he irs +Ä J aw +ax ter +Ä Public ations +Ä al ters +int ention +Ä Winc hester +d etermination +Ä Lif etime +th in +Mon ster +7 80 +Ä approx imation +Ä super markets +Ä Second s +or os +h uge +Ä b ribe +Ä LIM ITED +un ed +Ä mis interpret +Ä In jury +Ä 3 67 +Ä threshold s +Ä Carn ival +Ä gastro intestinal +Ä guid eline +Ä de ceived +f eatures +Ä purported ly +Ä Ron nie +Ä New t +Ä sp acious +as us +Ä superhero es +Ä Cyn thia +le gged +k amp +ch io +Ä th umbnail +Ä Shir ley +ill ation +Ä she ds +Ä Z y +E PA +Ä dam s +Ä y awn +n ah +Ä Pe ggy +Ä E rie +Ä Ju ventus +Ä F ountain +r x +don ald +al bum +Ä Comp rehensive +Ä c aching +Ä U z +ulner ability +Ä Princ iple +Ä J ian +ing ers +cast s +Ä Os iris +ch art +t ile +Ä Tiff any +Ä Patt on +Ä Wh ip +Ä overs ized +J e +Ä Cind erella +Ä B orders +Ä Da esh +M ah +Ä dog ma +Ä commun ists +v u +Coun cil +Ä fresh water +Ä w ounding +Ä deb acle +Ä young ster +Ä thread ed +Ä B ots +Ä Sav ings +ÃŖÄŖ Ĥ +ol ing +oh o +Ä illum ination +M RI +Ä lo osen +tr ump +ag ency +ur ion +Ä moment arily +Ä Ch un +Ä Bud apest +Ä Al ley +D isk +Ä aston ished +Ä Con quer +Ä Account ing +h aving +Ä We in +Ä Al right +Ä rev olver +Ä del usion +Ä relic s +Ä ad herent +qu ant +Ä hand made +or io +Ä comb ating +c oded +Ä quad ru +re th +N ik +Ä Trib al +Ä Myster ious +Ä in hal +Ä Win ning +Ä Class ification +ch anged +Ä un ab +Ä sc orn +icip ated +w l +ond uctor +Ä rein forcing +Ä Child hood +an ova +Ä adventure r +Ä doctor al +Ä Strateg ies +Ä engulf ed +Ä Enc ounter +Ä l ashes +Crit ical +ric ular +Ä U TF +oci ation +check ing +Ä Consult ing +Run time +per iod +Ä As gard +Ä dist illed +Ä Pas adena +Ä D ying +Ä COUN TY +Ä gran ite +Ä sm ack +Ä parach ute +Ä S UR +Virgin ia +Ä F urious +78 7 +Ä O kin +Ä cam el +Ä M bps +19 72 +Ä Ch ao +Ä C yan +j oice +ef er +Ä W rap +Ä Deb ate +S eg +Ä fore arm +Ä Ign ore +Ä tim estamp +Ä prob ing +Ä No on +Ä Gra il +f en +Ä dorm ant +Ä First ly +Ä E ighth +Ä H UN +Ä Des ire +or as +Girl s +Ä Des mond +z ar +am ines +O AD +exec ute +Ä bo obs +Ä AT L +_ ( +Chel sea +Ä masturb ation +Ä Co C +Ä destroy er +Ä Ch omsky +Ä sc atter +Ä Ass ets +79 6 +Ä C argo +Ä recept ive +Ä Sc ope +Ä market ers +Ä laun chers +Ä ax le +Ä SE A +se q +Ä M off +f inding +Ä Gib bs +Georg ia +extreme ly +N J +Ä lab orers +st als +Ä med iation +Ä H edge +at own +Ä i od +des pite +v ill +J ane +ex istence +Ä coinc ided +Ä Ut ilities +Ä Che ap +Ä log istical +Ä cul mination +Ä Nic otine +p ak +F older +Ä rod ents +st uff +Ä law fully +Ä reper to +io ch +j j +Dial ogue +HH HH +lic tion +Look s +Ä 29 7 +Ä tur rets +Ä Ab andon +Ä inc ess +Ä Traff ord +Ä cur led +Ä prefer ring +Ä privat ization +Ä ir resist +Ä P anda +Ä Sh ake +Ä Mc Gr +ÃŖÄĨ ÄĻ +und ers +Ä discrim inated +Ä bart ender +I LE +Atl antic +Ä prop ensity +Ä W iz +Ä G im +con ference +Ä rein forces +G h +w agon +Ä e erie +F al +Ä hug ged +rac ist +R IC +F u +Ä f iller +Ä St ub +Ä eng raved +Ä Wrest le +Ä imagin ative +Ä Pe er +Ä Fact ors +an us +Ä Drac ula +mon itor +Ä rou ters +ib ia +Ä Boo lean +end ale +Ä Sl aughter +Ä Sh ack +R FC +Ä Spiel berg +S ax +Ä PH OTO +Ä Cl over +Ä R ae +Dep ending +Ä Mem or +ar am +Ä pier ced +Ä cur tains +v ale +Ä Inqu isition +Ä P oke +Ä forecast ing +Ä compl ains +S ense +Ä Her mes +isc overed +Ä b ible +Ä Mor ph +Ä g erm +78 5 +D ON +Ä con gen +Ä cr ane +Ä D PR +Ä respect fully +R oom +Ä N aw +Ä Dal ai +re ason +Ä Ang us +Educ ation +Ä Titan ic +Ë Äž +Ä o val +un ited +Ä third s +Ä moist ur +Ä C PC +M iami +Ä tent acles +Ä Pol aris +ex c +ex clusive +Ä Pra irie +Ä col ossal +Ä Bl end +sur prisingly +ÃŃ s +Ä indo ctr +Ä bas al +Ä MP EG +und o +Spl it +Develop ment +Ä lan tern +19 71 +Ä prov ocation +Ä ang uish +Ä B ind +Ä Le ia +duc ers +ipp y +conserv ancy +Ä initial ize +Ä Tw ice +Ä Su k +Ä pred ic +Ä di ploma +Ä soc iop +Ing redients +Ä hamm ered +Ä Ir ma +Q aida +Ä glim ps +Ä B ian +Ä st acking +Ä f end +gov track +Ä un n +dem ocratic +ig ree +Ä 5 80 +Ä 29 4 +Ä straw berry +ID ER +Ä cher ished +Ä H ots +Ä infer red +Ä 8 08 +Ä S ocrates +O regon +Ä R oses +Ä FO IA +Ä ins ensitive +Ä 40 8 +Recomm end +Ä Sh ine +Ä pain staking +UG E +Ä Hell er +Ä Enter prises +I OR +ad j +N RS +L G +Ä alien ated +Ä acknowled gement +Ä A UD +Ä Ren eg +Ä vou chers +Ä 9 60 +Ä m oot +Ä Dim ensions +Ä c abbage +B right +g at +Ä K lu +Ä lat ent +Ä z e +Ä M eng +Ä dis perse +Ä pand emonium +H Q +Ä virt uous +Ä Loc ations +ee per +prov ided +Ä se ams +Ä W T +iz o +PR OV +Ä tit anium +Ä recol lection +Ä cr an +Ä 7 80 +Ä N F +49 1 +64 2 +p acking +59 8 +text ure +Sp ider +fre edom +cipl ed +Ä TAM ADRA +ÃĸÄģ ÂĻ +aut hent +Ä W ANT +r ified +Ä r ites +Ä uter us +k iss +Ä ÃĸÄĢ Â¤ +Ä sk illet +Ä dis enfranch +Ä Ga al +Comp an +Ä age ing +gu ide +B alt +Ä iter ator +Ä discretion ary +t ips +Ä prim ates +Ä Techn ique +Ä Pay ments +az el +Ä R OCK +stant ial +0 60 +Ä d mg +Ä Jack ets +Ä Play off +Ä nurs ery +Ä Sy mb +art on +Ä annex ation +Color ado +Ä co ils +Ä Sh oes +ÃĸÄĻÂĸ : +Ä Ro z +COM PLE +Ä Eve rest +Ä Tri umph +J oy +G rid +à Âŧ +process or +Ä Pros per +Ä Sever us +Ä Select ed +r g +Ä Tay yip +St ra +Ä ski ing +Ä ? ) +Ä pe g +Tes la +Ä time frame +Ä master mind +Ä N B +scient ific +Ä Sh it +gener ic +IN TER +N UM +Ä st roll +Ä En ix +Ä M MR +Ä E MS +m ovie +Ĥ ÂĒ +Ä minim izing +idd ling +Ä illeg itimate +Ä prot otyp +Ä premature ly +Ä manual s +obb ies +Ä Cass idy +D EC +des ktop +Ä aer os +Ä screen ings +Ä deb ilitating +Ä Gr ind +nature conservancy +Ä f ades +ter mination +assets adobe +F actor +Ä definitive ly +P okÊ +ap ult +Ä Laf ayette +C orn +Ä Cor al +Ä stagn ant +T ue +Ä dissatisf action +G ender +Ä kid neys +Ä G ow +Ä Def eat +Ä Ash ton +Ä cart els +Ä fore closure +Ä Expl ore +stre ngth +ot in +Ä veterin arian +Ä f umble +Ä par ap +Ä St rait +r ils +Ä pr ick +Ä Berm uda +Ä Am munition +skin ned +Ä ab ound +Ä B raz +Ä shar per +Ä Asc ension +Ä 9 78 +Ä preview s +Ä commun ion +Ä X Y +Ä ph ony +Ä newcom er +Ä 3 32 +." ," +Ä redist ribution +Prot ect +Ä So f +K al +Ä lip stick +w orst +Ä tang led +Ä retrospect ive +int eger +Ä volunte ering +Ä 19 07 +Ä  -------------------- +ic hen +Ä unve iling +Ä sen seless +Ä fisher ies +\ - +Ä h inges +Ä calcul us +My th +Ä und efeated +Ä optim izations +Ä dep ress +Ä bill board +Ä Y ad +Ä Py ramid +Is n +I de +Ä leg ion +Ä K ramer +ent anyl +Ä penet rating +Ä Haw th +Ä PR ODUCT +Ä Ger ard +Ä P act +Ä In cluding +Ä El ias +Ä El aine +vis ual +Ä hum ming +Ä cond esc +Ä F asc +ä¸ ÄŦ +Ä e galitarian +Ä dev s +Ä D ahl +O ps +D H +Ä B ounce +id ated +ald o +Ä republic an +Ä h amb +Ä S ett +ograph ies +CH APTER +Ä trans sexual +Ä sky rocket +ans wer +Ä mark up +Ø ÂĒ +Ä hero ine +Comp are +Ä T av +Be ast +Ä success ors +Ä na ïve +Ä Buck ley +st ress +me at +Ä download able +Ä index ed +Ä sc aff +Ä L ump +Ä Hom o +Stud io +In sp +Ä r acked +far ious +Ä Pet ty +Ex ternal +Ä 19 09 +W ars +com mit +put ers +Ä un ob +Ä Er r +Ä E G +Ä Al am +Ä Siber ia +Ä Atmosp heric +IS TER +Ä Satan ic +trans lation +Ä L oud +tra umatic +l ique +Ä reson ate +Ä Wel ch +Ä spark ing +Ä T OM +t one +Ä out l +Ä handc uffed +Ä Ser ie +8 01 +Ä land marks +Ä Ree ves +Ä soft ened +Ä dazz ling +Ä W anted +month s +Mag ikarp +Ä unt reated +Ä Bed ford +M i +Ä Dynam o +O re +79 5 +Ä wrong ful +Ä l ured +Ä cort isol +Ä ve x +d rawn +ile t +Download ha +Ä F action +Ä lab yrinth +Ä hij acked +w aters +er ick +Ä super iors +Ä Row ling +Ä Gu inness +Ä t d +99 2 +Ä une arthed +Ä centr if +Ä sham eless +P od +Ä F ib +Ä  icing +Ä predict or +Ä 29 2 +fore station +con struct +C and +@ # +Ä ag itated +Ä re pr +OV A +Ä kn itting +Ä Lim a +Ä f odder +68 4 +Ä Person a +k l +7 01 +Ä break up +ÃĄ ¸ +Ä app alled +Ä antidepress ants +Ä Sus sex +Har ris +Ä Ther mal +ee ee +U pload +Ä g ulf +Ä door step +Ä Sh ank +L U +Ä M EN +Ä P ond +s orry +Ä mis fortune +n ance +Ä b ona +M ut +Ä de graded +Ä L OG +Ä N ess +an imal +Ä a version +und own +Ä supplement ed +Ä C ups +Ä 50 4 +Ä dep rive +Ä Spark le +Å Ĥ +Ä Med itation +auth ors +Ä Sab an +Ä N aked +air d +Ä Mand arin +Ä Script ures +Ä Person nel +Ä Mahar ashtra +Ä 19 03 +Ä P ai +Ä Mir age +omb at +Access ory +Ä frag mented +T ogether +Ä belie vable +Ä Gl adiator +al igned +Ä Sl ug +M AT +Ä convert ible +Ä Bour bon +amer on +Ä Re hab +nt ax +Ä powd ered +pill ar +Ä sm oker +Ä Mans on +Ä B F +5 11 +Ä Good ell +Ä D AR +m ud +g art +Ä ob edient +Ä Trans mission +Ä Don ation +8 80 +Ä bother ing +Material s +ÃŖÄ¤ Âą +dest roy +Ä fore going +Ä anarch ism +Ä K ry +ice ps +Ä l ittered +Ä Sch iff +Ä anecd otal +un its +Ä f ian +Ä St im +Ä S OME +Ä Inv aders +Ä behaviour al +Ä Vent ures +Ä sub lime +Ä fru ition +Ä Pen alty +Ä corros ion +Âļ ħ +Ä lik ened +Ä besie ged +ween ey +Ä Cre ep +Ä linem en +mult i +ic ably +ud der +Ä vital ity +Ä short fall +Ä P ants +ap ist +H idden +Ä Dro ps +med ical +Ä pron unciation +Ä N RL +Ä insight ful +J V +Ä Be ard +Ä Ch ou +Ä char ms +Ä b ins +Ä amb assadors +Ä S aturdays +Ä inhib itor +Ä Fr anch +6 01 +', ' +Ä Con or +art ney +Ä X peria +g rave +be es +Ä Protest ants +Ä so aking +Ä M andal +Ä ph ased +Ä 6 60 +Ä sc ams +Ä buzz ing +Ä Ital ians +Ä Loren zo +Ä J A +Ä hes itated +Ä cl iffs +Ä G OT +ingu ishable +Ä k o +Ä inter ruption +Z ip +Lear ning +Ä undersc ores +Ä Bl ink +K u +57 9 +Ä Aut ob +I RE +Ä water ing +Ä past ry +8 20 +Ä vision ary +Ä Templ ar +awa ited +Ä pist on +Ä ant id +current ly +Ä p ard +Ä w aging +Ä nob ility +Ä Y us +Ä inject ing +f aith +Ä P ASS +ÃĨ Âē +Ä ret ake +Ä PR OC +Ä cat hedral +b ash +Ä wrest lers +Ä partner ing +Ä n oses +Ä 3 58 +Trans form +am en +Ä b outs +Ä Id eal +Ä Constant in +Ä se p +Ä Mon arch +att en +Ä Pe oples +mod ified +Ä mor atorium +Ä pen chant +Ä offensive ly +Ä prox ies +ok ane +Ä Taiwan ese +Ä P oo +Ä H OME +us ional +Ä ver bs +Ä O man +vis ory +Ä persu asion +Ä mult it +Ä sc issors +G ay +ow ay +oph ysical +l us +gn u +Ä ap ocalyptic +Ä absurd ity +Ä play book +Ä autobi ography +I UM +Ä sne aking +Ä Sim ulation +pp s +ell ery +Plan et +Ä right fully +Ä n iece +Ä N EC +Ä IP O +Ä Dis closure +lean or +ous y +ST ER +Ä 28 2 +Cru z +Ch all +64 3 +Ä Surv ive +Ä F atal +Ä Am id +ap o +We apons +D EN +7 70 +Ä Green wald +Ä lin en +al os +Ä pollut ants +Ä PCI e +k at +Ä p aw +Ä K raft +C hem +Ä Termin ator +Ä re incarn +Ä ] [ +Ä Se eds +Ä silhou ette +Ä St ores +Ä gro oming +Ä D irection +Ä Is abel +Ä Br idges +ðŁ Äŗ +E ED +Ä M orsi +Ä val ves +Ä Rank ed +Ä Ph arma +Ä Organ izations +Ä penet rated +Ä Rod ham +Ä Prot oss +Ä ove rest +Ä ex asper +Ä T J +Ä  000000 +Ä trick le +Ä bour bon +WH O +Ä w retched +Ä microsc opic +Ä check list +Ä ad orned +R oyal +Ad minist +Ä Ret irement +Ä Hig hest +We ather +ile ge +Ä incre ments +Ä C osponsors +Ä mas se +Ä S inn +r f +Ä h ordes +as sembly +75 4 +Ä Nat asha +Ä TY PE +Ä GEN ERAL +Ä arr anging +Ä 40 7 +l ator +Ä g lean +Ä disc redited +Ä clin icians +UN E +Ä achie ves +Ä Em erson +com plex += [ +Ä princip ally +Ä fra il +p icked +Ä than king +Ä re cl +Ä L AST +Ä supp ressing +il ic +Ä antidepress ant +Ä Lis bon +Ä th or +Ä sp a +Ä king doms +Ä Pear ce +em o +Ä pl ung +Ä div est +Ä  ******************************** +b is +osp els +ad r +Sp irit +hall a +P ink +end ez +Ä resurrect ed +esc ape +Ä Rosen stein +Ä ge ological +Ä necess ities +Ä carn iv +Ä E lys +Ä Bar ney +Ä 29 6 +dig y +ST ON +D OWN +Ä mil estones +Ä k er +Ä dismant ling +Ä re prim +Ä cross ings +19 45 +Ä patri archy +Ä blasp hemy +Ä 3 59 +met ry +Ä Ob esity +Ä Diff erences +bl ocking +ÃŖÄĨġ ÃŖÄ¤ÂĄ +ich ita +Ä Sab ha +ph alt +Ä Col o +ual a +effic ients +Ä Med ina +con sole +55 7 +Ä Hann ibal +Ä Hab it +Ä F ever +Ä then ce +Ä syn agogue +Ä essential s +Ä w ink +Ä Tr ader +ID A +Ä Sp oiler +Ä Iceland ic +Ä Hay ward +Ä pe ac +Ä mal ice +Ä flash back +Ä th w +Ä lay offs +L iquid +Ä tro oper +Ä h inge +Ä Read ers +Ph ill +Ä B auer +Cre ated +Ä aud its +ac compan +Ä unsus pecting +ier a +6666 6666 +Ä bro ch +Ä apprehend ed +Ä M alk +cer ning +Ä Cod ex +O VER +M arsh +Ä D eng +Ä Exp ression +Ä disrespect ful +Ä asc ending +t ests +Ä Plaint iff +ster y +Ä Al ibaba +din and +Ä Dem psey +Applic ations +mor al +Ä through put +Ä quar rel +Ä m ills +Ä he mor +Ä C ASE +terror ist +st im +ifest yle +ro zen +CE PT +Ar k +u ci +lect ic +Ä irrit ating +she ets +A y +Ä rede emed +Ä horn y +Ä Te ach +Ä S ear +dem ocracy +4 65 +Ä Rest ore +Ä stand by +Ä P is +iff in +Ä sleep y +Ä extr ater +Ä compl iments +Fram eworks +Ä install s +Ä b anging +sur face +found land +Ä metaph ysical +Ä 28 3 +oul s +dev ices +Ar gs +Ä Sac rifice +Ä McC orm +es on +Cons ervative +Ä M ikhail +see ing +is ively +Ä Ro oms +Ä Gener ic +Ä enthusi astically +Ä gri pped +Ä comed ic +Ä Electric ity +Ä gu errilla +Ä dec oration +Ä Perspect ive +Ä consult ations +Ä un amb +Ä plag iar +Ä magic ian +Ä e rection +Ä Tour ism +or ied +ro xy +11 00 +T am +ÄĒ Ã¨ +Î Âŗ +× ÂĒ +Ä Pred ators +Nit rome +Ä telesc opes +project s +Ä un protected +Ä st ocked +Ä Ent reprene +nex pected +Ä wast ewater +V ill +Ä int imately +Ä i Cloud +Ä Const able +Ä spo of +Ä ne farious +Ä fin s +Ä cens or +Ä Mod es +Ä Es per +ar bon +Ä inter sections +Ä laud ed +Ä phys i +Ä gener ously +Ä The Nitrome +Ä TheNitrome Fan +Ä ar isen +ĠÙ ÄĒ +Ä g lands +Ä Pav ilion +Ä Gu pta +Ä uniform ly +Ä r amps +ri et +Ä WH EN +Ä Van essa +Ä rout ed +Ä lim p +Ä C PI +p ter +int uitive +Ä v aping +Ä experiment ed +Ä Olymp us +Ä Am on +Ä sight ing +Ä infiltr ate +Ä Gentle man +Ä sign ings +Ä Me ow +Ä Nav igation +che cks +4 33 +Ä el apsed +Ä Bulg arian +esp ie +Ä S OM +d uring +Ä sp ills +anc a +Ä Ply mouth +M AL +Ä domest ically +Ä Water gate +Ä F AM +k illed +ed ited +Ä Your self +Ä synchron ization +Ä Pract ices +ST EP +Ä gen omes +Ä Q R +not ice +Ä loc ating +z in +Ä 3 29 +al cohol +Ä k itten +V o +Ä r inse +Ä grapp le +Ä Sc rew +Ä D ul +A IR +Ä le asing +Ä Caf Ê +Ä ro ses +Ä Res pect +Ä mis lead +Ä perfect ed +Ä nud ity +Ä non partisan +Ä Cons umption +Report ing +Ä nu ances +Ä deduct ible +Ä Sh ots +Ä 3 77 +Ä ÃĻ Äž +ano oga +Ben ef +Ä B am +Ä S amp +if ix +Ä gal van +Ä Med als +rad ius +Ä no bles +Ä e aves +igr ate +K T +Ä Har bour +u ers +Ä risk ed +re q +Ä neuro t +get table +ain a +Rom ney +Ä under pin +Ä lo ft +Ä Sub committee +Ä Mong ol +b iz +Ä manif ests +ass isted +Ä G aga +Ä sy nergy +Ä religious ly +Ä Pre f +Ä G erry +T AG +Ä Cho i +4 66 +beh ind +Ä O u +Gold Magikarp +Ä hemor rh +R iver +Ä tend on +Ä inj ure +Ä F iona +Ä p ag +Ä ag itation +|| || +ur an +Ä E SA +Ä est eem +Ä dod ging +Ä 4 12 +r ss +Ä ce ases +ex cluding +Ä int akes +Ä insert s +Ä emb old +Ä O ral +up uncture +4 11 +Ä Un ified +Ä De le +Ä furn ace +Ä Coy otes +Ä Br ach +L abor +Ä hand shake +Ä bru ises +Gr ade +ÊĚ Äē +Ä Gram my +ile en +St ates +Ä Scandinav ian +Ä Kard ash +8 66 +Ä effort lessly +Ä DI RECT +Ä TH EN +Ä Me i +ert ation +19 68 +Ä gro in +w itch +Requ irements +98 5 +Ä roof s +Ä est ates +Ä H F +Ä ha ha +Ä dense ly +Ä O CT +Ä pl astics +Ä incident ally +Ä Tr acks +Ä Tax es +Ä ch anted +Ä force ful +Ä Bie ber +Ä K ahn +K ent +Ä C ot +lic ts +F ed +Ä hide ous +Ä Ver d +Ä Synd icate +Ä Il legal +J et +Ä D AV +re asonable +c rew +Ä fundamental ist +Ä truth ful +Ä J ing +Ä l il +Ä down ed +Ä en chanted +Ä Polic ies +Ä McM aster +Ä H are +ides how +Ä par ams +en cers +gorith m +Ä allow ances +Ä turb ulent +Ä complex ities +Ä K T +Ä 3 37 +Ä Gen etic +F UN +D oug +t ick +Ä g igs +ument hal +Ä patriarch al +Ä cal c +, ... +Ä c out +Ä Gu an +Ä path ological +Ä R ivals +Ä under rated +Ä flu orescent +Ä J iu +arna ev +Ä Qu an +Ä 4 29 +Ä  ਠ+M ario +Con struct +Ä C itation +Ä R acial +Ä R SA +Ä F idel +Ä 3 95 +Person ally +C ause +à Âģ +rad ical +in en +Ä vehement ly +Ä Pap a +Ä intern ship +Ä fl akes +Ä Re ck +Luck ily +B ra +20 20 +rav ings +R N +W onder +Ser iously +Ä re usable +Ä poll uted +Ä P eng +le igh +ind le +Ä circuit ry +Ä Mad onna +Ä B ART +Res idents +att ribute +Phil adelphia +Cl ub +Ä plan ner +Ä fr antically +Ä faith fully +Ä Territ ories +Ä L AT +Ä Anders en +an u +Ä P ARK +Ä S ora +i age +Ä Play offs +Ä G CC +4 27 +Ä ab norm +Ä L ever +Ä disob edience +As ync +Ä She a +V ert +Ä sk irts +Ä Saw yer +x p +Ä wors ening +Ä sc apego +Ä Ang le +oth al +Ä tro ve +Ä St y +Ä N guyen +mar ine +ide on +Dep ths +Bl og +Ä Ill uminati +Ä tract s +Ä organ ise +Ä o str +F s +Ä lever aging +Ä D aredevil +as ar +Ä l ang +Ä ex termin +urs ions +Ä Rom o +ÃŖÄ¤Â¤ ÃŖÄĨÄĒ +Ä cont ended +Ä encounter ing +Ä Table t +Ä Altern ate +sk ill +Ä swe ets +Ä co hesive +cap acity +Ä rep ud +Ä l izard +ro o +Ä pilgr ims +Ä R uff +Ä Instr ument +Ä Log o +uit ous +E H +Ä sales man +Ä ank les +L ed +Ä Pat ty +ud os +Own er +Ä discrep ancies +k j +M U +Ä uncond itional +Dragon Magazine +i ard +O ak +Ä Convers ation +be er +Ä Os aka +D elta +us ky +Ä secret ion +Ä pl aza +Ä m ing +Ä de pletion +Ä M ous +Ä I TS +Ä H imal +Ä Fle ming +Ä cyt ok +Ä H ick +Ä bat ters +Ä Int ellectual +6 75 +Ê r +IS ION +Ä Qu entin +Ä Ch apters +ih adi +Ä co aster +WAY S +Ä L izard +Ä Y or +and ering +S kin +ha ust +ab by +Ä portray ing +Ä wield ed +d ash +Ä prop onent +Ä r ipple +Ä grap hene +Ä fly er +Ä rec urrent +Ä dev ils +Ä water fall +ÃĻÄē ¯ +go o +Text Color +Ä tam pering +IV ES +TR UMP +Ä Ab el +Ä S AL +Ä Hend ricks +Ä Lu cius +b ots +Ä 40 96 +IST ORY +Gu est +Ä N X +in ant +Ben z +Ä Load ed +Ä Cle ver +t reatment +Ä ta vern +Ä 3 39 +Ä T NT +ific antly +Tem perature +F el +Ä under world +Ä Jud ges +Ä < + +Ä st ump +Ä occup ancy +Ä ab er +Ä F inder +) ", +Ä N unes +res et +in et +ect omy +Ä well ness +Ä P eb +quart ered +and an +Ä neg atives +Ä Th iel +Ä Cl ip +Ä L TD +Ä bl ight +Ä reperto ire +K yle +Ä qu er +Ä C es +Ä ha pl +98 9 +Ä Th ames +isc opal +Des k +ivari ate +Ä Ex cellence +found ation +Ä Ãĸ ÄŠ +X i +Ä myster iously +esty les +Ä per ish +Ä Eng els +Ä DE AD +09 0 +}} } +Ä Un real +Ä rest less +ID ES +orth odox +Ä Inter mediate +Ä din ners +Ä Tr out +Ä Se ym +Ä Hall s +og ged +Ä traged ies +Ä did nt +67 6 +Ä ail ments +Ä observ able +Ä V ide +ad apt +Ä D usk +Ä professional ism +Ä Pres cott +Ä Ind ies +p ox +Ä Me hran +W ide +Ä end emic +Ä Par an +B ird +Ä ped als +Ä I U +Ä Adam ant +Ä H urt +Ä correl ates +urd en +Ä spons oring +cl imate +Ä Univers ities +Ä K not +enn es +Ä Dam ian +Ä Ax el +S port +Ä bar b +Ä S no +sh own +ste en +ud ence +Ä non violent +Ä hom ophobia +Ä biom ass +Ä Det ail +Ä srf N +Ä T une +accompan ied +I ENCE +Al bert +Ä Mong o +z x +Ä Cer berus +or bit +c ens +Ä sl ay +SH ARE +H Y +Ä b rawl +Ä Pro be +Ä nonex istent +Ä Clare nce +Ä Black burn +Ä port als +Ä R ita +Ä Rem ain +Ä Le vant +Ä trick ed +Ä F erry +aver ing +Ä Straw berry +Ä An swers +Ä horrend ous +Ä A man +Supp lement +Ä T oad +Ä pe eled +Ä man oeuv +Ä U zbek +mond s +Ä H ector +Ä 40 2 +pe es +fix es +Ä d j +Ä res umes +Ä account ant +Ä advers ity +Ä ham pered +Ä L arson +Ä d oping +part s +H ur +Ä be arded +Ä y r +Ä Plug in +ÃĨÂĨ Âŗ +Ä / ** +rol ley +Ä waters hed +Ä Sub mission +if lower +AS C +Ä cho ir +Ä sculpt ures +m A +incre asing +ai i +Ä sne akers +Ä confront s +Ä Ele phant +Ä El ixir +Ä rec al +Ä T TL +w idget +Ä W ax +Ä Gr ayson +Ä ha irst +Ä humili ated +Ä WAR N +app iness +Ä T TC +F uel +Ä pol io +Ä complex es +Ä bab e +Ä X IV +P F +). [ +P arts +Ä 4 35 +M eg +Ä Y ards +Ä AL P +Ä y ells +Ä prin ces +Ä bull ies +Ä Capital ism +ex empt +FA Q +Ä Sp onge +Ä Al a +Ä pleas antly +Ä bu f +Ä den ote +Ä unp ublished +Ä kne eling +asc a +Ä l apse +al ien +99 4 +Ä refere es +Ä Law yers +S anta +Ä puzz ling +Ä Prom etheus +Ä Ph araoh +Ä Del ay +Ä facilit ates +Ä C ES +Ä jew els +Ä book let +ond ing +Ä polar ization +Ä Mor an +Ä Sal ad +Ä S OS +Ä Adv ice +PH OTOS +IC AN +iat ures +ex press +Ä Wonder land +Ä C ODE +Ä CL ASS +9 75 +Ä g rep +Ä D iesel +Ä Gl ac +! ?" +Ä r m +o ine +disc rimination +Ä N urse +m allow +Ä v ortex +Ä Cons ortium +Ä large Download +stra ight +augh lin +G rad +Ä public ized +Ä W aves +Ä Red d +Ä fest ivities +Ä M ane +ar ov +Ä fleet ing +Ä Dr unk +ug en +C ele +Ä chromos omes +Ä D OT +-+-+ -+-+ +Ä bus iest +Ä Be aver +Sy rian +Ä K yr +k as +Ä Cross Ref +19 50 +76 01 +Ä repe aling +Ä Win ners +Ä Mac ro +Ä D OD +bl ance +S ort +64 1 +Ä met re +Ä D irk +Ä go ggles +Ä draw backs +Ä complain ant +Ä author izing +Ä antit rust +oper ated +Ä m ah +Ä exagger ation +Am azing +Ä Ser aph +Ä ha ze +w ow +Ä extingu ished +Ä can yon +Ä B osh +Ä v ents +Ä sc rape +Cor rect +4 26 +Ä av g +Dem and +Ä ÃĸÄĒ Âŧ +Ä microbi ota +"} ]," +Ä St ev +B io +Ä Plan es +Ä suggest ive +Ä dec ipher +Ä Refuge e +Ä Ke jriwal +Ä Green peace +Ä decl ass +Ä Sound ers +Ä th o +Ä dec rypt +Ä br ushing +Ä Jane iro +ip op +S i +8 77 +Ä Geoff rey +Ä c pu +Ä Haz el +Ä view points +Ä cris py +Ä Not ification +Ä sold er +Ä Mod est +Ä Hem isphere +Ä cass ette +in cludes +Ä ident ifiers +Ä C ALL +in cent +T odd +Ä Swe ep +Ä 3 34 +b oss +Ä sm ir +gin x +Ä town ship +Ä g rieving +Ä Mos que +Net flix +AS ED +Ä Millenn ials +oc om +19 67 +Ä bold ly +s leep +Ä es che +arij uana +Ä sw irl +Ä Pen al +Ä neglig ent +Ä Stephen son +K ER +Ä Z oro +ris is +Ä local ization +Ä Seym our +Ä Ang lic +red itation +prot ection +Ä Pa ige +Ä o mit +Ä R ousse +Ä T ub +Ä inv itations +t ty +Ä m oss +ph ysical +C redits +Ä an archy +Ä child care +Ä l ull +Ä M ek +Ä L anguages +lat est +Ä San ford +Ä us ability +Ä diff use +Ä D ATA +Ä sp rites +Ä Veget a +Ä Prom otion +ÃŖÄĨÂŧ ÃŖÄ¤Â¯ +rict ing +z ee +Tur kish +Ä TD s +pro ven +57 1 +Ä smug glers +707 10 +Ä reform ed +Ä Lo is +Ä un fl +Ä WITH OUT +Ä Return ing +ann ie +Ä Tom as +Fr anc +Ä Prof it +Ä SER V +Ä R umble +ik uman +es an +Ä t esters +Ä gad get +Ä brace let +Ä F SA +comp onent +Ä paramed ics +Ä j an +Ä Rem em +Ä Sk inner +Ä l ov +Ä Qu ake +rom a +Ä fl ask +Pr inc +Ä over power +Ä lod ging +Ä K KK +ret te +Ä absor bs +w rote +Ä  ," +K ings +Ä H ail +Ä Fall ing +xt ap +Ä Hel ena +ire ns +L arry +Ä pamph let +Ä C PR +G ro +Ä Hirosh ima +Ä hol istic +". [ +Ä det achment +Ä as pire +Ä compl icit +Ä Green wood +Ä resp awn +Ä St upid +Ä Fin ished +f al +b ass +Ä ab hor +Ä mock ery +Ä Fe ast +VID EO +Ä con sec +Ä Hung ry +P ull +Ä H ust +it ance +? ÃŖÄĸį +) -- +Ä Par allel +con v +4 69 +ha ar +w ant +P aper +m ins +Ä Tor o +Ä TR UMP +Ä R ai +D W +Ä W icked +Ä L ep +Ä fun ky +Ä detrim ent +ios is +ache v +Ä de grade +im ilation +Ä ret ard +Ä frag mentation +Ä cow boy +Ä Y PG +Ä H AL +Parent s +Ä S ieg +Ä Stra uss +Ä Rub ber +× IJ +Fr ag +Ä p t +Ä option ally +Ä Z IP +Ä Trans cript +Ä D well +88 2 +M erc +Ä M OT +ÃŖÄĨ¯ ÃŖÄĨÂŗ +Ä hun ts +Ä exec utes +In cludes +Ä acid ic +Ä Respons ibility +Ä D umb +we i +And erson +Ä Jas per +ight on +abs olutely +Ad ult +Ä pl under +Mor ning +Ä T ours +Ä D ane +Î Âē +Ä T EST +Ä G ina +Ä can ine +aw an +Ä social ists +Ä S oda +Ä imp etus +Ä Supplement ary +oli ath +Ä Kinn ikuman +mitted ly +second s +Ä organis ers +Ä document aries +Vari able +GRE EN +Ä res orts +Ä br agging +Ä 3 68 +Art ist +w k +bl ers +Un common +Ä Ret rieved +Ä hect ares +Ä tox in +r ank +Ä faith s +Ä G raphic +Ä ve c +Ä L IA +Af rican +Ä ard ent +end iary +L ake +Ä D OS +cient ious +Ä Ok awaru +Ä All y +Ä Tim eline +D ash +Ä I c +contin ue +Ä t idy +Ä instinct ively +Ä P ossibly +Ä Out door +Ä Would n +Ä l ich +Ä Br ay +Ä A X +Ġà ÄĢ +Ä + # +\ ' +Direct ory +ab iding +Ä f eral +ic ative +but t +Ä per verse +S alt +Ä war ped +Ä nin eteen +Ä cabin ets +Ä srf Attach +Ä Sl oan +Ä power ing +reg ation +F light +se vere +Ä st ren +Ä c og +ap ache +Ä Ãĸ Äŋ +Ä caf eteria +p aces +Ä Grim oire +uton ium +Ä r aining +Ä cir cling +Ä lineback ers +c redit +Ä rep atri +Ä Cam den +lic ense +Ä ly ric +Ä descript or +Ä val leys +Ä re q +Ä back stage +Ä Pro hibition +Ä K et +Op ening +S ym +ÃĻĸ š +Ä serv ings +Ä overse en +Ä aster oids +Ä Mod s +Ä Spr inger +Ä Cont ainer +è Âģ +Ä M ens +Ä mult im +Ä fire fighter +pe c +Ä chlor ine +Ð Âŧ +end i +Ä sp aring +Ä polyg amy +Ä R N +Ä P ell +Ä t igers +Ä flash y +Ä Mad ame +S word +Ä pref rontal +Ä pre requisite +uc a +Ä w ifi +Ä miscon ception +Ä harsh ly +Ä Stream ing +ot om +Ä Giul iani +foot ed +Ä tub ing +ind ividual +z ek +n uclear +m ol +Ä right ful +49 3 +Ä special ization +Ä passion ately +Ä Vel ocity +Ä Av ailability +T enn +Ä l atch +Ä Some body +Ä hel ium +cl aw +Ä di pping +XX X +Ä inter personal +7 10 +Ä sub ter +Ä bi ologists +Ä Light ing +Ä opt ic +Ä den im +end on +Ä C orm +Ä 3 41 +Ä C oup +Ä fear less +Ä al ot +Ä Cliff ord +Ä Run time +Ä Prov ision +up dated +lene ck +Ä neur on +Ä grad ing +Ä C t +sequ ence +in ia +con cept +Ä ro aring +ri val +Ä Caucas ian +Ä mon og +key es +Ä appell ate +Ä lia ison +EStream Frame +Ä Pl um +! . +Ä sp herical +Ä per ished +Ä bl ot +Ä ben ches +Ä 4 11 +Ä pione ered +Ä hur led +Jenn ifer +Ä Yose mite +Ch air +Ä reef s +Ä elect or +Ä Ant hem +65 2 +Ä un install +Ä imp ede +Ä bl inking +Ä got o +Dec re +A ren +Ä stabil ization +Ä Dis abled +Ä Yanuk ovych +Ä outlaw ed +Ä Vent ura +ten ess +Ä plant ation +Ä y acht +Ä Hu awei +Ä sol vent +Ä gr acious +Ä cur iously +Ä capac itor +Ä c x +Ä Ref lex +Ph ys +Ä C f +pt in +cons ervative +Ä inv ocation +c our +F N +Ä New ly +H our +As ian +Ä Le ading +Ä Aer ospace +An ne +Ä pre natal +Ä deterior ating +H CR +Ä Norm andy +ol ini +Ä Am bro +9 10 +Ä set backs +Ä T RE +Ä s ig +Ä Sc ourge +59 7 +79 8 +Game play +Ä m sec +M X +Ä price y +Ä L LP +aker u +Ä over arching +Ä B ale +Ä world ly +Cl ark +Ä scen ic +Ä disl iked +Ä Cont rolled +T ickets +Ä E W +ab ies +Ä Pl enty +Non etheless +Ä art isan +Trans fer +Ä F amous +Ä inf ield +ble y +Ä unres olved +Ä ML A +ÃŖÄ¤ Ĥ +Cor rection +Ä democr at +Ä More no +ro cal +il ings +Ä sail or +Ä r ife +h ung +Ä trop es +Ä sn atched +Ä L IN +Ä B ib +ES A +Ä Pre v +Ä Cam el +run time +Ä ob noxious +4 37 +Ä sum mers +Ä unexpl ained +Ä Wal ters +cal iber +Ä g ull +Ä End urance +äÂŊ Äž +Ä 3 47 +Ir ish +Ä aer obic +Ä cr amped +Ä Hon olulu +à Š +us erc +ec ast +AC Y +Ä Qu ery +ÃŖÄ¤Âš ÃŖÄĨÄĒ +Bet a +Ä suscept ibility +Ä Sh iv +Ä Lim baugh +Ġà ĸ +Ä N XT +Ä M uss +Ä Brit ons +ES CO +EG IN +Ä % % +Ä sec ession +Ä Pat ron +Ä Lu a +n aires +Ä JPM organ +us b +ocy te +Ä councill ors +Ä Li ang +f arm +Ä nerv ously +Ä attract iveness +Ä K ov +j ump +Pl ot +Ä st ains +Ä Stat ue +Ä Apost les +he ter +Ä SUP PORT +Ä overwhel m +Y ES +Ä 29 1 +d ensity +Ä tra pping +M it +Ä f ide +Ä Pam ela +atl antic +Dam n +Ä p ts +OP A +Ä serv icing +Ä overfl owing +ul o +Ä E rit +t icket +light ing +Ä H mm +ÃŖÄĨÂŧ ÃŖÄĨÂĢ +im oto +Ä chuck le +4 23 +ÃŖÄŖ ġ +sh ape +Ä que ues +Ä anch ors +ÃŖÄ¤Âŧ ÃŖÄ¤ÂĻÃŖÄ¤Âš +F er +Ä aw oke +Ä 6 66 +h ands +Ä diver gence +Ä 50 5 +T ips +Ä dep ot +Ä ske w +Ä Del iver +op ot +Ä div ul +Ä E B +uns igned +Ä Un i +X box +Ä for ks +Ä 7 02 +ÃĨ ¯ +Ä promot ers +Ä V apor +Ä lev ied +sl ot +Ä pig ment +Ä cyl inders +C RE +Ä sn atch +Ä perpet ually +Ä l icking +Ä Fe et +Ä Kra ken +Ä Hold en +Ä CLS ID +m r +Ä project or +Ä den otes +Ä chap el +Ä Tor rent +b ler +R oute +Ä Def endant +Ä Publisher s +Ä M ales +Ä Inn ov +Ä Ag ility +rit er +ty mology +st ores +L ind +Ä f olly +Ä Zur ich +B le +Ä nurt ure +Ä coast line +uch in +D omin +Ä fri vol +Ä Cons olid +res ults +M J +Ä phyl ogen +Ä ha uled +Ä W iley +Ä Jess ie +Ä Prep are +Ä E ps +Ä treasure r +I AS +Ä colon ists +Ä in und +Ä WW F +Ä Con verted +6 000 +out side +Ä App earance +Ä Rel ic +Ä M ister +s aw +Ä result ant +Ä adject ive +Ä Laure l +Ä Hind i +b da +Pe ace +Ä reb irth +Ä membr anes +Ä forward ing +Ä coll ided +Ä Car olyn +K ansas +5 99 +Ä Solid GoldMagikarp +Be ck +Ä stress ing +Ä Go o +Ä Cooper ative +Ä f s +Ä Ar chie +L iter +Ä K lopp +J erry +Ä foot wear +War ren +Ä sc ree +h are +Under standing +P ed +Ä anth ology +Ä Ann ounce +M ega +Ä flu ent +Ä bond age +Ä Disc ount +il ial +C art +Ä Night mares +Sh am +Ä B oll +uss ie +H ttp +Atl anta +Ä un recogn +Ä B id +Ä under grad +Ä forg iving +Ä Gl over +AAAA AAAA +4 45 +V G +pa io +kill ers +Ä respons ibly +Ä mobil ize +Ä effect ed +Ä L umin +Ä k ale +Ä infring ing +ann ounced +Ä f itt +b atch +Ä T ackle +Ä L ime +Ä AP P +uke mia +Ä rub y +Ä ex oner +Ä Cas ual +0 70 +Ä pel vic +Ä autom ate +Ä K ear +Ä Coast al +Ä cre ed +Ä bored om +Ä St un +ri ott +Ĥ İ +Ä regener ate +Ä comed ians +Ä OP ER +Sp ons +id ium +on is +L ocated +05 7 +Ä susp ense +Ä D ating +C ass +Ä neoc ons +Ä Shin zo +Ä aw oken +ch rist +Ä Mess ages +att led +Ä Spr ay +Ä Sp ice +C W +Ä shield ing +Ä G aul +Am id +Ä param ilitary +Ä mult if +Ä Tan ner +il k +Ä godd amn +g ements +Ä be friend +m obi +Ä 3 88 +fold er +acc a +Ä ins in +g ap +N ev +fif th +Ä psychiat ry +b anks +TH IS +Ä har b +ac qu +Ä fac ade +Ä Power Point +80 3 +Ä bl uff +Sh ares +Ä favor ing +El izabeth +Ãį Ãį +Ä r anger +77 2 +Ä Ar che +h ak +Ä Gen etics +Ä F EMA +Ä ev olves +Ä est e +Ä P ets +Ä M Ê +Ä Interest ing +Ä Canter bury +ch apter +Ä Star fleet +Sp anish +Ä draw back +Ä Nor wich +9 70 +n orth +ag anda +Ä transform ative +ram ids +bi ology +ad ay +Ä propag ation +Ä Gam ma +Ä Den ise +Ä Calcul ator +ent imes +Ä B ett +Ä app endix +Ä HD D +AK ING +Ä st igmat +Ä hol ster +Ä ord inarily +Ch ance +Ä Cont rary +Ä ad hesive +Ä gather s +6 12 +re au +ony ms +ew ays +Ä indu ces +Ä interchange able +se m +Wh it +Ä tr ance +Ä incorpor ation +Ä Ext ras +Fin ancial +Ä awkward ly +Ä Stur geon +Ä H Y +Norm ally +Ä End ing +Ä Ass ist +enc rypted +Ä sub jug +Ä n os +Ä fan atic +C ub +C U +?" . +Ä irre versible +ÃĨ Ĥ +03 1 +Ä H AR +sp read +ul ia += $ +Sc ope +L ots +Ä lif estyles +ol on +Ä f eds +Ä congrat ulate +web kit +Ä indist inguishable +Ä Sw ing +Ä command ments +qu ila +ab ella +m ethyl +ann abin +Ä o vere +Ä lob ster +Ä QU EST +Ä CONT IN +bern atorial +:::: :::: +Ä Tra ve +Ä Sam oa +AN I +75 2 +Ð ´ +userc ontent +Ä Mod erate +y eah +Ä K itt +Ä we e +Ä stuff ing +Ä Inter vention +Ä D ign +Ä ware houses +Ä F iji +Ä pel lets +Ä take away +Ä T ABLE +Ä Class ical +col lection +Ä land fall +Ä Mus cle +Ä sett les +Ä AD V +Ä 3 44 +L aura +Ä f ared +Ä Part ial +4 36 +oss ibility +Ä D aly +Ä T arant +Ä Fu ji +am l +c ence +55 1 +Ä Proced ures +Ä O CD +Ä U D +t in +Q UI +ach o +4 38 +Ä gl itches +Ä enchant ment +Ä calcul ates +IR O +Ä H ua +alys es +Ä L ift +um o +Ä le apt +Ä hypothes ized +Ä Gust av +it ans +VERS ION +ÃĻ Å‚ +Rog er +Ä r and +Ä Ad apter +Ä 3 31 +Ä Pet ition +k ies +M ars +Ä under cut +ze es +Ä Ly ons +Ä DH CP +Miss ing +Ä retire es +Ä ins idious +el i +> ) +. ÃŖÄĸį +Ä final ists +Ä A ure +Ä acc user +Ä was tes +Ä Y s +Ä L ori +Ä constitu encies +Ä supp er +Ä may hem +or ange +Ä mis placed +Ä manager ial +Ä ex ce +Ä CL I +Ä prim al +Ä L ent +Cry stal +h over +Ä N TS +end um +Ä d w +Ä Al c +n ostic +Ä pres erves +Ä Ts arnaev +Ä tri pled +rel ative +Arc ade +k illing +Ä W EEK +Ä H anna +D ust +Com pleted +ÄŖ ÂĢ +Ä appro ves +Ä Sur f +Ä Luther an +ven ants +Ä robber ies +we ights +soft ware +at ana +ug al +Ä grav y +Ä C ance +OLOG Y +ly ak +Ton ight +Ä unve il +Ä 19 04 +Ä Min ion +ent ious +st ice +pack ages +Ä G EAR +Ä g ol +Ä Hutch inson +Ä Prof ession +Ä G UN +Ä Diff erence +Ä Tsuk uyomi +Ä Les bian +6 70 +Ä fug itive +Ä Plan etary +-------------------------------- ------------------------ +Ä acc rued +Ä ch icks +Ä sto pp +Ä block ers +C od +Ä comment ers +Ä Somew here +Ä Phot ographer +the me +Ä may oral +w u +Ä anten nas +Ä rev amped +Ä Subject s +it Ê +im ura +Ä entr ances +liter ally +Ä ten ets +Ä O MG +Ä MP H +Ä Don key +Ä Off ense +Ä " + +Sn ap +Ä AF B +Ä an imate +Ä S od +His panic +Ä inconsist ency +D b +F Y +Ex port +Ä a pe +Ä pear l +ib el +Ä PAC s +Ä { \ +Ä act u +Ä HS BC +camp us +Ä pay off +Ä de ities +Ä N ato +ou ple +Ä cens ored +Ä Cl ojure +Ä conf ounding +en i +Ä reck on +op he +Ä spot ting +Ä sign ifies +Ä prop el +Ä fest ive +S uggest +Ä pled ging +Ä B erman +Ä rebell ious +Ä overshadow ed +Ä infiltr ated +j obs +67 2 +Ä scal able +Ä domin ion +Ä New foundland +Ä Mead ow +Ä part itions +AM I +Ä supplement ary +str ument +Ä hair y +Ä perpet uate +Ä nuts hell +Ä Pot ato +Ä Hob bit +Ä cur ses +Flo at +Ä quiet er +Ä fuel ing +Ä caps ules +Ä L ust +Ä H aunted +Exec utive +Ä child birth +G re +Ä rad iant +ÃĨ İ +Ä m alls +Ä in ept +Ä Warrant y +Ä spect ator +E h +t hens +Ä culmin ating +ÃĻ ÂŠ +ary a +ÃŖÄ¤ ÂŽ +ilit arian +Ä OR IG +Ä Sp ending +pt ives +Ä S iren +Ä Rec ording +ay ne +Ä v im +Ä spr ang +T ang +Ä M FT +mor ning +Ä We ed +m peg +cess ion +Ä Ch ung +7 30 +w arning +56 2 +handed ly +P oor +P olitics +: # +Ä p ian +Ä fec es +Ä Document ation +Ä ban ished +Ä 3 99 +Ä AR C +Ä he inous +J ake +Ä Am ir +way ne +v re +os henko +Ä notebook s +Ä found ational +Ä marvel ous +ixt ape +Ä withdraw als +Ä h orde +Ä D habi +is able +Ä K D +Ä contag ious +Ä D ip +Ä Ar rows +Ä pronoun s +Ä morph ine +Ä B US +68 2 +Ä k osher +fin ished +Ä Instr uments +Ä f used +yd en +Ä Sal mon +F ab +aff ected +K EN +C ENT +Dom ain +Ä poke mon +Ä Dr inking +G rowing +Ä Investig ative +Ä A ether +em i +Ä tabl oid +Ä rep ro +Ä Not withstanding +Ä Bers erker +Ä dram as +Ä clich Ê +Ä b ung +Ä U RI +Ä D os +0 44 +Ä past ors +Ä l s +Ä ac rylic +aun ts +Ed ward +Ä major ities +B ang +Ä field ing +Ä Repl acement +Ä Al chemy +pp ard +Ä Rome o +Ä San ct +Ä Lav rov +ib ble +Inst ruct +Ä imp ractical +Ä Play boy +ce phal +Ä sw aps +Ä k an +Ä The o +Ä illust rating +Ä dismant led +Ä Trans gender +Ä G uth +UG H +Ä triumph ant +Ä encomp ass +Ä book mark +udd in +j er +Ä pred icate +ES H +Ä when ce +Ä AB E +Ä non profits +Se qu +Ä di abetic +Ä p end +Ä heart felt +sh i +Ä inter acts +Ä Tele com +Ä bombard ment +dep ending +Ä Low ry +Ä Ad mission +Ä Bl ooming +ust ration +ene gger +B rew +Ä mol ten +Ä Ner d +P IN +Ãĸĸ Äĸ +ave ment +Ä tou red +Ä co efficients +Ä Tray von +ans son +Ä sand y +t old +fl ows +Ä pop ulous +Ä T inder +Ä Bl iss +R achel +Min imum +Ä contest ant +Ä Red uce +Ä Mor se +Ä Grass ley +Ä Click er +Ä exp r +Ä s incerity +Ä mar qu +Ä elic it +Ä Pro position +Ä Demon ic +Ä tac os +G reek +Ä post war +Ä in sofar +Ä P ork +Ä 35 2 +doctor al +walk ing +Ä mid term +Ä Sam my +sight ed +Ä TR ANS +ic i +AL D +Ä US L +Ä F ISA +Ä Am pl +Ä Alex andra +ine lli +Tr ain +Ä sign ify +Ä Vers us +Ä ob fusc +Ä k h +Ä agg ro +Ä Ren ault +Ä 3 48 +5 18 +ox icity +0 22 +Ä Tw ist +Ä goof y +D ynamic +Ä brief ings +m ight +8 99 +Ä derog atory +T ro +Ä for ging +Ä Kor an +Ä Mar ried +Ä Buc s +Ä pal ate +Ä Con version +m able +4 13 +Ä ( _ +Ä s iph +Ä N EO +col lege +Ä marg inally +Ä fl irt +Ä Tra ps +Ä P ace +Ê ÂģÄ´ +Ä goalt ender +Ä forb ids +Ä cler ks +Ä T ant +Ä Robb ins +Ä Print ing +Ä premie red +Ä magn ification +Ä T G +Ä R ouse +Ä M ock +odynam ics +Ä pre clude +ism o +Ä Pul itzer +Ä aval anche +Ä K odi +rib une +Ä L ena +Elect ric +Ä ref inery +Ä end owed +Ä counsel ors +Ä d olphin +Ä M ith +Ä arm oured +hib ited +Beg in +Ä P W +O il +Ä V or +Ä Shar if +Ä Fraz ier +est ate +Ä j ams +Pro xy +Ä band its +Ä Presbyter ian +Ä Prem iere +t iny +Ä Cru el +Test ing +Ä hom er +Ä V ERS +Ä Pro l +Ä Dep osit +Ä Coff in +Ä semin ars +Ä s ql +Ä Def endants +Altern atively +Ä R ats +ç ÂĢ +ethy st +' > +Ä iss uer +58 9 +Ä ch aired +Ä Access ories +man ent +Ä mar row +Ä Prim ordial +C N +Ä limit less +Ä Carn age +Ä und rafted +q v +IN ESS +on ew +Ä co hesion +98 7 +Ä ne cks +Ä football er +Ä G ER +Ä detect able +Ä Support ing +Ä CS V +oc ally +k Hz +Ä und e +Ä sh one +Ä bud ding +tra k +Stand ing +Ä Star craft +Ä Kem p +Ben ch +Ä thw arted +Ä Ground s +ath i +L isa +Dial og +Ä S X +V ision +Ä ingen ious +Ù IJ +Ä fost ering +Ä Z a +Ä In gram +Ä " @ +N aturally +6 16 +0 35 +Ä F AC +H mm +55 4 +Ä acceler ator +Ä V end +Ä sun screen +Ä tuber culosis +rav iolet +Ä Function al +Ä Er rors +ed ar +19 66 +Ä Spect re +Ä Rec ipes +88 5 +Ä M ankind +L iverpool +Ä | -- +Ä subst itutes +Ä X T +w ired +Ä inc o +Ä Af gh +E va +ic c +S ong +K night +Ä dilig ently +Ä Broad cast +A id +Ä af ar +Ä H MS +aton in +Ä Gr ateful +Ä fire place +Ä Om ni +e uro +Ä F RE +Ä Sh ib +Ä Dig est +t oggle +Ä heads ets +Ä diff usion +Ä Squ irrel +Ä F N +Ä dark ened +out her +Ä sleep s +Ä X er +gun s +Ä set ups +Ä pars ed +Ä mamm oth +Ä Cur ious +g ob +Ä Fitz patrick +Ä Em il +im ov +........ ..... +Ä B enny +Second ly +Ä heart y +Ä cons on +st ained +Ä gal actic +cl ave +Ä plummet ed +Ä p ests +Ä sw at +Ä refer rals +Ä Lion el +h oly +Ä under dog +Ä Sl ater +Ä Prov ide +Ä Am ar +ress or +ÃĨ ÄŽ +ong a +Ä tim id +Ä p iety +Ä D ek +Ä sur ging +az o +Ä 6 10 +Ä des ks +Ä Sp okane +Ä An field +Ä wars hips +Ä Cob ra +Ä ar ming +clus ively +Ä Bad ge +ag ascar +Ä PR ESS +Ä McK enzie +Ä Fer dinand +burn ing +Af ee +Ä tyr ann +Ä I w +Ä Bo one +100 7 +Ä Re pt +Ċ Âł +Ä car avan +Ä D ill +Ä Bundes liga +Ch uck +Ä heal er +ÃŖÄĨÂŧÃŖÄĨ Ĩ +Ä H obby +Ä neg ate +Ä crit iques +section al +mop olitan +Ä d x +Ä outs ourcing +Ä C ipher +t ap +Sh arp +Ä up beat +Ä hang ar +Ä cru ising +Ä Ni agara +Ä 3 42 +ill us +Ä S v +Ä subt itles +Ä squ ared +Ä book store +Ä revolution aries +Ä Carl ton +ab al +Ut ah +Ä desp ise +Ä U M +cons ider +aid o +Ä c arts +Ä T urtles +Tr aining +Ä honor ary + Âĸ +Ä tri angles +4 22 +Ä reprint ed +Ä grace ful +Ä Mong olia +Ä disrupt ions +Ä B oh +Ä 3 49 +Ä dr ains +Ä cons ulate +Ä b ends +Ä m afia +ur on +Ä F ulton +m isc +Ä ren al +Ä in action +ck ing +Ä phot ons +Ä bru ised +Ä C odes +og i +Ä n ests +Ä Love ly +Ä Lib re +Ä D aryl +Ä # ## +S ys +. ," +Ä free zes +est ablishment +and owski +Ä cum bers +Ä St arg +Ä Bom bs +Ä leg ions +Ä hand writing +Ä gr un +Ä C ah +sequ ent +Ä m oth +Ä MS M +Ins ert +F if +Ä mot el +Ä dex ter +Ä B ild +hearted ly +Ä pro pe +Ä Text ure +Ä J unction +ynt hesis +oc ard +Ä Ver a +Ä Bar th +ĠÎÂŧ g +Ä l ashed +Ä 35 1 +Ä Z amb +Ä St aples +Ä Cort ex +Ä Cork er +Ä continu um +Ä WR ITE +unt a +rid or +Ä de ems +0 33 +Ä G OLD +p as +Ä rep ressive +ÃŖÄĨĨ ÃŖÄ¤ÂŖ +Ä baff led +Sc ar +Ä c rave +Ä  ______ +Ä entrepreneurs hip +Ä Director ate +Ä ' [ +Ä v ines +Ä asc ended +Ä GR OUP +Ä Good bye +Ä do gged +ÃŖÄĨ´ ÃŖÄ¤ÂĄ +Man ufact +Ä unimagin able +ri ots +ier rez +Ä rel ativity +Ä Craft ing +ra ught +ud en +c ookie +Ä assass ins +Ä dissatisf ied +ac ci +Ä condu it +Sp read +Ä R ican +n ice +izz le +Ä sc ares +Ä WH Y +ph ans +5 35 +Ä prot racted +Ä Krist en +5 36 +Ä Sc rib +Ä Ne h +Ä twent ies +Ä predic ament +Ä handc uffs +Ä fruit ful +Ä U L +Ä Lud wig +Ä att est +Ä Bre aker +Ä bi ologically +Ä Deal er +Ä renov ations +f w +ess en +Al ice +Ä Hen ri +Ä un ilaterally +Ä S idd +h ai +Ä St retch +S ales +Ä cumbers ome +Ä J avier +Ä trend y +Ä rot ting +Ä Chall enges +Ä scra ps +Ä fac ets +Ä Ver onica +Ä Ver ge +Ä S ana +Al ien +Ä R ih +Ä rad ial +ect ar +Ä 6 30 +cl i +Mar ie +Ä wild fire +Ä Cat o +h ander +Ä wait ress +Ä ch ops +Ä S ECTION +Ä blunt ly +Ä Cat alog +n ian +stud y +Ä pat rolling +Ä T enth +nex us +Ä N ON +op sy +Ä sc athing +s ie +Ä deterior ated +V B +Naz is +Ä dep ictions +Ä authent icated +Ä Con ce +k rit +Ä promul g +Ä L ONG +U FC +Ä Vis itors +Ä Rec all +Ä rehab ilit +Ä SL I +Ä glac ier +Ä B ite +Ä 50 3 +Ä vom it +Ä fer mented +Ä Kh alid +Ä grad ed +Ä Mag icka +Ä Ich igo +power ful +ic ators +75 3 +Ä sh rew +Ä 35 6 +Ä legal izing +Ä all otted +Ä Arch demon +ith ing +igg urat +V OL +Le od +Ä o ily +Ä indu cing +Ä amy gdala +Ä adm ins +Ä Acqu isition +C AN +Ä sche matic +Ä mo an +Ä Camer oon +Ä t ink +Ä mer ry +Ä butter flies +Ä Go ff +Ä works pace +Ä Cor ona +Ä j avascript +Ä D olphin +Ä Cant or +4 64 +to e +AP S +Ä Ag ing +Ä padd ed +Ä Z heng +Ä He ld +Ä est ranged +Ä 7 70 +. } +Ä Dun ham +Ä sm okes +Ä cap itals +und ai +Sh in +Ä Found ing +Ä ent itle +Ä center piece +D iscover +Ä there to +al ert +Ä N ou +Ä Analy st +l c +F H +FI ELD +Ä P OV +gr ay +Ä ar cs +Ä H OT +Ä r s +Ä oblig atory +Ä Architect s +Ä S ven +Ä F EC +0 200 +Christ mas +Ä Alban ia +rat om +58 7 +Ä hard ships +Ä aut os +Ä Charg es +Ä ap es +Ä 3 76 +wal let +Ä intox ication +Ä gobl in +Ä 5 70 +++++++++ ++++++++ +Ä Yel p +Ä Mag netic +Ä Br iggs +R ail +Ä spawn s +Ä W iggins +Ä showc ased +Ä res orted +ub en +Ä wh ipping +Ä im itate +Ä digest ion +Ä US PS +Ä G est +Ä ye a +Ä T ight +ind al +ic as +` . +C AST +'' ; +Ä F et +opath ic +In valid +Ä regrett ed +Ä bro ccoli +Ä Sc ores +e ve +Ä post ings +Ä accum ulating +Ä need less +elf th +Ä may ors +Ä sc rib +Ä anecd otes +Ä bot ched +Ä Rib bon +Ä Constant ine +i uses +ess es +Ä dev ise +Comp ared +Ä p udding +Ä g arg +Ä ev oke +79 7 +Ä det ox +9 09 +Ä Pie ces +Ä McC artney +Ä met ast +Ä K rypt +P OR +Ä t ending +Ä Merch ants +Pro of +Ä V arg +Ä Port able +ÃŖÄĨÂŧÃŖÄĨĨ ÃŖÄ¤ÂŖ +B rain +25 00 +Ä fol iage +Ø š +Ä ment ors +Ä A ires +Ä minimal ist +Ä ing ested +Ä Tro jan +Ä Q ian +inv olved +0 27 +Ä er oded +RA FT +Ä bl urry +M ob +Ä buff et +Ä Fn atic +ae a +KN OWN +Ä In it +s afety +en um +ACT ION +Ä Crus her +Ä D ates +Ä  ................ +c alling +ak ov +Ä vent ured +Ä 5 55 +au ga +H art +Ä A ero +M AC +Ä thin ly +Ä ar ra +ST ATE +ild e +Ä Jac qu +Ä Fem ales +Ä the orem +Ä 3 46 +Ä smart est +Ä PU BLIC +Ä K ron +Ä B its +Ä V essel +Ä Tele phone +Ä dec ap +Ä adj unct +Ä S EN +mer ga +Ä red acted +Ä pre historic +Ä explan atory +Ä Run s +Ä Utt ar +Ä M anny +Ä AUTH OR +Ä Unle ashed +Ä Bow ling +be ans +79 3 +Ä univers es +Ä sens it +Ä K ung +re peat +ctr l +Ä p aced +Ä full er +Cl ock +Ä rec omb +Ä F aul +Ä B unker +Ä pool ed +Ä an a +Ä M outh +LL OW +hum ane +Ä bull do +Ä Micha els +f am +Ä wreck ed +Ä port rays +Ä Wh ale +Ä H es +Ä guess es +Ä Brow se +Ä L APD +Ä consequ ential +Ä Inn ocent +Ä D RAG +Ä trans gress +Ä O aks +Ä tri via +Ä Res on +Ä A DS +-- + +Ä T oll +Ä grasp ing +Ä THE M +Ä T ags +Ä Con clusion +Ä pract icable +Ä ho op +Ä unintention ally +Ä ign ite +Ä M ov +ur ized +le hem +Ter min +Ä colour ful +Ä Lin ear +Ä Ell ie +G y +Ä man power +Ä j s +Ä em oji +Ä SHAR ES +_ . +0000 7 +Ä sophistic ation +Ä unders core +Ä pract ise +Ä bl ob +op ens +Uk raine +Ke eping +Y C +J R +ult imate +Cl aim +Ä autom obiles +99 3 +ste el +Ä part ing +Ä L ank +... ? +Ä 38 5 +Ä remem brance +Ä e ased +Ä cov ari +Ä S ind +Effect ive +Ä disse mination +Ä Mo ose +Ä Cl apper +br ates +App ly +Ä inv is +Ä wors ened +ÃĸÄĸÄļ - +Ä legisl ator +Ä L ol +Ä Row e +Ä dealers hip +um ar +id ences +Ä investig ates +Ä c ascade +Ä bid der +Ä B EN +Iron ically +Ä pres iding +Ä d ing +Ä contrad icted +Ä shut s +Ä F IX +Ä 3 66 +Dist rict +Ä sin ful +Ä Char isma +o ops +Ä tot ality +Ä rest itution +Ä Opt imus +Ä D ah +Ä cl ueless +urn ed +Ä nut rit +Ä land owners +Ä fl ushed +Ä broad en +m ie +Ä print ln +Ä n ig +Ä Corp us +J en +Ä prot o +Ä Wik imedia +Ä Pal o +C OR +Ä story lines +Ä evangel icals +Ä Dar rell +Ä rot or +Ä H W +sk illed +ery l +Ä be gg +Ä Bl umenthal +Ä we aving +Ä down wards +Ä Jack et +Ä ANG EL +Te chnology +Ä es oteric +alde hyde +Ä fur iously +Ä foreign er +We ak +CH O +Ä H ound +Exper ience +Ä Play station +Ä M IA +Ä U ng +cl oth +ag all +Ä cal ming +iz ens +St ruct +Ä W itches +Ä Celeb ration +Ä ........ ...... +pt roller +Ä TC U +Ä b unny +ÃŖÄĨ į +ut orial +Ä up scale +Ä St a +Ä Col ossus +Ä chlor ide +Ä Z ac +Ä Re asons +Ä Brook ings +Ä WH ITE +][ / +Ä L ose +9 05 +Ä unders ide +ern els +Ä v ape +do zen +upp et +Ä ST OP +mat ical +Ä Stat ements +hed dar +P AC +Custom er +Ä mem os +Ä P J +end ars +Ä Lim its +l augh +Ä stabil ized +Ä ALE C +Y A +Up grade +al am +Ä techn o +Ä an ew +fore seen +Ä colleg iate +Ä Py ro +Ä D ism +Ä front line +Ä ammon ia +I U +Qu ite +John ny +ass in +G OP +Ä St yles +Ä Sovere ign +acter ial +5 49 +Ä R IP +Ä L ists +Ä 3 64 +Ä Rece p +s ocket +Ä Byr d +Ä Cand le +An cient +Ä appell ant +en forcement +ace a +ans ki +Ä old s +88 6 +Ä sl urs +Ä em pires +Ä buck le +Ä alien ation +Ä Aber deen +Ä unic orn +Ä overr iding +Ä L X +pp a +Ä desp ised +Ä B ugs +Ä B ST +S outhern +5 33 +Ä hall mark +Ä Post er +Ä stem med +Ä princip als +Ä T ECH +Ä Sand wich +It aly +Ä che esy +Ä Set TextColor +Ä Prot ective +Ä C ohn +J O +apt op +Re ason +Lead er +Ä Under stand +Ä Fr idays +Ä Contin uous +Ä cl ipping +Ä R ye +Ä ber th +tim er +ann is +re act +Ä buff alo +Ä Par as +Ä 6 55 +Ä pres ided +Ä Sun rise +Ä ve ts +Ä cl oves +Ä McC ull +Stre ngth +G AN +Ä ill iter +Ä Pric ing +l Ê +Ä resist or +Ä br un +Ä Suff olk +Ñ Ä­ +Ä L iver +Re leased +Ä what s +8 60 +Ä Me asures +Ä den ouncing +Ä Ry zen +Ä sou ven +Ä careg ivers +ch ini +Ä Scar lett +Ä t rough +Cong ratulations +Ä tax is +Ä Trad ition +j it +Ä table top +Ä hither to +Ä dis information +off ensive +h ra +Ä DISTR ICT +Ä compl icate +chen ko +Ä Recon struction +Ä palp able +Ä a usp +Ä 4 28 +Ä showc ases +Ä Public ation +know ledge +inn on +4 19 +Ä retri eval +and ers +Ä ref ute +Ä inqu ired +g ur +Ä neg ativity +Ä cons erve +Ä after life +Ä pres upp +Ä Gill espie +Ä m t +Ä D N +T ap +Ä per pend +Ä S my +does n +Ä sp illing +Ä hyp ers +K ate +Ž , +ke pt +Ä P owered +Ä j a +Ä K lux +ard e +ab an +Ä 4 44 +Ä flatt ened +Ä Improve ments +urg a +Ä K und +Ä ins cribed +Ä fac ult +Ä unpre pared +Ä Cons umers +Ä satisf ies +Ä pul monary +Ä inf iltration +Ä ex ternally +Ä congrat ulations +ag han +Ä air liner +Ä fl ung +Ä fly ers +G D +Ä snipp ets +Ä rec ursive +Ä master ing +L ex +Ä overt ly +v g +Ä luck ily +Ä enc ro +Ä Lanc et +Ä Abyss al +function al +Ä s ow +Ä squ id +Ä nar ration +Ä n aughty +Ä Hon our +Ä Spart ans +Ä sh atter +Ä Tac oma +Ä Cal ories +Ä R aces +Sub mit +Ä purpose fully +w av +Ä Y ok +F est +Ä G err +Met ro +Ä it iner +f amous +Ä " { +in line +was her +Iss ue +Ä CL IENT +oz o +Vers ions +7 25 +Ä Gl ock +Ä shield ed +Ä PC R +ENC Y +Ä We ld +Ä Sim pl +Ä redirect ed +Ä K ham +Ä ( > +Ä lab ou +Ä di apers +ss l +Ä cell ar +organ isms +ore sc +Ä Ber ks +did n +Sh ipping +C hest +Ä und one +Ä million aire +Ä c ords +Ä Young er +appropri ately +Ä sequ els +u ve +ant icipated +Ä le wd +Ä Sh irt +Ä Dmit ry +V eter +Ä sl aying +Ä Y ar +Ä compl ication +I owa +Ä Eric a +Ä BL M +g irlfriend +b odied +6 26 +19 63 +Ä intermedi ary +Ä cons olation +M ask +Ä Si em +ow an +Beg inning +Ä fix me +Ä culmin ated +Ä con duc +Ä Volunte er +Ä pos itional +Ä gre ets +Ä Defin itions +Ä think er +Ä ingen uity +Ä fresh men +Ä Mom ents +Ä 35 7 +ate urs +Ä Fed Ex +s g +69 4 +Ä dwind ling +Ä BO X +sel age +Ä t mp +Ä st en +Ä S ut +Ä neighbourhood s +Ä class mate +f ledged +Ä left ists +Ä clim ates +ATH ER +Ä Scy the +ul iffe +Ä s ag +Ä ho pped +Ä F t +Ä E ck +Ä C K +Ä Do omsday +k ids +Ä gas ped +Ä mon iker +Ä L od +Ä C FL +t ions +r ums +fol ios +Ä m d +Ä unc anny +Ä trans ports +Ä Lab rador +Ä rail ways +Ä appl iance +Ä CTR L +ÃĻ Äĸ +Pop ulation +Ä Confeder acy +Ä unb earable +Ä dors al +Ä In form +op ted +Ä K ILL +Mar x +Ä hypoc ritical +q us +Ä N umerous +Ä Georg ian +Ä Ambro se +Ä L och +Ä gu bernatorial +Ä X eon +Ä Supp orts +ens er +ee ly +Ä Aven ger +19 65 +Ar my +Ä ju xtap +Ä cho pping +Ä Spl ash +Ä S ustainable +Ä Fin ch +Ä 18 61 +ict ive +at meal +Ä G ohan +Ä lights aber +Ä G PA +ug u +Ä RE PL +vari able +Ä her pes +Ä desert s +ac iously +Ä situ ational +week ly +ob l +Ä text ile +Ä Corn wall +Ä contrace ptives +Ä A ke +] - +äš Ä­ +: , +Ä W em +Ä B ihar +Ä ' . +Ä be re +Ä anal ogue +Ä Cook ies +Ä take off +Whe el +Ä maj estic +Ä comm uting +0 23 +Ä Cor pse +ass ment +min i +Ä gor illa +Ä Al as +ere e +Ä acquaint ances +Ä Ad vantage +Ä spirit ually +Ä ey ed +pm wiki +Ä E nder +Ä trans lucent +Ä night time +Ä IM AGES +5 45 +Ä K amp +Ä Fre ak +Ä  ig +Port land +4 32 +Ä M ata +Ä mar ines +Ä h ors +ater asu +Ä Att ribution +Ä -------- - +Ä k ins +Ä BEL OW +++ + +Ä re eling +ol ed +Ä cl utter +Ä Rel ative +Ä 4 27 +B US +Ä a vert +Ä Che ong +Ä A ble +Ä Pry or +Develop er +Ä en cyclopedia +Ä USA F +Ä G arry +Sp ain +Bl ocks +Ä exp osition +Ä Gamer Gate +W OR +Ä stockp ile +Ä clot hed +Ä T one +Ä R ue +t umblr +Ä treacher ous +Ä f rying +Ñ ÄŽ +Ä S ph +Ä rest raints +Ä emb odies +Ä G es +S afety +Ä negoti ators +min ing +Ä Appalach ian +L OS +Ä Jenn a +Ä pass ers +ç Ä­ +sn ap +Ä short en +creat or +Ä inn umerable +uther land +67 4 +Ä W OM +Ä As cend +Ä Arm ory +Ä Trans action +K ick +Ä suit case +day Name +Ä waste ful +mar riage +Ä McC abe +ite ch +Ä O ss +Cl osure +Ä Treasure r +Ä indec ent +Ä D ull +Ä resid ences +19 59 +Ä S ettlement +Ham ilton +Ä self ies +Ä Rank ing +Ä Bark ley +Ä B ore +Ä W CS +Ä Mar itime +Ä H uh +Ä Forest ry +Ä cultiv ating +Ä Ball ard +Ä g arrison +Ä SD L +9 30 +Ä nas cent +Ä irresist ible +Ä aw fully +\/ \/ +Ä equ ate +Ä anthrop ology +Ä Sylv ia +Ä intest ine +Ä innoc uous +cess ive +ag ra +Ä Met roid +G rant +8 55 +ÄŖ ĸ +Ä " _ +ÃŖÄĨÄĨ ÃŖÄĨÄĢ +Ä appra isal +Ä Fred dy +04 6 +Ä 40 6 +Ä 18 30 +Ä d ocking +St atic +Ä p ont +Ä Volt age +Ä St ead +Ä Mort gage +Ä Jon ah +Y L +CLASS IFIED +Ä as bestos +nik ov +Ä coll agen +Ä Orb ital +P ocket +7 99 +Ä hy brids +inc hes +Ä inv oice +und y +Ä inequ alities +T rend +w ashed +B ALL +Ä luc id +Ä Comment ary +Ä w itty +Br andon +Ä bru ising +Ä 6 20 +es cent +box ing +P OL +Ä 3 78 +R ect +Ä lic ences +Ä McG ee +p ressed +D anny +Ä j ammed +ord inate +Ä le th +Ä distingu ishes +Ä Yam aha +IL S +Ä H ume +Ä C ategories +Rober ts +Ch art +Ä beet le +Ä Gra veyard +Ä ($ ) +o ÄŁ +Ä tw ilight +are lla +ÃĄ ÂŊ +Ä booth s +Ä H HS +Ä Feld man +Ä excav ation +Ä philosoph ies +at ography +Ä Gar age +te chnology +Ä unfor gettable +Ä ver ifying +Ä subord inates +E ls +Ä ne b +G aming +EN A +Ä Achieve ment +it ters +Ä G abe +Ä d umps +for cer +Ä po ignant +Ä M BA +Ä He idi +ime i +Ä m ages +Ä liber ate +Ä circum cised +Ä Mer maid +Ä Mat th +t ogether +Ä W ichita +Ä store front +Ä Ad in +V II +Four th +Ä explore rs +W ER +Not able +Bro ok +m ens +F aith +-------- - +Ä J ou +ÂŦ Âŧ +Ä pine apple +Ä am alg +el n +ark able +Ä ÃŖÄ¤Âĩ ÃŖÄĨÂŧÃŖÄĨÄ¨ÃŖÄ¤ÂŖ +Ä ÃŖÄ¤ÂĩÃŖÄĨÂŧÃŖÄĨÄ¨ÃŖÄ¤ÂŖ ÃŖÄĨÂ¯ÃŖÄĨÂŗ +Ä ov arian +Ä E choes +Ä hairc ut +Ä p av +Ä ch illed +anas ia +Ä sty led +Ä d ab +ni per +Ä minister ial +Ä D UP +T an +Ä sul ph +Ä D eter +Ä Bo hem +od an +Ä educ ator +Ãĸ ÄĩÄē +sp ir +Ch icken +Ä E leanor +Ä qu i +Ä heav iest +Ä grasp ed +U RA +Ä cro oked +Jess ica +pro blem +Ä pred etermined +Ä man iac +Ä breath s +Ä Lauder dale +Ä h obbies +y z +Cr ime +Ä charism a +d L +Ä le aping +Ä k ittens +Ang elo +Ä J ACK +Ä Su zanne +Ä hal ting +ENT ION +Ä swall owing +Ä Earthqu ake +Ä eight eenth +Ä N IC +Ä IN F +Ä Cons cious +Ä particular s +circ le +7 40 +Ä bene volent +Ä 7 47 +Ä 4 90 +Ä r undown +Ä Val erie +Ä B UR +Ä civil isation +Ä S chn +W B +ot ide +intern ational +Ä j ohn +Ä 19 02 +Ä pe anuts +Ä flav ored +k us +Ä ro ared +Ä cut off +Ê ÂŖ +Ä orn ament +Ä architect ures +Ä 3 69 +ol or +Ä Wild e +Ä C RC +Ä Adjust ed +Ä prov oking +land ish +Ä rational ity +Ä just ifies +Ä disp el +Ä a meric +Ä Pol es +Ø Š +Ä en vis +Ä D oodle +äÂŊ Âŋ +igs aw +auld ron +Techn ical +T een +up hem +Ä X iang +Ä detract ors +Ä Z i +Ä Journal ists +Ä conduc ive +Ä Volunte ers +Ä s d +Know ing +Ä trans missions +Ä PL AN +Ä L IB +Ä all uded +Ä ob e +Ä d ope +Ä Gold stein +Ä wavelength s +Ä Dest ination +nd a +ug i +Ä attent ive +Ä Le an +ral tar +Ä man g +mb uds +ak ings +b ender +Ä acc ol +Ä craw led +N OW +Min nesota +Ä flour ished +Ä Z up +Ä Super visor +Ä Oliv ier +Ex cellent +Ä wid en +D one +Ä w ig +Ä miscon ceptions +Cor p +W an +Ä vener able +Ä Not ably +Ä Kling on +an imate +Bo ost +Ä S AY +miss ing +ibli ography +mel on +Ä pay day +Ø Âŗ +bo le +Ä ve iled +Ä Al phabet +It alian +Ä ever lasting +Ä R IS +Ä C ree +rom pt +Ä h ating +Ä grin ning +Ä ge ographically +OS H +Ä we eping +ĠÂłĠÂłĠÂłĠÂł ĠÂłĠÂłĠÂłĠÂł +Ä impe cc +Let ter +Ä blo ated +PL A +Ä Fe in +Ä per sever +Th under +Ä a ur +Ä R L +Ä pit falls +Ãĸĸ Âē +Ä predomin ant +Ä 5 25 +7 18 +AP E +7 14 +Ä farm land +Ä Q iao +Ä v iolet +Ä Bah amas +Ä inflic ting +Ä E fficiency +Ä home brew +Ä undert ook +Ä cur ly +Ä Hard ing +man ia +59 6 +Ä tem pered +Ä har rowing +Ä P ledge +Ä Franken stein +è ÂĒ +M otion +Ä predict ably +Ä Expl osion +oc using +er d +col o +FF ER +Ä back field +Ä V IDE +ue bl +N arr +Ä Arg ument +Ä gen omic +Ä bout ique +Ä batt ed +Ä B inary +Ä g amb +Ä Rh ythm +67 3 +Ä a float +Ä Olymp ia +Y ING +Ä end if +is in +Ä win ters +Ä sc attering +I v +D istance +Ä tr u +Ä Com fort +Ä ne xus +Ä air flow +Ä Byz antine +p ayers +con i +Ä B etsy +D eal +Ä N ug +Ä Contin ent +red ibly +Ä optim izing +al beit +Ä ec static +Ä Pro to +ç ¡ +iv ot +Ãĸĸ ÄĻ +em p +rou nder +Ä cl out +Ä I ST +66 3 +Ä Doll ars +Ä D AC +Ä subsc ribed +Ä rehears al +Ä am ps +Ä Sh ang +es m +Ä spr inkle +Ä assail ant +Ä O o +Ä Coin base +T act +Ä ret ina +Ä n uns +R ON +att o +Ä j ug +Ä SV G +Ä b ikini +Ä FI LE +Ä Found ers +ep ort +Ä K P +Ä rest ores +Ä Th ick +Ä ash ore +Ä appro vals +R ender +M AG +G raham +Ä Cort ana +ÃŖÄĨÂŗ ÃŖÄ¤Â¸ +ss h +or ians +ars ity +Ä Insp ired +u pper +Ä sign alling +Ä reb uke +Ä fl ares +Ä downt ime +Stud ies +Ä stagn ation +Ä Sequ ence +Ä gr unt +Ä ass ures +Ä PL A +59 2 +Ä intra ven +d epend +Sus an +Ä Manz iel +Man ia +Cont ract +Ä sl ams +Ä cult ured +Ä cred itor +L IST +Ä H UM +Ä Chatt anooga +serv ed +Ä clo aked +Ä F TP +p owder +Ä St ella +uct ive +Ä cheap ly +Ä MU CH +Ä Galile o +Ä su ites +spe ech +Ä deliber ations +Ä Ch ips +ÂĢ Äē +Bal ance +Ä Wyn ne +Ä Ak ron +Ass et +Ä hon oured +Ä ed ged +Like wise +anim ous +Ä W age +Ä Ez ek +ad vertisement +Ä RT X +Ä M AD +Ä migr ating +Ä S QU +Ä 4 75 +Ed ited +Ä shorth and +Ä Bas ics +Ä cro tch +Ä EV EN +Ä v m +effic iency +Ä cal ves +Ä F rie +Ä Brill iant +Ä stri kers +Ä repent ance +Ä arter ies +r l +B ed +h ap +Ä crypt ography +Ä Sab res +Ä 4 14 +vi ks +ih ara +aps es +T alking +Ä intertw ined +Ä doc ks +Ä alle le +Ä Art ifact +Ä H IM +t orn +ç ġ +Ä op acity +Ä E ly +os uke +Ä n ipple +Ä hand written +Ä V K +Ä Chamber lain +Ä La os +ig raph +g row +Ä tr illions +Ä descend ant +Ä Sail or +as uring +Ä ce ilings +Ä Ware house +f lying +Ä Gl ow +Ä n ont +Ä miscar riage +Ä rig s +Ä min istries +Ä elabor ated +Ä del usional +Ä Hum ane +Ä 3 79 +n ets +Ä black out +add ers +Ä n p +Ä T ire +ro sc +Ä sub div +Ä link age +Ä chron ological +Ä HER O +Ä res ettlement +Ä Vin yl +Ä past oral +Ä Mob il +Ä Bar bar +Co oldown +Ä F ritz +c riminal +re pe +Ä bell ig +Ä Bre ed +Ä 4 18 +Ä sem blance +ij k +Ä cur tail +Ä clin ch +cont ained +Ä Prom pt +ast on +Ä w i +Ä pursu its +5 15 +Ä Gl oss +Ä fl ips +Ä coup ons +Ä cl oning +Ä Like ly +Rem oved +Ä Qu artz +r ices +Ä Spe ars +Ä p ious +Ä dep reciation +Ä D are +oun ces +am az +O nt +Ä p innacle +d ocker +0 26 +Ä W yr +Ä Pro per +Ë ÄĒ +n il +By tes +Ä seek er +t rial +Ä unf olds +Ä Mar se +Ä extravag ant +Ä Surviv ors +RED ACTED +Ä Speed way +Ä Cra igslist +sub mit +Ä Gener ations +Ä up holding +Ä blood stream +Ä Miss ions +Ä L awn +Ä lim bo +ene i +H uh +Ä Wild cats +pre p +Ä Mark us +Ä For bidden +rit ic +IN O +Ä exhib iting +requ ent +ch uk +Ä habit ual +Ä Comp atibility +Dr ag +RIP T +uj ah +GR OUND +Ä delinqu ent +Ä burn er +Ä contempor aries +Ä gimm ick +load s +Ä no zzle +p odcast +Ä W ak +Ä Stat en +Ä K uh +ÃŖÄŖ Äĩ +inter rupted +Ä inv incible +Ä Burn ett +cig arette +Ä Peb ble +Ä Tem porary +Ä Mar ino +58 2 +Ä wast eland +ident ly +T x +Ä r ite +Ä Pan asonic +Ä M iddles +Ä Hort on +ae us +Ä c uring +Ä m ats +Ä adj ourn +Ä fears ome +pe z +bo ats +Ä pro pell +Ä conflic ted +Ä Ang er +Ä insurg ent +K arl +Ä co ales +Ä south western +Ä dis su +Ä O vert +******** **** +Ä box ed +Ä Br une +aa a +Ä gard ening +Ä Eng el +tr acks +Ä pur ified +Ä place holder +Ä L ikes +Ä d an +G ab +Ä e ct +Ä F aw +Ä El iot +Ä ' , +otrop ic +Ä Ru in +hed on +Ä ca ul +Ä a ft +Ä Cad illac +gh a +ass ian +ud eb +Ä T ick +Ä adjust s +AR GET +5 37 +isc he +ant y +Ä Fried rich +Ä Bl izz +Ä A OL +Camp aign +Ä mamm al +Ä Ve il +Ä K ev +Ä Maur it +Ä Dam ien +N ation +E astern +Ä { : +Ä = ================================ +Ä stereotyp ical +Ä att ic +Ä Cy borg +requ ire +Ä award ing +Ä Pap ua +bt n +b ent +B oo +Ä ( = +Ä X ander +Ä Somers et +Ä catch y +Ä cert ify +STR UCT +Ä it al +Ä t ides +Ä Br ands +G ray +comp etitive +Ä cur ator +Ä D G +omin ium +Ä GM Os +ci ating +Ä Carm en +ow ard +Balt imore +Ä r gb +C u +Ä wip es +spe ll +IT NESS +Ä summar izes +Ä Re vis +Ä whistlebl owers +Ä Bre ach +Ä cro chet +k os +ews ki +Ä rep et +Ä crim son +Ä Kar achi +read able +dim ension +Ä I gor +ild ed +Ä Z ed +Ä Ke ane +Ä Cos metic +DE P +Ä retreat ing +Ä U A +ens ical +Ä d usk +Ä Dick ens +Ä aren as +Ä Pass age +level s +Ä cur v +P ope +Ä ch ores +Ä El ise +Ä Comp ass +b ub +Ä mamm alian +Ä Sans krit +Ä AN C +Ä Cr ack +Q ual +L aun +amp unk +Ä learn ers +Ä glam orous +Ä fur the +erm ott +c and +Gener ic +Ä narr ated +Ä disorder ly +Ä Trans actions +Ä Det ention +Ä R oku +Ä į +Ä under statement +Ä S aur +Ä Rodrig o +Ä AS AP +S in +Ä re joice +Method s +Ä electro de +Ä worsh ipped +Ä id i +Ä Phys icians +Ä pop up +Ä de ft +Ä Rem oval +Ä Bu enos +ver bs +Ä fun k +ush a +rict ion +ore a +Ä Bang alore +Ä Ken obi +zz i +Ä norm ative +Ä gobl ins +Ä caf es +Ä UN CLASSIFIED +Ä F ired +S IGN +Ä s clerosis +Ä V oter +Ä Son ny +Ä Ext end +Ä EV s +Ar senal +Ä p si +Ä wid est +Ä T us +Ä lo oms +Ä just ifying +Ä Gr anger +è ¯ +Ref er +58 3 +Ä flour ishing +ab re +Ä r ave +Ä Cont ra +Ä 18 98 +Add s +Ä f ul +Ä Co oke +some one += # +67 1 +Ä y ak +Ä ar te +Ä Mis cellaneous +Ä Det ection +Ä Cl ancy +Ãĸ ÄŖ +ass ies +Ä val iant +Ä Femin ist +cor ruption +V el +P ear +Ä succ inct +Ä quick est +k w +Ä sp itting +Ä L ibraries +ÃĨħ ÄĢ +ant z +D ad +Ä Spec ifications +rup ulous +and r +RES ULTS +Ä snow ball +Ä pred is +Ä B axter +Ä Nurs ing +Ä Ch aff +s we +Ä out age +Ä nest ing +Ä notor iety +tr igger +on ite +j on +Ä f ou +ook ed +Ä Celebr ity +re ality +Ä fat ig +Ä hug ging +Ä bother s +Ä Pan zer +Ä Ch andra +fig ured +Ä vol ts +Ä Cloud s +Ä fee ble +Ä Cur ve +Ä As us +78 6 +abs or +Ä V ICE +Ä H ess +Ä manufact ures +Ä gri zz +Ä Power ful +ac id +Ä sub sections +Ä Krug man +Ä Al ps +is u +Ä sequ est +Ä Ult ron +Ä T inker +Ä Go ose +Ä mism atch +Att orney +Ä morph ology +Ä Six ers +ut tered +Ä E LECT +gr an +Rus sell +Ä G SL +Ä fort night +Ä . ) +Ä apost le +pr one +el ist +Unt itled +Ä Im plementation +ist ors +Ä tank er +Ä pl ush +Ä attend ants +Ä T ik +Ä Green wich +Ä Y on +Ä SP L +cell s +unt led +S olution +Ä Qu Ê +Ä vac ated +Ä upt ick +Ä Mer idian +ÃĻ ÄĨ +Ä Dr ill +9 25 +58 4 +Ä renov ated +Ä Kub rick +zy k +Ä l ousy +pp el +ohyd rate +Ä I zzy +lesi astical +CC C +Ä Aj ax +Ä ad apters +Ä Petra eus +Ä affirm ation +Ä ST OR +le ms +ad oes +Ä Constantin ople +Ä p onies +Ä l ighthouse +Ä adherent s +Ä Bre es +omorph ic +Fight ing +Ä pl aster +Ä P VC +Ä Ob st +Ä dear ly +Ä To oth +icks on +Ä sh aming +P lex +A gg +Ä ÃĸÄĸÂĻ " +Ä sub reddits +Ä pige on +Ä Resident ial +Ä Pass ing +Ä l um +Ä P ension +Ä pessim istic +Ä 4 32 +z inski +c ade +0 75 +Ä apolog ised +iy ah +Put ting +Ä gloom y +Ä Ly me +=-=-=-=- =-=-=-=- +Ä T ome +Ä Psych iatric +Ä H IT +c ms +ap olog +Ä break er +Ä deep en +Ä theor ist +Ä High lands +Ä b aker +Ä st aples +Ä interf ered +Ä Ab ortion +jo ined +ch u +Ä form ulate +Ä vacc inations +Ä ban ter +phe us +Ä outfield er +Ä M eter +Ä # #### +Ä 18 95 +Ä narrow ing +Ä ST ORY +f p +Ä C ST +ign ore +Ä proclaim ing +Ä R U +Ä B ALL +yn a +65 3 +Ä pos it +P RE +59 4 +Ä Regist rar +Ä Pil grim +ic io +Ä pre tt +Ä lif eless +Ä __ _ +Ne igh +Ä Ch urches +orn o +Ä or cs +Ä kind red +Ä Aud it +Ä millenn ial +Ä Pers ia +g ravity +Ä Dis ability +Ä D ARK +W s +od on +Ä grand daughter +Ä Bro oke +Ä A DA +ER A +Ä pick ups +Ä Wil kinson +Ä Sh ards +Ä N K +Ä exp el +Ä Kis lyak +Ä j argon +Ä polar ized +ian e +Pub lisher +Ä reb utt +Ä apprehens ion +Ä K essler +Ä pr ism +F UL +19 64 +Ä L oll +ä Âŋ +le thal +Å Ł +Ä g hetto +Ä b oulder +Ä Slow ly +Ä Osc ars +Ä Inst ruction +Ä Ul tr +Ä M oe +N ich +Ä P ATH +( * +Ä RE LEASE +un ing +rou se +en eg +Ä re imb +Ä Det ected +Do S +Ä ster ling +Ä aggreg ation +Ä Lone ly +Ä Att end +hig her +Ä airst rike +ks on +SE LECT +Ä def lation +Ä Her rera +C ole +rit ch +Ä advis able +F ax +Ä work around +Ä p id +mort em +ers en +Ä typ o +Ä al um +78 2 +Ä Jam al +script s +Ä capt ives +Ä Pres ence +Ä Lie berman +angel o +Ä alcohol ism +ass i +Ä rec ite +Ä gap ing +Ä bask ets +Ä G ou +Brow ser +ne au +Ä correct ive +und a +sc oring +Ä X D +Ä fil ament +Ä deep ening +Ä Stain less +Int eger +Ä bu ggy +Ä ten ancy +Ä Mub arak +Ä t uple +Ä D roid +Ä S itting +Ä forfe it +Ä Rasm ussen +ixt ies +es i +Ä Kim mel +Ä metic ulously +Ä ap opt +Ä S eller +08 8 +ec ake +hem atically +T N +Ä mind less +Ä dig s +Ä Acc ord +ons ense +em ing +br ace +Ä e Book +Ä Dist ribut +Ä Invest ments +w t +] ), +beh avior +56 3 +Ä bl inding +Ä Pro testers +top ia +Ä reb orn +Ä Kel vin +Ä Do ver +Ä D airy +Ä Out s +Ä [ / +Ï Äĸ +b p +Ä Van ity +Ä Rec ap +Ä HOU SE +Ä F ACE +Ä 4 22 +69 2 +Ä Ant ioch +cook ed +Ä coll ide +Ä a pr +Ä sle eper +Ä Jar vis +Ä alternative ly +Ä Le aves +Ä M aw +Ä antiqu ity +Ä Adin ida +Ä ab user +PokÊ mon +Ä ass orted +Ä Rev ision +Ä P iano +Ä G ideon +O cean +Ä sal on +Ä bust ling +ogn itive +Ä Rah man +Ä wa iter +Ä pres ets +Ä O sh +Ä G HC +oper ator +Ä rept iles +Ä 4 13 +Ä G arr +Ä Ch ak +Ä has hes +Ä fail ings +Ä folk lore +Ä ab l +Ä C ena +Ä Mac Arthur +Ä COUR T +Ä peripher y +app ers +Ä reck oned +Ä Inf lu +Ä C ET +Ä 3 72 +Ä Defin itive +ass ault +4 21 +Ä reservoir s +Ä d ives +Ä Co il +DA Q +Ä vivid ly +Ä R J +Ä Bel lev +Ä ec lectic +Ä Show down +Ä K M +ip ed +reet ings +Ä As uka +L iberal +ĠÏ ÄĻ +Ä bystand ers +Ä Good win +uk ong +S it +Ä T rem +Ä crim inally +Ä Circ us +ch rome +88 7 +Ä nan op +Ä Ob i +Ä L OW +o gh +Ä Auth ors +ob yl +Ur ban +Ä t i +Ä We ir +t rap +ag y +Ä parent heses +Ä out numbered +Ä counter productive +Ä Tob ias +ub is +P arser +ST AR +Ä syn aptic +Ä G ears +Ä h iber +Ä debunk ed +Ä ex alted +aw atts +H OU +Ch urch +Ä Pix ie +Ä U ri +Ä Form ation +Ä Pred iction +C EO +Ä thro tt +Ä Brit ann +Ä Mad agascar +ÃĢ Ä­ +Ä bill boards +Ä RPG s +Ä Be es +complete ly +F IL +Ä does nt +Ä Green berg +re ys +Ä sl ing +Ä empt ied +Ä Pix ar +Ä Dh arma +l uck +ingu ished +Ä end ot +Ä bab ys +05 9 +che st +r ats +Ä r idden +Ä beet les +Ä illum inating +Ä fict itious +Ä Prov incial +Ä 7 68 +Ä she pherd +Ä R ender +Ä 18 96 +C rew +Ä mold ed +Ä Xia omi +Ä Sp iral +Ä del im +Ä organ ising +Ä ho ops +Ä Be i +z hen +Ä fuck in +Ä dec ad +Ä un biased +am my +sw ing +Ä smugg led +Ä k ios +Ä P ERSON +Ä Inquis itor +Ä snow y +Ä scrap ing +Ä Burg ess +P tr +ag ame +R W +Ä dro id +Ä L ys +Ä Cass andra +Jac ob +Ä 35 4 +Ä past ure +Ä fr anc +Ä Scot ch +Ä End s +Ä I GF +def inition +Ä hyster ical +Ä Brown e +77 1 +Ä mobil ization +ÃĻ Äˇ +iqu eness +Th or +Ä spear headed +Ä embro iled +Ä conject ure +jud icial +Ch oice +Ä paper back +P ir +Ä rec overs +Ä Sur ge +Ä Sh ogun +Ä Ped iatrics +ÃŖÄŖ ł +Ä sweep s +Ä Labor atories +Ä P acks +al us +add in +Ä head lights +g ra +Ev idence +COL OR +Ad min +ÄŦ Âą +Ä conco ct +s ufficient +Ä un marked +Ä rich ness +Ä diss ertation +Ä season ing +Ä g ib +Ä M ages +un ctions +Ä N id +che at +Ä TM Z +c itizens +Ä Catholic ism +n b +Ä disemb ark +Ä PROG RAM +a ques +Ty ler +Or g +Ä Sl ay +Ä N ero +Ä Town send +IN TON +te le +Ä mes mer +9 01 +Ä fire ball +ev idence +aff iliated +Ä French man +Ä August a +0 21 +Ä s led +Ä re used +Ä Immun ity +Ä wrest le +assemb led +Mar ia +Ä gun shots +Ä Barb ie +Ä cannabin oids +Ä To ast +Ä K inder +IR D +Ä re juven +Ä g ore +Ä rupt ure +Ä bre aching +Ä Cart oon +Ä 4 55 +Ä Pale o +6 14 +Ä spe ars +Ä Am es +ab us +Mad ison +GR OUP +Ä ab orted +y ah +Ä fel on +Ä caus ation +Ä prep aid +Ä p itted +op lan +Ä Shel ley +Ä Rus so +Ä P agan +Ä will fully +Ä Can aver +und rum +Ä Sal ary +Ä Ar paio +read er +Ä R ational +Ä Over se +Ä Ca uses +Ä * . +Ä w ob +Ke ith +Ä Cons ent +man ac +77 3 +6 23 +Ä fate ful +et imes +Ä spir ited +Ä D ys +Ä he gemony +Ä boy cot +Ä En rique +em outh +Ä tim elines +Ä Sah ara +Ä Rel ax +Ä Quin cy +Ä Less ons +Ä E QU +SE A +N K +Ä Cost co +Incre ase +Ä motiv ating +Ä Ch ong +am aru +Ä Div ide +Ä ped igree +Ä Tasman ia +Ä Prel ude +L as +9 40 +57 4 +Ä ch au +Ä Sp iegel +un ic +-- > +Ä Phil ips +Ä Kaf ka +Ä uphe aval +Ä sent imental +Ä sa x +Ä Ak ira +ser ial +Mat rix +Ä elect ing +Ä comment er +Ä Neb ula +ple ts +Ä Nad u +Ä Ad ren +Ä en shr +Ä R AND +fin ancial +Ä Cly de +uther ford +Ä sign age +Ä de line +Ä phosph ate +rovers ial +f ascist +Ä V all +Ä Beth lehem +Ä for s +Ä eng lish +S olid +N ature +Ä v a +Ä Gu ests +Ä tant al +Ä auto immune +;;;;;;;; ;;;; +Ä Tot ally +Ä O v +Ä def ences +Ä Coc onut +Ä tranqu il +Ä pl oy +Ä flav ours +Ä Fl ask +ÃŖÄ¤Â¨ ÃŖÄĨÂĢ +Ä West on +Ä Vol vo +8 70 +Ä micro phones +ver bal +R PG +Ä i ii +; } +0 28 +Ä head lined +Ä prim ed +Ä ho ard +Ä Sh ad +Ä EN TER +Ä tri angular +Ä cap it +l ik +Ä An cients +Ä l ash +Ä conv ol +Ä colon el +en emy +G ra +Ä pub s +ut ters +Ä assign s +Ä Pen et +Ä Mon strous +Ä Bow en +il ver +H aunted +Ä D ing +start ed +pl in +Ä contamin ants +Ä DO E +ff en +Ä Techn ician +R y +Ä rob bers +Ä hot line +Ä Guard iola +Ä Kau fman +row er +Ä Dres den +Ä Al pine +E lf +Ä f mt +Ä S ard +urs es +g pu +Un ix +Ä unequiv ocally +Ä Citizens hip +qu ad +m ire +Ä S weeney +B attery +6 15 +Ä panc akes +Ä o ats +M aps +Ä Cont rast +mbuds man +Ä E PS +Ä sub committee +Ä sour cing +Ä s izing +Ä Buff er +Ä Mand atory +Ä moder ates +Ä Pattern s +Ä Ch ocobo +Ä Z an +Ä STAT ES +Ä Jud ging +Ä In her +* : +Ä b il +Ä Y en +Ä exh ilar +oll ower +z ers +Ä sn ug +max imum +Ä desp icable +Ä P ACK +Ä An nex +Ä sarcast ic +Ä late x +Ä t amp +Ä S ao +b ah +Ä Re verend +Ä Chin atown +Ä A UT +d ocumented +Ä GA BA +Ä Can aan +ĠÙ ħ +Ä govern s +pre v +E sc +Ä Est imates +OS P +Ä endeav our +Ä Cl osing +omet ime +every one +Ä wor sen +Ä sc anners +Ä dev iations +Ä Robot ics +Ä Com pton +Ä sorce rer +Ä end ogenous +Ä em ulation +Ä Pier cing +Ä A ph +Ä S ocket +Ä b ould +Ä O U +Ä Border lands +Ä 18 63 +G ordon +Ä W TO +Ä restrict s +Ä mosa ic +Ä mel odies +ç ÄĻ +T ar +Ä dis son +Ä Prov ides +Ä  ...... +b ek +F IX +Ä bro om +ans hip +Do ctors +Ä ner ds +Ä Reg ions +na issance +Ä met e +Ä cre pt +pl ings +Ä girlfriend s +kn it +ig ent +ow e +Ä us hered +Ä B az +M obil +4 34 +Ä Pres ents +orig in +Ä ins omnia +Ä A ux +4 39 +Ä Ch ili +irs ch +G AME +Ä gest ation +alg ia +rom ising +$ , +c row +Ä In spection +at omic +Rel ations +J OHN +rom an +Ä Clock work +Ä Bak r +m one +M ET +Ä thirst y +Ä b c +Ä facult ies +R um +Ä nu ance +Ä D arius +ple ting +fter s +etch up +Reg istration +Ä K E +R ah +Ä pref erential +Ä L ash +Ä H H +Val id +Ä N AV +Ä star ve +Ä G ong +z ynski +Ä Act ress +Ä w ik +Ä un accompanied +lv l +Br ide +AD S +Ä Command o +Ä Vaugh n +Wal let +Ä ho pping +Ä V ie +Ä cave ats +Ä al as +if led +ab use +66 1 +Ä ib n +Ä g ul +Ä rob bing +t il +IL A +Ä mit igating +Ä apt ly +Ä ty rant +Ä mid day +Ä Gil more +Ä De cker +Ġ§ § +part ial +Ex actly +Ä phen otype +Ä [+ ] +Ä P lex +Ä I ps +vers ions +Ä e book +Ä ch ic +g ross +":" "},{" +Ä Sur prisingly +M organ +Ä resid ues +Ä Conf ederation +in feld +Ä l yr +mod erate +Ä perpend icular +V K +Ä synchron ized +Ä refres hed +Ä ad ore +Ä Tor ment +ol ina +Ä 26 00 +Item Tracker +Ä p ies +Ä F AT +Ä R HP +0 48 +Ä RES P +Ä B J +all ows +P and +Ä unw elcome +Ä V oc +Ä Bast ard +Ä O W +Ä L AR +Ä Heal er +Environment al +Ä Ken yan +Ä Tr ance +Ä P ats +Ä ali ases +Ä Gar field +Ä campaign er +Ä advance ments +Ä Okin awa +Ä C oh +ows ky +Ä star ved +Ä size able +Ä : -) +Ä m RNA +Ä susp ensions +ist ar +Scot land +Pr in +-------------------------------- ---------------- +Ä 50 2 +Ä teasp oons +Ä 10 50 +Ä coerc ive +Ä Mason ic +edd ed +Ä Pass enger +Ä l att +Ä br aces +Ä St eal +Ä NY T +Ä K ats +Ä Cel est +ae z +T u +Ä Coul ter +ðŁ Äē +Fl ickr +Ä Wil mington +ith s +++ ; +Ä v ending +Ä neg ro +Ä Ph i +Ä Yellow stone +Call back +Ä sh ampoo +Ä Sh ades +w at +Ä super human +Ä ridic uled +Ä hol iest +om bo +Ä intern s +Ä h one +Ä Par agu +UR I +Ä d angling +ÃŖÄ¤ Âģ +so v +ict ional +av ailability +Ä rev ocation +Ä d ow +in ic +Ä THE IR +Ä is o +Ä out ings +Ä Leth al +Ä ) )) +Ä inacc ur +Ä out landish +Ä an us +let ico +id on +l ol +Ä un regulated +Ä succumb ed +Ä c uff +Ä Wast eland +let al +Ä sub str +Ä coff ers +Ä autom akers +ov i +Ä X ue +Ä Dayton a +Ä jar ring +Ä f umes +Ä disband ed +z ik +itt on +Ä striking ly +Ä sp ores +Ad apter +.) : +Ä Lynd on +ival ry +Ä or ally +Ä tumult uous +Ä disple asure +Ä con es +or rect +Ä appe ase +Ä der by +Ä Trip oli +Ä Al ess +Ä p oked +Ä Gu ilty +v P +En ough +Ä orig inals +6 99 +Ä rabb i +Ä proverb ial +Ä postp one +el ope +Ä Mist y +Ä staff ed +Ä Un employment +redit ary +Ä dilig ent +re comm +me asures +as in +8 25 +Ä pond s +Ä mm ol +Ä S AR +Ä C ARE +Ä 3 71 +Ä clen ched +Ä Cors air +Ä caric ature +z n +att ach +Ä Sch ro +spe ak +p ainted +Ä S uc +Ä E NT +Ä cell ul +Ä P aid +di agn +WH ERE +Ä text ed +B arn +Ä ret racted +Ä Re ferred +S av +Ä up keep +Ä work places +Ä Tok ens +Ä ampl ify +cl inical +Ä mult ic +mber g +Ä convol uted +Reg ion +5 65 +Ä Top ic +Ä sn ail +Ä sal ine +Ä ins urrection +Ä Pet r +f orts +B AT +Ä Nav ajo +Ä rud imentary +Ä Lak sh +OND ON +Me asure +Ä transform er +Ä Godd ard +Ä coinc ides +ir in +R ex +Ä B ok +qu it +Ä shotgun s +Ä prolet arian +Ä sc orp +Ä Ad a +5 14 +Ä sl ander +record ed +Ä emb ell +ris ome +Ä apolog izing +Ä Mul cair +Ä Gib raltar +Cl a +Ä all ot +Ä Att ention +Ä 4 33 +le ave +Ä wh ine +Ä Iss a +Ä Fa ust +Ä Bar ron +hen y +Ä victim ized +J ews +Ä nurt uring +ett el +W inged +Ä Sub tle +Ä flavor ful +Ä Rep s +eng ed +call back +Ä direction al +Ä cl asp +Ä Direct ions +plan et +icult ure +Hel per +ic ion +ac ia +Ġç ÂĨŀ +Ä sur ges +Ä can oe +Ä Prem iership +be en +Ä def ied +Ä Tro oper +Ä trip od +Ä gas p +Ä E uph +Ä Ad s +vern ight +high ly +R ole +Ä ent angled +Ä Ze it +6 18 +Ä Rust y +Ä haven s +Ä Vaugh an +HA EL +Ä SER VICE +/ , +Ä str icken +Ä del usions +Ä b is +Ä H af +Ä grat ification +Ä ent icing +UN CH +Ad ams +Ä OL ED +Ä Beet le +Ä 18 99 +Ä SO FTWARE +ateg or +V L +Ä Tot em +Ä G ators +AT URES +Ä imped ance +Reg istered +Ä C ary +Ä Aer ial +on ne +en ium +Ä d red +Ä Be g +Ä concurrent ly +Ä super power +Ä X an +j ew +imes ter +Ä Dick inson +ÃĸÄļ ÄŖ +F la +Ä p ree +Ä Roll ins +Š ÂļÃĻ +Ä den omination +Ä L ana +5 16 +Ä inc iting +sc ribed +j uries +Ä Wond ers +app roximately +Ä susp ending +Ä mountain ous +Ä L augh +oid al +N s +Det ect +) = +Ä L uthor +Ä Schwarz enegger +Ä Mull er +Ä Dev i +ec ycle +J ar +6 13 +Ä L ongh +B ah +Ä SP ORTS +n w +Ä ref inement +Ä water ways +Ä d iner +Bl ade +68 3 +F ac +Ä initial s +Ä ro g +Ä paran ormal +B UT +Ä [ ( +Ä Sw anson +Ä M esh +Ãĸĸ ÂŦ +Impro ve +Ä Rad iation +Ä Est her +Ä E sk +Ä A ly +ik y +Ä ir rad +Ä Buck ingham +Ä ref ill +Ä . _ +Re pe +CON CLUS +Ä different iated +Ä chi rop +Ä At kins +Pat tern +Ä exc ise +Ä cab al +N SA +Ä ST A +Ä S IL +Ä Par aly +Ä r ye +Ä How ell +Ä Count down +ness es +alys ed +Ä res ize +ÃŖÄ¤ ÂŊ +Ä budget ary +Ä Str as +w ang +Ä ap iece +Ä precinct s +Ä pe ach +Ä sky line +Ä 35 3 +pop ular +App earances +Ä Mechan ics +Ä Dev Online +S ullivan +Z en +Ä p u +op olis +5 44 +Ä de form +Ä counter act +Ä L ange +Ä 4 17 +Con sole +77 4 +Ä nodd ing +Ä popul ism +Ä he p +Ä coun selling +compl iance +U FF +Ä unden iably +Ä rail ing +Ä Hor owitz +Ä Sim one +Ä Bung ie +Ä a k +Ä Tal ks +x ff +fl ake +Cr ash +Ä sweat y +Ä ban quet +Ä OFF IC +Ä invent ive +Ä astron omer +Ä Stam ford +Ä Sc are +Ä GRE EN +olic ited +Ä r usher +Ä cent rist +ight ing +Ä sub class +Ä dis av +Ä def und +Ä N anto +oci ate +m ast +Ä pac if +Ä m end +e ers +imm igration +ESS ION +Ä number ing +Ä laugh able +Ä End ed +v iation +em ark +P itt +Ä metic ulous +Ä L F +Ä congrat ulated +Ä Bir ch +Ä sway ed +Ä semif inals +Ä hum ankind +m atter +Ä Equ ip +opa usal +S aid +Ä Lay out +Ä vo icing +Ä th ug +Ä porn ographic +I PS +Ä mo aning +Ä griev ance +Ä conf essions +esc al +TEXT URE +Aut hent +os aurus +P urchase +Ä releg ation +al ter +ĠÂł Âł +Ä r iddled +Ä o gre +Ä Low ell +Occ up +E at +Ä Hy der +Ä Advis er +Com merce +H unt +Ä Or th +Ä Comp etitive +Ä CL A +CD C +Ä sal ads +F le +Ä industrial ized +` , +Ä O WN +Ä bec k +Ä Part icularly +oub t +Ä m M +Ä Huss ain +Ä Chen nai +Ä 9 20 +Ä appoint ing +Ä Cull en +,,,, ,,,, +Ä p ores +ver ified +Ä bi ochemical +em ate +Ä coward ly +Ä Hels inki +Ä Ethiop ian +S OURCE +ER C +est ro +Ä bi otech +Ä S our +Ä brew er +Bloom berg +Ä intens ify +Gl ass +an co +Ä F DR +gre SQL +Ä F ires +ŠÂļÃĻ ÂĨÂĩ +ec o +100 1 +Ä Hom eless +Ä instant aneous +Ä H aste +ig el +D iamond +Ä p aving +Ä land fill +Ä d ads +h oun +: ] +Ä inc endiary +Ä Living ston +Ä Hil bert +Ä Che cks +st yles +in ators +Ä Cl ive +ph rine +Ä chimpan zees +Ä p all +Ä J M +Ä Aad haar +ð Äŋ +Ä achie vable +dis abled +P ET +OOOO OOOO +M ot +Ä int angible +Ä bal let +Ä We bs +Ä Est imated +Effect s +Ä b ailed +Josh ua +Ä turb ulence +Ä occup ant +Ä Day light +Ä 36 1 +me et +Ä stat ically +Ä on look +Ä k i +il legal +Ä vel vet +Ä dehyd ration +Ä acqu ies +Ä Re z +ak ura +Ä U pton +at ro +Ä incomp rehensible +Ä back door +Ä Rh ino +7 27 +Ä math s +) + +Ä he resy +Ä d f +Ä Roc he +Ä L ydia +Ä panc reat +re ply +arre ll +Ä solicit ation +Ä circ adian +BI P +Ä for ay +Ä crypt ic +iz u +ime o +Ä Tom ato +Ä H oms +ex amination +Ä qu arry +Ä Val iant +Ä Jer icho +Ä IN CLUD +Ä 18 40 +5 19 +Ä res ists +Ä snap shots +Ä Sp ur +Ä Ant iqu +Log in +Ä best selling +Ä ant ic +Ä S utherland +ÃŖÄ¤Âĸ ÃŖÄĨÂĢ +Ä ~ / +Ä P arm +è ÄĨ +P ages +int ensity +Ä imm obil +Ä 18 65 +zz o +Ä n ifty +Ä f entanyl +Ä Pres ervation +op hen +Ä d arts +Ä D inosaur +po inters +Ä R ite +s uggest +aware ness +Ä Sher idan +Ä st ances +Ä sor cery +Ä per jury +Ä Nik ola +ie ver +Ä f iance +Ä Jordan ian +Ä Ball oon +Ä n ab +Ä k b +Ä human ities +Ä Tan aka +hill ary +Ä consult ancy +Ä Z ub +Ä rem ission +Ä conf id +CH Q +Ä F ug +Ä impro vis +Y ep +/ _ +Ä unwilling ness +Ä port folios +05 5 +Ä Instruct or +aim an +Ä claim ants +M bps +Ä By e +re ceived +T weet +Ä ind emn +ri z +am ara +N at +Ä eval uates +Ä L ur +ep ad +FO X +Ä Th ro +Ä rust y +Ä bed rock +Ä Op rah +J B +Ä manip ulative +Ä will ful +Ä rel apse +Ä ext ant +The me +S ensor +Ä St ability +go vern +Ä po ppy +Ä kn ack +Ä ins ulated +Ä T ile +Ä Ext rem +Ä unt old +Ä conver ge +Ä ref uel +ig roup +Ä distort ions +Ä rav aged +Ä mechan ically +Ä Re illy +Ä N ose +Ä Incarn ation +Ä Beck y +abb ling +Ä t aco +Ä r ake +Ä melanch oly +Ä illust rious +Ä Dart mouth +Gu ide +Ä R azer +Ä Ben z +Ult imate +Ä Sur prise +Ä page ant +off er +Who ever +Ä w iser +Ä chem ist +Ä HE LL +Ä Bul k +Ä pl utonium +Ä CO VER +Ö Âŧ +f ailed +Ä tire lessly +Ä inf ertility +Ä Tr ident +Ä Show time +Ä C iv +V ice +requ ires +itt ance +Ä un controlled +interest ing +56 1 +Ä innov ate +ateg ic +L ie +Ä S elling +U l +Ä sav ior +Ä T osh +Ä sw ast +P ASS +Ä r ink +Ä card io +Ä I ro +ud i +Ä v antage +Ä v ans +Ä Ni ÃƒÂąo ++ = +Ä propag ate +< ? +Ä method ological +204 39 +Ä trig lycer +Ä ing rained +Ä An notations +arr anted +6 17 +Ä S odium +Ä A AC +techn ical +mult ipl +Ä 3 73 +ÃĨ Ä­ +Ä dec isively +Ä boost ers +Ä dessert s +Ä Gren ade +Ä test ifying +Ä Sc ully +ID s +Ä lock down +Ä Sc her +Ä R Ê +Ä Whit man +Ä Rams ay +rem ote +Ä h ikers +Ä Hy undai +Ä cons cientious +Ä cler ics +Ä Siber ian +ut i +is bury +Ä rel ayed +Ä qu artz +Ä C BI +seek ers +ull a +Ä weld ing +Ä Sh al +ble acher +T ai +Ä Sam son +Ä t umble +Ä Invest or +Ä sub contract +Ä Shin ra +ow icz +j andro +d ad +Ä termin ating +Ä Ne ural +äÂģ ÂŖ +Ä leak age +Ä Mid lands +Ä Caucas us +í ġ +c it +ll an +iv ably +Ä Alb ion +Ä 4 57 +Ä regist rations +Ä comr ade +Ä clip board +0 47 +Ä discour aging +Ä O ops +Ad apt +Ä em path +n v +Ä PR OT +Ä Don n +Ä P ax +Ä B ayer +t is +Squ are +Ä foot prints +part icip +Ä Chile an +B rend +ind ucing +M agn +Ä club house +Ä Magn um +Ä enc amp +Ä Eth nic +uch a +ere y +Ä w atered +Ä Cal ais +Ä complex ion +Ä sect s +Ä ren ters +Ä br as +oÄŁ an +Time out +Man agement +Ä inf ographic +P okemon +Cl ar +Ä loc ality +Ä fl ora +as el +P ont +Ä pop ulate +Ä O ng +Ä subs istence +Ä a uctions +Ä McA uliffe +Ä L OOK +br inger +Ä tit an +Ä manif old +Ä ÃĸÄš Äą +Ä calibr ated +Ä cal iphate +Ä SH E +Ä Commission ers +ce ivable +j c +W inner +5 24 +Ä cond one +Other wise +Ä p iling +Ä em body +Ä Crime an +ut ics +Ä Ex hibition +Ä 4 26 +e ering +Ä v ying +Ä H UGE +* =- +Ä prin cipled +à ÂĻ +Ä quir ks +Ä Edit ors +put ing +G ES +Ä F TA +ठž +add on +Ä H AM +Ä Frie za +W oman +. $ +Ä c rib +Ä Her od +Ä tim ers +Ä Sp aces +Ä Mac intosh +at aka +Ä gl ide +Ä smell ing +Ä B AL +Ä un su +Ä cond os +Ä bicy cl +Ä Rev ival +55 3 +Ä jugg ling +H ug +Ä Kardash ian +Ä Balk ans +mult iple +Ä nutrit ious +oc ry +19 00 +Ä integ rates +Ä ad joining +Ä F older +roll ment +ven ient +Ä u ber +y i +Ä wh iff +Ä Ju ven +Ä B orough +net te +Ä b ilingual +Ä Sp arks +ph thal +man ufact +Ä t outing +Ä PH I +Ke efe +Rew ard +Ä inf all +Ä Tem per +typ ically +Ä Nik ol +Ä regular s +Ä pseud onym +Ä exhib itions +Ä bl aster +Ä 40 9 +w arming +Ä rever ber +Ä recip rocal +Ä 6 70 +ip ient +b ett +Ä Be gins +Ä it ching +Ä Ph ar +Ass uming +Ä em itting +Ä ML G +Ä birth place +Ä t aunt +Ä L uffy +Ä Am it +Ä cir cled +Ä N ost +enn ett +Ä de forestation +Ä Hist orically +Ä Every day +Ä overt ake +79 2 +Ä n un +Ä Luc ia +Ä accompan ies +Ä Se eking +Ä Tr ash +an ism +R ogue +Ä north western +Ä Supplement al +Ä NY U +Ä F RI +Ä Sat isf +x es +5 17 +Ä reass ured +Ä spor adic +Ä 7 01 +Ä med ial +Ä cannabin oid +Ä barbar ic +Ä ep is +Ä Explos ive +Ä D ough +Ä uns olved +Support ed +Ä acknowled gment +sp awn +Ä kit chens +Ä - = +talk ing +ic ist +Ä Peg asus +Ä PS U +Ä phot on +Ä Authent ication +R G +@# & +76 2 +Ä Cl air +Ä di aper +Ä br ist +Ä Prosecut ors +Ä J em +6 28 +Ä Every where +Ä Jean ne +equ ality +ÃŖÄĨŠ ÃŖÄĨÂŗ +object s +Ä Pel icans +Ä 39 2 +Ä bl u +b ys +Ä A go +Ä instruction al +Ä discrim inating +Ä TR AN +Ä Corn el +ag os +Ä ty re +Ä as piration +Ä Brid gewater +": - +! ". +Ä En s +Ä Coc o +P ie +Ä det ach +Ä C ouch +Ä phys ique +Ä Occup ations +osc opic +en ough +B uzz +App earance +Y P +Ä rac er +Ä compl icity +r pm +T oy +Ä interrupt s +Ä Cat alyst +Ä ut ilitarian +imp act +Ä sp aghetti +Ä p orous +Ä este emed +Ä inc iner +Ä I OC +7 48 +Ä esp resso +Ä Sm ile +abil ia +6 35 +Ä mathematic ian +Ä 4 24 +Ä K L +Ä H IP +Ä over heard +Ä T ud +Ä T ec +Ä qu izz +Ä fl attering +Ä con n +ÃĸÄĸ İ +Ä att aches +Ä R OS +Ä AC S +Ä t cp +Ä Sh ame +sk ip +res pected +Ä Trin idad +gr ain +Ä footh old +Ä Unch arted +Ä Jul io +z l +av ored +Ä An xiety +er rors +Ä Cent auri +its ch +D addy +Ä clutch ing +Ä Im plement +Ä Gut ierrez +Ä 7 60 +Ä tele portation +end ra +Ä revers ible +st ros +Ad venture +08 3 +Ä liber ating +Ä as phalt +Ä Sp end +AR DS +im sy +PR ES +Ä Emer ging +Ä wild fires +Ä techn ologically +Ä em its +Ä ART ICLE +Ä irregular ities +Ä cher ish +çÄĢ ÄĒ +Ä st ink +Ä R ost +Econom ic +Ä cough ing +Ä McC ann +pro perties +ilant ro +Ä reneg oti +Trans lation +Ä in quest +Ä Gra pe +oot ers +gu i +Ä Swords man +ace ae +h itting +Ä r c +Ä exert ed +Ä S AP +it ent +Ä peril ous +Ä obsc urity +Ä assass inate +Ä ab original +Ä resc uing +Ä Sh attered +lock ing +all ion +Ch anging +Ä Har rington +Ä B ord +Ä Afgh ans +Jam ie +aret z +Ä August us +Ä 38 6 +8 30 +Ä j og +ok ingly +Tr igger +Ä H OR +Stat istics +Ä viewers hip +Ä add itives +h ur +Ä maxim izing +Ä R ove +Ä Lou ie +Ä Buck et +Ä CHR IST +ou sel +Ä stre aks +ir ted +Ä t ert +Ä colonial ism +Ä bur ying +y k +Cond ition +Ä DPR K +By Id +75 1 +ÃĸÄš Âŧ +Ä wor risome +Ä voc ational +sl ice +Ä sa ils +Ä Correction al +95 4 +Ä t ul +K id +l uster +Ä fam ilial +Ä Sp it +Ä Ep iscopal +Specific ally +Ä Vol cano +run s +q s +Ä ve tted +Ä cram med +t rop +here r +Thank fully +Ä per cussion +Ä or anges +Ä round up +Ä 4 99 +x ious +Char acters +Ä Zion ism +Ä R ao +ÃÄŊ ÃÄŊ +W F +Ä unintention al +ONE Y +Gr ab +Com mercial +Ä glut amate +Ä McK enna +ru ciating +ning ton +ih u +Ch an +Ä Sw ap +Ä leaf lets +Ä function ally +er ous +F arm +Ä cal oric +Ä Liter ally +con cert +Ä she nan +Ä rep aid +ey es +Ä bas hing +Ä G orge +Ä collabor ations +Ä un account +itch ie +Ä team work +pp elin +Ä pip ing +Ä min ced +Ä d iam +ri eg +Ä masc ara +Ä suck er +Ä Mo ons +App s +Ä Pe ck +Ä per v +Ä Fl oat +o ley +Ä N ish +im ize +Ä arom atic +u in +end ish +! / +Ä B icycle +Ä AS IC +ile ged +Ä Quad ro +ios yn +Ä lock out +Ä W ink +SP EC +Attempt s +Ä seed ed +red o +ias is +Ä sn ag +ÃŖÄĨġ ÃŖÄ¤ÂŠ +ÃŖÄ¤ Âļ +Ä ground ing +Ä relie ver +Ä frivol ous +Ä G ifts +Ä F aces +Es pecially +Ä microbi ome +im ag +Ä Sch l +Ä P les +Ä Ble ach +Ä Ir win +Ä E aton +Ä Disc iple +Ä multipl ication +Ä coer ced +Ä 4 19 +st h +E vil +B omb +Ä ex orc +Ä stag gered +L ESS +Ä inert ia +Ä ED IT +Ä go b +Tr aditional +Ä class y +Lear y +Ä P AGE +yr s +Ä trans porter +Ä mat ured +Ä hij ab +Ä bi ome +Where as +Ä ex termination +Ä T ues +Ä T akeru +Ä Aud rey +er ial +Ä Ad en +aff les +Ä narciss istic +Ä B aird +UT F +I re +Ä Con nie +Ch amp +Ä whis pering +Ä H att +D K +Ä dis infect +Ä deduct ed +Ä part ake +Ä down grade +Ä Es ports +Ä Contin uing +Ä democr atically +icro bial +itt a +Ä lim estone +Ä exempt ed +Ä Fren zy +H erm +7 28 +Ä fled gling +Met a +765 61 +69 3 +% : +w ake +5 26 +Ä Dis cipline +Ä virgin ity +Ä Leg ions +Ä Frank ie +int ent +Ä rest rooms +Ä Rou ter +da q +Ä objection able +ÃĸĨ Äŗ +w ark +Ä Rah ul +g ain +activ ation +abs olute +Ä Access ed +Ä 24 00 +ogg les +Ä second ly +Ä DEF ENSE +Ä post age +wra pper +sh arp +7 29 +Ä commun icates +Ä add on +Ä Mil itia +H ong +Ä sl umped +Ä JP EG +Ä I car +ad ish +68 1 +Ä maj esty +Ä Wolf gang +Ä El astic +u per +Ä v iz +Ä unconscious ly +Ä ST D +Ä S ass +Ä flower ing +Ä Hel ic +Ä Dra per +Ä Am ateur +Ä man ure +Ä dis ingen +Ä Le i +br ing +9 49 +Ä inhib ited +Ä head quartered +Ä en igmatic +ïÂŋÂŊïÂŋÂŊ ïÂŋÂŊ +Ä red ress +R H +Ä ratt led +Ä d iction +l io +Ä T BA +Ä SN AP +C alling +Ä fasc ists +Ä D ove +iew icz +0 36 +Ä co asts +Ä R ect +Ä ) ] +L ot +6 29 +Ä S EM +Ä Peters en +Ä Expl ain +Ä Bo ards +Ä Be zos +Ä J ournals +Ä 20 24 +p arser +Ä mist rust +Ä gr ate +Ä L ocked +bo a +S aint +g aming +Ä vow el +in ately +bl ow +All ah +Ä un matched +Ä b ordering +Ä Exp end +n r +Or acle +rou ch +Ä cont iguous +ac us +Ä dist raught +58 1 +Ä anat omical +O X +ap ixel +8 33 +Ä PL US +Ä res usc +Ä ab iding +57 3 +Ä vac ancies +Em ily +Ä hyp othal +Ä Wer ner +Ä We e +Ä DJ s +5 13 +Ä witch craft +Ä ac upuncture +ent ary +benef it +Product s +Ä P SP +Ä MP G +Ä J inn +Ä J arrett +Ä 4 45 +Ä Im aging +Ä P yth +Fin ish +Ä te x +Ä juven iles +Ä hero ism +Ä doubt less +Ä A ki +Ä T end +Ä Patri arch +Ä bit ters +Ä Tele communications +it atively +ag na +Ä r g +Ä S OLD +Ä comp ulsion +Ä N asa +Ä Kath ryn +Ä million aires +Ä intrins ically +Ä bolst ered +time out +fl o +Ä tut or +p our +Stat ement +Ä { * +Ä Rud olph +Ä Kimber ly +rog ens +adi q +] + +Ä indign ation +Ä fract uring +Ä Re leases +Ä Gr ain +pro tein +L ago +Ä vac ations +Ä boot ed +Ä TH REE +Ä H G +oresc ence +Ä t f +Ä so ar +iosyn cr +Ä gl ances +Ä Sp oon +Ä J ury +Ä Cow boy +Ä creat ively +Hig her +Ä solic itor +Ä haw k +ac io +89 6 +Ä superf lu +Ä bombs hell +ct ure +Ä broker age +Ä raid ing +Ä f rench +Ä ang led +Trans action +Ä Gen ocide +u pe +Ä Hait ian +57 2 +! : +Ä unwitting ly +iter ator +sc roll +Ä tall ied +Ä bi omedical +Ä C ARD +Ä e uphem +Ä brain storm +a quin +K o +Mic helle +Ä R unes +Ä Ball istic +ud ers +Ä mod esty +Ä iP ads +Ä Ezek iel +Y E +Ä stars hip +Ä power fully +Ä per l +Ä Sh ade +Ä Qu art +Ä E EG +Ä fisher man +OS ED +Ä Typ ical +df x +Ä mes hes +Ä et ched +worth iness +Ä topp led +Ä 3 96 +or ius +We iss +Ä my sql +Ä Val halla +Ù Ä´ +le asing +Ä rec omp +rap nel +S el +04 3 +Ä der ailed +Ä Gu ides +IR T +Ä de human +Ä Britt any +" )) +Ä ex claim +Ä b alk +Ä 8 40 +CLA IM +int el +L AB +Ä pe gged +Ä ast roph +sm oking +Ä rig ging +Ä fix ation +Ä cat apult +ins ide +Ä C ascade +Ä Bolshe vik +G aza +Dep th +Ä loud spe +Ä almond s +me yer +l eness +j en +f resh +Ä unbeat en +Ä Squ id +Ä Pres umably +Tim er +B W +Ä ro sters +Ä ell ipt +Ä Har riet +dat abase +Ä Mut ual +Ä Comm odore +uk ed +kn ife +Ä COMM UN +h ya +Ä mel ts +arch ives +Ä rat ification +Ä multip lying +Ä inter oper +Ä asc ert +w ings +ver ting +Ä Scorp ion +ay e +Ä Ports mouth +Ä M TA +n it +iaz ep +Ä qu arantine +Ä slides how +Ä cent imeters +Ä syn opsis +Ä sp ate +th irst +Ä nom inating +Ä Mel vin +Pre view +Ä thro b +Ä gener ational +Ä Rad ius +rest ling +put able +aw ar +N ECT +Ä unlaw fully +Ä Revel ations +Wik ipedia +sur v +Ä eye ing +ij n +Ä F W +Ä br unt +Ä inter stellar +Ä cl itor +Ä Croat ian +Ä Ch ic +ev a +Ä Dis app +Ä A kin +iner ies +d ust +Interest ed +Ä gen esis +Ä E ucl +ÃÂļ n +p icking +Ä mut ated +Ä disappro ve +Ä HD L +Ä 6 25 +Ì Âļ +c ancer +Ä squ ats +Ä le vers +Disc uss += ] +D ex +Ä VIDE OS +A UD +Ä trans act +Ä Kin ect +Ä K uala +Ä C yp +7 47 +Ä sh attering +Ä arsen ic +Ä Int ake +Ä Angel o +Ä Qu it +Ä K he +Ä 18 93 +M aker +0 29 +Ä Pain ting +Dis able +9 16 +Ä anal ges +Ä tact ile +Ä prop hes +Ä d iced +Ä Travel s +Ä He ader +Ä Club s +Ass istant +Ä inc rim +Ä d ips +Ä cruc ifix +Ä Shan ahan +Ä Inter pret +Ä 40 90 +al ogy +abb a +Ä simul ac +hus band +S IM +Ä recy cle +uc er +ed ged +Ä re naissance +Ä Bomb ay +Cath olic +Ä L INE +Ä Cl othing +re ports +Ä pl aus +Ä d ag +Ä M ace +Z I +Ä intr uder +Ä Veter inary +g ru +Ä sne aky +Ä S ie +Ä C innamon +P OSE +Ä cou rier +Ä C NS +Ä emanc ipation +s it +Ä play through +Ä Fac ilities +v irt +Ä G auntlet +Thom pson +Ä unbeliev ably +Param eters +Ä st itching +ign e +Ä TH ESE +Priv acy +Ä shenan igans +Ä vit ri +Ä Val id +59 1 +Ń ¡ +Ä Prot otype +ink a +SC P +Ä T id +è ÄĒ +old ed +Ä individual ity +Ä bark ing +Ä m ars +Ä W D +Ä 8 20 +Ä t ir +Ä sl apping +Ä disgr untled +Ä Ang ola +ri us +Ä Torn ado +Ä Th urs +Ä capt cha +Ä ang st +Ä P og +Ä Assass ins +Ä Ad idas +Ä joy ful +Ä wh ining +Emer gency +Ä phosph orus +Ä att rition +oph on +Ä Timber wolves +Ä J ah +Ä Br inging +Ä W ad +Ä En sure +oh l +Ä X ie +omm el +c mp +Ä z ipper +Ä rel at +Ä Cor ridor +m ilo +T ING +Av g +Ä cro pped +] } +Ä r aged +Ä Lump ur +Ä Guer rero +our ke +N ut +Ä off sets +og lu +dr m +Ä mort als +lat able +Ä dismiss ive +ä¸ ÄĢ +Ä thro ats +Ä chips et +Ä Spot light +Catal og +art ist +G b +Ä ch illy +Ä st oked +Ä 3 74 +W ard +L atin +Ä f iasco +Ä ble ach +Ä b rav +Enh anced +Ä in oc +Ä Fior ina +_ > +Ä le ukemia +Ä el uc +Ä announ cer +Ä Lith uan +Ä Arm ageddon +ÃĨ ÄŠ +Len in +Ä R uk +Ä pe pp +Ä Rom antic +Ä P IT +Ä Inter stellar +Ä At kinson +R aid +J s +Go al +C ourse +Ä van ishing +es ley +Ä R ounds +Els a +59 3 +Ä redund ancy +Ä ST AND +Ä prop hetic +Ä habit able +ry u +Ä faint ly +M ODE +Ä fl anked +IR C +Aw esome +Ä sp urious +Ä Z ah +Ä MS G +Ä sh ading +Ä motiv ational +Ä Sant ana +Ä S PR +Ä exc ruciating +om ial +Ä M iko +Ä Le opard +A byss +Ä [ | +d irty +Ä bath s +Ä dem oral +and re +P B +Ä un ification +Ä sac rament +Ä [ & +Ä pric eless +Ä gel atin +Ä eman ating +Ä All aah +98 6 +Ä out burst +Ä er as +Ä X VI +Ä SP I +O tt +Ä Laz arus +PL IED +F lying +blog s +W isconsin +R aven +Ä reb ate +Ä creep s +Ä Sp an +Ä Pain ter +Ä Kir a +Ä Am os +Ä Cor vette +Cons umer +Ä Rec over +ck i +Ä pes ky +Ä In vention +Compan ies +Ä challeng ers +ad emic +Ä Ukrain ians +Ä Neuro log +Ä Fors aken +Ä ent rants +Ä emb attled +Ä def unct +Ä Glac ier +Ä po isons +Ä H orses +m akes +Ä D irt +Ä 4 23 +hh h +Ä Trans formation +QUI RE +................ .. +Ä trave ller +Ä Se xy +Ä K ern +ip olar +Ä ransom ware +oooooooo oooooooo +E c +rub y +Prof essional +Ä Out break +arg ument +G rey +Ä Fif a +Ä CH O +Ä FOR M +Ä Am trak +- [ +Ä cr adle +Ä antioxid ants +ÃŖÄŖÂŽÃĨ ÂŽ +7 36 +Ä NAS L +Ä Contribut ions +Ind iana +Ä ST EP +C SS +Ä sal ient +Ä all ocations +yr ights +Ä m ashed +Ä Cut ter +Sex ual +Ä p ounded +Ä fan base +Ä c asc +Ä Trans parency +Ä analy tic +Ä Summon er +× ŀ +Ä AD C +det ail +Ä van quished +Ä cr abs +ar ie +Dest roy +Ä S ack +Ä trans istor +Al abama +Ä K oen +Ä Fisher ies +c one +Ä annex ed +Ä M GM +es a +Ä f aked +Ä Cong ratulations +Ä hind ered +Ä correction al +Ä I TV +lee ve +Ä in appropriately +lic ks +Ä tresp ass +Ä p aws +Ä negoti ator +Ä Christ ensen +lim its +Ä Dian ne +Ä eleg ance +Ä Contract s +an ke +Ob j +Ä vigil ance +Ä cast les +Ä N AD +Ä Hol o +Ä emph atically +Ä Tit us +Ä Serv ing +Ä Rich ie +Ä P igs +5 68 +Ä anim osity +Ä Att ributes +Ä U riel +M Q +my ra +Ä Applic ant +Ä psychiat rists +Ä V ij +Ä Ab by +ag ree +P ush +Ä k Wh +hib a +Ä inc ite +Ä We asley +Ä Tax i +minist ic +hy per +Ä F arn +Ä 6 01 +Ä Nation wide +F ake +95 2 +Ä ma ize +Ä interact ed +Ä transition ed +Ä paras itic +Ä harm onic +Ä dec aying +Ä bas eless +ns ics +Ä trans pired +Ä abund antly +Ä Fore nsic +Ä tread mill +Ä J av +ab and +Ä ssh d +Ä front man +Ä Jak arta +oll er +dro ps +Ä SERV ICES +rompt u +oph ical +h ospital +bled on +6 45 +Ä mid range +Ä EV ENT +cul ated +raw led +Ä per ched +Ä over board +Ä Pe el +Ä P wr +Ä Car th +Ä COM PLE +co e +sh all +Ä deter rence +M ETHOD +Ä Abs ent +M EN +Ä s ill +Ä LE VEL +Y ork +Ä sin ners +Ä OP EC +Ä N ur +Ä Design s +se lection +Ä unw orthy +CH A +Ä streng thens +88 3 +ed ly +Ä slic ing +Ä mal nutrition +Ä film making +Ä Pol k +ur ated +Ä 4 21 +bre akers +!' " +Ä wet lands +Ä Disc rimination +Ä allow able +Ä ste ered +Ä Sic ily +S AM +Ä must ache +Ä m ids +Ä cl ipped +Ä circ ulate +Ä br ittle +Ä Build ings +ra ised +Ä Round up +Ä wealth ier +Ä overw rite +Ä over powered +Ä Gerr ard +s ites +PD ATED +Ä acute ly +Ä Gam ble +Ä p im +Ä K us +Typ ically +De ploy +Ä Moroc can +p otion +com be +Ä vigil ante +Ä 36 3 +St ew +Ä B agg +Ä res ided +Ä Sp o +Ä rem nant +Ä empt iness +br ainer +Ä out patient +pri ority +Ä le ptin +Ä Pay ton +Ä Gle aming +Ä S hed +Ä Pol o +Ä Mormon ism +rest ricted +arl ane +w x +Ä creat ine +Ä An on +Ä ST UD +Ä J UL +Ä T ee +5 28 +08 9 +Ä hat ched +Dis patch +Ä Compos ite +Ä 45 1 +p uff +Ä X COM +Ä Or n +Ä TH ANK +END ED +Ä Ashe ville +Ġà Ğ +Ä man go +Ä S lightly +world ly +Ä W ander +Ä Exp and +Ä Ch r +M ist +Ä orthodox y +Ä UN ESCO +reg ate +Else where +k ie +ir led +Ä topp le +Ä adopt ive +Ä Leg s +d ress +Ä S agan +b are +Ä Gl ou +Cr unch +Ä help ers +Ä chron ically +Ä H uma +1 0000 +Ä accommod ating +äÂē Äļ +Ä wrink les +Ä dod ged +four th +Ä pre con +Ä compress or +Ä K are +Ä ev ict +Ä War wick +im ar +Ä modern ization +Ä band wagon +Ä ref uted +Ä net ted +Ä Na ples +Ä Gen ie +per ors +Ä field ed +Ä de re +Ä Par ables +le es +Ä tr out +asp ers +Ä n ihil +Ä happ iest +Ä flo ppy +Ä Lo ft +Ä He ard +Ä un ison +Ä l ug +Ä Red mond +class ic +Supp orters +SH IP +G MT +Ä fue lled +ç IJ +Ä d d +Ä Emin em +Ä 18 97 +NY SE +Ä secret aries +Ä F IA +Ä Canaver al +F avorite +Ä p omp +Ä detain ee +ers hip +aim on +i our +Ä A pex +Ä plant ations +am ia +ac ion +R ust +Ä tow ed +Ä Tru ly +5 77 +Ä shel tered +r ider +W o +Ä l air +Ä Int elligent +impro ve +m atically +Ä et iquette +ad ra +all o +Ä Jun o +any thing +Ä Stru ggle +Ä Pred ict +Ä Gr imes +Ä AMER ICA +ct x +Ä Sit uation +W OOD +Ä sol uble +me ier +Ä intoler able +ang ering +Ä un interrupted +Ä tool tip +Ä interrog ated +Ä gun ned +Ä Sne ak +ÃĻŃ ÂĻ +Ä t ether +Ä cr umble +L ens +Ä clust ered +Ä Sy l +Ä Has an +Ä dystop ian +w ana +Ä joy stick +Ä Th ib +amm u +Tom orrow +5 46 +Ä overc ame +Ä minim ized +cept or +Run ner +ENG TH +Ä Brend a +Ä Achieve ments +Ä tor ches +Ä rapp ort +Ä Investig ator +Ä Hand ling +rel ation +g rey +8 15 +Ä k cal +Ä Comm ands +d q +Ä cur ls +Ä be arer +Ä cyn icism +it ri +Ä Use ful +B ee +D CS +Ä ab ras +P ract +BIL ITIES +7 12 +Ä debug ger +Ä debt or +Ä L ia +Ä K ers +Ä exacerb ate +Ä St acy +Ä B land +Ä Sc enes +Ä branch ing +ÃĸĸÄĒÃĸĸÄĒÃĸĸÄĒÃĸĸÄĒ ÃĸĸÄĒÃĸĸÄĒÃĸĸÄĒÃĸĸÄĒ +ape ake +Ä s alsa +Ä mish and +Ä Kon ami +Ä N ib +Ä anecd ote +Ä agree able +Ï ÄĢ +Ä Nath aniel +Ä He isman +Ä B eware +Ä 18 86 +spect ive +69 1 +5 22 +Ä inhib its +Ä has hing +Ä 18 89 +ÃĨ° Ĩ +v ich +P ure +Ä solid ly +Ä aspir in +im aru +Ä street car +Ä U CS +Ä J udd +Ä flash backs +p ins +Ä 14 40 +Ä UN HCR +Ä Sym ptoms +T IT +5 38 +F ra +% ); +Ä o oz +Ä cur few +Ä cal med +Ä particip ates +Te X +Ä nons ensical +Ä full back +Ä De L +mon key +h ari +Ä metabol ites +Ä loot ed +Ä AL WAYS +Ä B CC +L t +oc het +B one +Ä veto ed +Ä g cc +Ä CL ICK +Ä 18 88 +s af +Ä stiff ness +Ä low ly +Ä Ge h +vers on +ors et +Ä un foreseen +Ä an esthesia +Ä Opt ical +Ä recon structed +Ä T up +sh ows +NEW S +Ä Newsp aper +Ä A SA +ter a +N umbers +Ä inexpl icable +× Äŗ +Ä hard ness +unt arily +Ä A cer +grad ient +ARD IS +Ä wood land +Ä metaph ors +Ä Wem bley +Ä Pa vel +phil is +Ä re writing +Ä percept ual +Ä 10 70 +worm s +Ä Down s +Ä unsur prisingly +Ä tag ging +fl ame +Ä lit res +Ä boun ces +Ä B abe +sh ut +Ä overd oses +Ä She ila +Ä Ch au +Ä Bl ess +Capt ure +Ä Sign ificant +Ä Sc ion +Ä 38 9 +Ä Mc H +Ä Titan ium +Ä Me al +amed a +ag ents +agg ressive +B illy +76 3 +Ä S aying +DER R +it one +Coll ins +B ound +Ä bol ted +Ä DM CA +95 3 +Ä un iqueness +Ä ep igen +un ci +ant am +Ä reck oning +ch airs +OG R +Ä Sen egal +Ä 18 62 +re levant +Ġ ¯ +Ä pharm acies +Ä G eral +v ier +Y an +OR PG +Ä rab id +b ending +Ä UN ITED +Ä 4 65 +As sembly +Ä we ep +Ä be hest +Ä Mother s +Ä J ace +h id +Ä wh irlwind +Ä UN IVERS +Ä ut opian +Ä kidn ap +Ph ilipp +K in +89 3 +Ä livest ream +Ä M ISS +Ä sub versive +Ä Techn iques +Ä JUST ICE +Ä B ASE +Ä 38 7 +Ä assail ants +Ä Hard core +Ä sprink led +Ä P se +Ê Äŧ +print ed +Ä H au +OR GE +Ä T OUR +Ä l aced +Ä it ch +G iving +Ä port ed +78 1 +//////////////// //////////////// +bre eding +Ä log ger +Ä H OL +inn ie +First ly +Ä embry onic +Ä deleg ated +p ai +O IL +Ä centr ally +Ä R x +Ä Sc outing +D utch +Ä he reditary +Ä Cru iser +s at +5 29 +Ä Mar riott +other mal +Ä prohib itions +E arn +Ä St ab +Ä Colleg es +Ä Bel ief +st retched +Ä L H +Ä Entity Item +C IA +Ä un rem +Ä laure ate +Ä denomin ations +sum mary +h ler +S pect +Ä K laus +Ä Be ans +Ä ins ur +Ä PA X +Ä field er +Ä V et +Ä Sp arrow +z ie +Ä S Q +Ä Mond ays +Ä Off line +Ä Ler ner +Ä Ext ensions +Ire land +Ä patron age +Ä contrast ed +Ä Man ia +h irt +Mos cow +Ä condem ns +Ä An ge +Ä comp osing +Ä Pe pe +Ä P addock +Ä heter ogeneity +Ä ide ologically +Ä f ishes +Ä cur sing +Ä R utherford +Ä Flo ating +Ä Am elia +Te a +Syn opsis +Ä stun ts +Ä be ad +Ä stock ing +Ä M ILL +ob ook +mass ive +\ < +Ä h ump +Ä Pref erences +Engine Debug +ge ist +Ä Niet o +ome ver +ish y +eval uate +col onial +Altern ative +Ä Go Pro +Ä V ortex +Ä NET WORK +ans ky +Sec ure +Ä Th rust +Sn ake +Ä parcel s +Ä sam urai +Ä actress es +N ap +M F +ifer ation +Be er +5 23 +Ä I ly +oint ment +P ing +Ä stri ped +Ä Mell on +oss ession +Ä neut ron +end ium +Ä a ph +Ä Flav oring +Ä 38 3 +Ä respons iveness +Ä J indal +Ä Hitch cock +Den ver +Ä DRAG ON +sm anship +Ä Du pl +Ä s ly +Ä web cam +Ä Tw ain +Ä Dar ling +ili ate +cons umer +D IT +Ä names ake +Ä un orthodox +Ä fun er +Ä PL oS +Ä CONTR OL +ozy g +ogl obin +F ACE +ER G +Ä D ia +Ä F iesta +ce le +0 34 +Ä encl ave +ÃĸĸÂŦ ÃĸĸÂŦ +on ement +al ist +M and +Ä home grown +Ä F ancy +Ä concept ions +Ä Cont ains +ure en +Ä reiter ate +Ä me ager +Ä install ments +Sp awn +6 27 +Ä phot oc +Ä Cab rera +Ä Ros enthal +Ä Lans ing +is ner +Ä invest s +Ä UFO s +EX P +Hard ware +Ä tr agically +Ä conced es +ie ft +ch am +bor gh +Ä Sch r +Ä Mel anie +Ä H oy +Ä visit ation +Ä id iosyncr +Ä fract ions +Ä fore skin +ob os +Ä po aching +Ä VI EW +Ä stimul ates +Ä G ork +can on +M IC +Ä Nem esis +Ä Ind ra +Ä DM V +Ä 5 29 +Ä inspect ing +Ä grand ma +Ä W hedon +Ä Sh ant +Ä P urg +ik an +Ä T eg +Ä CL R +z ac +Vict oria +Ä Ver ify +ion ics +Ä part ying +Ä M ou +col our +Ä testim onies +l ations +Ä press uring +hi ro +ac ers +Ä f id +ang ler +Ä CS I +Ä here after +Ä diss idents +report ing +iph any +che v +Ä sol itude +Ä l obe +Ä ind is +Ä cred ential +re cent +ad ult +Ä Nir vana +Ä Franch ise +L ayer +H yp +Ä Berks hire +Ä will s +t if +Ä tot em +Ä Jud ah +rep air +Inst ant +5 48 +Ä emb assies +Ä bott leneck +Ä b ount +Ä typ ew +Ä Al vin +j ing +im ilar +R ush +Ä br im +Ä HEL P +A im +] ' +Ä pass ively +Ä bound ed +Ä R ated +Ä criminal ity +Ä biom ark +Ä disp atcher +Ä Tow ards +Ä + ++ +right eous +f rog +Ä P anc +C arter +0 32 +ÃĻŠ Ł +Ä ult raviolet +Ä Lic ensed +Ä T ata +Ä Bl essing +Ä G AM +Ä chem ically +Ä Se af +Ä RE LE +Ä Merc enary +capital ist +Ä form ulations +Ä ann ihilation +Ä Ver b +Ä Ar gon +Ä un loaded +Ä morp hed +Ä conqu ering +back er +I ELD +Ä theft s +Ä front runner +Ä Roy ale +Ä Fund amental +el ight +C hip +necess ary +ay n +Ä Sl ip +Ä 4 48 +cern ed +P ause +Ä shock ingly +Ä AB V +Ä comp osure +7 33 +Ä Motors port +ah ime +Mur ray +M ach +Ä gr ids +Ä deb ian +Ä further more +Ä dexter ity +Ä Collect ions +os lov +il age +b j +Ä Mont eneg +Ä strut Connector +Ä massac res +Ä brief s +fet ched +uv ian +ol ition +Fail ure +emon ic +Ä fl ared +Ä claim ant +Ä c ures +Ä give aways +Ä Subst ance +al ions +Ä cr inge +Ä K ul +Ä arist ocracy +Ä Ul ster +ol ated +h ousing +Ä M IS +Ä gl ared +Ä Wil helm +ne eds +lam bda +build ers +Ä V IS +Ä radi ator +Ä Ghost busters +Ä 4 36 +act ual +Ä her ds +ç a +watch ing +Ä counter ing +Ch arge +Ä char red +Ä war heads +Ä iod ine +Ä M acy +04 1 +Ä depart ures +Ä S ins +Ä dy ed +Ä Concept s +g ado +7 13 +Ä quot ations +Ä g ist +Ä Christ y +Ä ant igen +Ä Hem p +Ä D rawn +Ä B arg +ez vous +Ä p aternity +Ä ar du +Ä Anch orage +Ä R ik +Ä over loaded +Ä Us ername +Ä Tam my +Ä N au +Ä Cell ular +Ä w aning +Ä rod ent +Ä Wor cester +il ts +Ä T ad +Ä dwell ings +Ä bull ish +4 31 +Ä retali ate +Ä mig raine +Ä Chev ron +CH ECK +Ä don key +c rim +SP A +Ä An alog +Ä marqu ee +Ä Ha as +B ir +Ä GD DR +Ä Download s +Ä will power +Ä For th +Ä Record ed +Ä imp ossibility +Ä Log ged +Ä Fr anks +Ä R att +in itions +Ä clean ers +Ä sore ly +Ä flick ering +Ä Ex amination +c atching +allow een +Ms g +Ä dun no +F a +Ä dys ph +c razy +.' '. +Ä main line +Ä c s +Ä p tr +Ä W ally +ig un +95 1 +Ä Big foot +f ights +Ä retrie ving +J r +Ä dupl ication +Ä Expl an +Ä rel ational +Ä qu aint +Ä bisc uits +Ä ad o +Ä sh udder +Ä antid ote +blood ed +ks h +Ä sa uces +Ä rein vest +Ä dispens ary +Ä D iver +Ä 9 000 +stud ent +Ä in separ +esc ap +Ä todd lers +Ä GP IO +Ä Ass ignment +head ers +Ä lack luster +Ä ab ack +95 6 +Ä tool bar +7 45 +Ä o ust +Ä contempl ation +Ä PRES IDENT +Ä 4 58 +==== == +Ä guarantee ing +Ä He ist +Ä Cann es +Äģ ÂŊ +Ä collabor ator +Ä Am p +Ä g ou +Ä SH ALL +st ories +78 3 +Ä mobil ized +Ä bro od +Ä L U +ĠðŁ Äŗ +Ä ref in +Ä Anthrop ology +v ind +ill i +Ä warrant ies +Ä B abel +Ä sw ath +Ä c aches +Ä antagon ists +art ifacts +Ä hot ly +Ä St arts +Ä G ÃÂļ +z ag +!! !!! +Ä sc ourge +Ä cons piring +ru its +re verse +Ä She en +Ä Jes uit +Ä Giov anni +ad ies +Ä butt ocks +ear cher +ac an +Ä volley ball +Ä shroud ed +Ä score board +b ats +Ä I PM +Ä ass es +Ä de regulation +Ä Te legram +Ä Reb oot +Ä 7 000 +Ä Can ary +Ä k ernels +Ä Franç ois +Ä D uff +Ä P on +Ä Le ica +Ä Gar min +Ä or phans +Ä Claud ia +Ä cal endars +Ä Le ilan +ent o +R ocket +Ä br unch +Ä Haw king +ain ers +Ä sens ibilities +Ä k W +Ä K and +Ä re claimed +Ä interesting ly +× Š +rom y +J M +Ä Enhance ment +b ush +Sk ip +Ä rapp ers +Ä g azing +p edia +ath lon +Rev olution +Ä sn ipers +Ä re verted +Ä conglomer ate +T erry +79 4 +Ä hars her +Ä des olate +Ä Hit man +Comm ission +Ä ( / +ÃĸÄĸÂĻ ." +Com par +Ä ampl ification +om inated +Ä reg ress +Ä Coll ider +Ä inform ants +Ä g azed diff --git a/java/extensions/semantickernel-gpt3-tokenizer/src/test/java/com/microsoft/semantickernel/GPT3TokenizerTest.java b/java/extensions/semantickernel-gpt3-tokenizer/src/test/java/com/microsoft/semantickernel/GPT3TokenizerTest.java new file mode 100644 index 0000000000..f4cfd25c17 --- /dev/null +++ b/java/extensions/semantickernel-gpt3-tokenizer/src/test/java/com/microsoft/semantickernel/GPT3TokenizerTest.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class GPT3TokenizerTest { + + @Test + public void tokenizerTest() { + String sentence = "Some text on one line"; + int tokenCount = GPT3Tokenizer.encode(sentence).size(); + Assertions.assertEquals(5, tokenCount); + + sentence = "Some text on\r\ntwo lines"; + tokenCount = GPT3Tokenizer.encode(sentence).size(); + Assertions.assertEquals(7, tokenCount); + + // Sample from: https://platform.openai.com/tokenizer + sentence = + "Many words map to one token, but some don't: indivisible.\n" + + "\n" + + "Unicode characters like emojis may be split into many tokens containing the" + + " underlying bytes: \uD83E\uDD1A\uD83C\uDFFE\n" + + "\n" + + "Sequences of characters commonly found next to each other may be grouped" + + " together: 1234567890"; + tokenCount = GPT3Tokenizer.encode(sentence).size(); + Assertions.assertEquals(64, tokenCount); + } +} diff --git a/java/extensions/semantickernel-planners/pom.xml b/java/extensions/semantickernel-planners/pom.xml new file mode 100644 index 0000000000..b4b2d8c220 --- /dev/null +++ b/java/extensions/semantickernel-planners/pom.xml @@ -0,0 +1,39 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-planners + Semantic Kernel Planners Extension + Planner implementation for Semantic Kernel + + + + com.microsoft.semantic-kernel + semantickernel-api + + + com.fasterxml.jackson.core + jackson-databind + compile + + + com.fasterxml.jackson.core + jackson-core + compile + + + org.junit.jupiter + junit-jupiter-api + test + + + + diff --git a/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanResponse.java b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanResponse.java new file mode 100644 index 0000000000..31c88c702b --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanResponse.java @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.actionplanner; + +/// +/// Plan data structure returned by the basic planner semantic function +/// +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; + +public class ActionPlanResponse { + + public static class PlanData { + /// + /// Rationale given by the LLM for choosing the function + /// + public final String rationale; + + /// + /// Name of the function chosen + /// + public final String function; + + /// + /// Parameter values + /// + public final Map parameters; + + @JsonCreator + public PlanData( + @JsonProperty("plan") String rationale, + @JsonProperty("function") String function, + @JsonProperty("parameters") Map parameters) { + this.rationale = rationale; + this.function = function; + this.parameters = parameters; + } + } + + public final PlanData plan; + + @JsonCreator + public ActionPlanResponse(@JsonProperty("plan") PlanData plan) { + this.plan = plan; + } +} diff --git a/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanner.java b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanner.java new file mode 100644 index 0000000000..d181050aa2 --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlanner.java @@ -0,0 +1,358 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.actionplanner; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.orchestration.WritableContextVariables; +import com.microsoft.semantickernel.planner.PlanningException; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +/// +/// Action Planner allows to select one function out of many, to achieve a given goal. +/// The planner implement the Intent Detection pattern, uses the functions registered +/// in the kernel to see if there's a relevant one, providing instructions to call the +/// function and the rationale used to select it. The planner can also return +/// "no function" is nothing relevant is available. +/// The rationale is currently available only in the prompt, we might include it in +/// the Plan object in future. +/// +public class ActionPlanner { + private static final Logger LOGGER = LoggerFactory.getLogger(ActionPlanner.class); + + // Extracts the json portion of a plan between the braces, stripping off any non-json content + private static final Pattern CLEAN_PLAN = + Pattern.compile("[^{]*(\\{.*})[^}]*", Pattern.MULTILINE | Pattern.DOTALL); + private static final String StopSequence = "#END-OF-PLAN"; + private static final String SkillName = "this"; + + // Planner semantic function + private final CompletionSKFunction plannerFunction; + + // Context used to access the list of functions in the kernel + private SKContext context; + private Kernel kernel; + + // TODO: allow to inject skill store + + /** + * Initialize a new instance of the ActionPlanner class + * + * @param kernel The semantic kernel instance + * @param prompt prompt override + */ + public ActionPlanner(Kernel kernel, @Nullable String prompt) { + // Verify.NotNull(kernel); + String promptTemplate; + if (prompt == null) { + promptTemplate = read("skprompt.txt"); + } else { + promptTemplate = prompt; + } + + this.plannerFunction = + SKBuilders.completionFunctions() + .withKernel(kernel) + .withPromptTemplate(promptTemplate) + .withSkillName(SkillName) + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0.0, 0.0, 0.0, 0.0, 1024)) + .build(); + + kernel.importSkill(this, SkillName); + + this.kernel = kernel; + this.context = SKBuilders.context().withSkills(kernel.getSkills()).build(); + } + + public static String read(String file) { + try (InputStream stream = ActionPlanner.class.getResourceAsStream(file)) { + byte[] buffer = new byte[stream.available()]; + stream.read(buffer); + return new String(buffer, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public Mono createPlanAsync(String goal) { + if (goal == null || goal.isEmpty()) { + throw new PlanningException( + PlanningException.ErrorCodes.INVALID_GOAL, "The goal specified is empty"); + } + + context = this.context.update(goal); + + return this.plannerFunction + .invokeAsync(this.context, new CompletionRequestSettings(0, 0, 0, 0, 2048)) + .handle( + (result, sink) -> { + try { + sink.next(parsePlan(goal, result)); + } catch (Exception e) { + sink.error(e); + } + }); + } + + private Plan parsePlan(String goal, SKContext result) { + ActionPlanResponse planData; + // Clean up the plan, removing any prompt and the stop sequence + Matcher matcher = CLEAN_PLAN.matcher(result.getResult()); + + String plan = result.getResult(); + if (matcher.matches()) { + plan = matcher.group(1); + } + + try { + planData = new ObjectMapper().readValue(plan, ActionPlanResponse.class); + } catch (Exception e) { + throw new PlanningException( + PlanningException.ErrorCodes.INVALID_PLAN, + "Plan parsing error, invalid JSON", + e); + } + + if (planData == null) { + throw new PlanningException( + PlanningException.ErrorCodes.INVALID_PLAN, + "The plan deserialized to a null object"); + } + + SKFunction function = getPlanFunction(planData); + + WritableContextVariables variables = SKBuilders.variables().build().writableClone(); + + planData.plan + .parameters + .entrySet() + .forEach( + entry -> { + variables.setVariable(entry.getKey(), entry.getValue()); + }); + + if (function == null) { + // No function was found - return a plan with no steps. + return new Plan(goal, variables, () -> kernel.getSkills()); + } else { + return new Plan(goal, variables, () -> kernel.getSkills(), function); + } + } + + public SKFunction getPlanFunction(ActionPlanResponse planData) { + + if (planData.plan.function.contains(".")) { + String[] parts = planData.plan.function.split("\\.", -1); + SKFunction function = + context.getSkills().getFunction(parts[0], parts[1], SKFunction.class); + + if (function == null) { + throw new PlanningException( + PlanningException.ErrorCodes.INVALID_PLAN, + "Unknown function " + planData.plan.function); + } + return function; + + } else if (!planData.plan.function.isEmpty()) { + CompletionSKFunction function = + context.getSkills() + .getFunction(planData.plan.function, CompletionSKFunction.class); + + if (function == null) { + throw new PlanningException( + PlanningException.ErrorCodes.INVALID_PLAN, + "Unknown skill " + planData.plan.function); + } + + return function; + } + return null; + } + + // TODO: use goal to find relevant functions in a skill store + /// + /// Native function returning a list of all the functions in the current context, + /// excluding functions in the planner itself. + /// + /// Currently unused. Will be used to handle long lists of functions. + /// Function execution context + /// List of functions, formatted accordingly to the prompt + + @DefineSKFunction( + name = "listOfFunctions", + description = "List all functions available in the kernel") + @Nullable + public String listOfFunctions( + @SKFunctionParameters( + name = "goal", + description = "The current goal processed by the planner", + defaultValue = "") + String goal, + SKContext context) { + // Verify.NotNull(context.Skills); + ReadOnlySkillCollection skills = context.getSkills(); + + return this.populateList(skills); + } + + // TODO: generate string programmatically + // TODO: use goal to find relevant examples + @DefineSKFunction( + name = "GoodExamples", + description = "List a few good examples of plans to generate") + public String goodExamples( + @SKFunctionParameters( + name = "goal", + description = "The current goal processed by the planner", + defaultValue = "") + String goal, + SKContext context) { + + return "\n" + + "[EXAMPLE]\n" + + "- List of functions:\n" + + "// Read a file.\n" + + "FileIOSkill.ReadAsync\n" + + "Parameter \"path\": Source file.\n" + + "// Write a file.\n" + + "FileIOSkill.WriteAsync\n" + + "Parameter \"path\": Destination file. (default value: sample.txt)\n" + + "Parameter \"content\": File content.\n" + + "// Get the current time.\n" + + "TimeSkill.Time\n" + + "No parameters.\n" + + "// Makes a POST request to a uri.\n" + + "HttpSkill.PostAsync\n" + + "Parameter \"body\": The body of the request.\n" + + "- End list of functions.\n" + + "Goal: create a file called \"something.txt\".\n" + + "{\"plan\":{\n" + + "\"rationale\": \"the list contains a function that allows to create files\",\n" + + "\"function\": \"FileIOSkill.WriteAsync\",\n" + + "\"parameters\": {\n" + + "\"path\": \"something.txt\",\n" + + "\"content\": null\n" + + "}}}\n" + + "#END-OF-PLAN\n"; + } + + @DefineSKFunction( + name = "EdgeCaseExamples", + description = "List a few edge case examples of plans to handle") + public String edgeCaseExamples( + @SKFunctionParameters( + name = "goal", + description = "The current goal processed by the planner", + defaultValue = "") + String goal, + SKContext context) { + return "\n" + + "[EXAMPLE]\n" + + "- List of functions:\n" + + "// Get the current time.\n" + + "TimeSkill.Time\n" + + "No parameters.\n" + + "// Write a file.\n" + + "FileIOSkill.WriteAsync\n" + + "Parameter \"path\": Destination file. (default value: sample.txt)\n" + + "Parameter \"content\": File content.\n" + + "// Makes a POST request to a uri.\n" + + "HttpSkill.PostAsync\n" + + "Parameter \"body\": The body of the request.\n" + + "// Read a file.\n" + + "FileIOSkill.ReadAsync\n" + + "Parameter \"path\": Source file.\n" + + "- End list of functions.\n" + + "Goal: tell me a joke.\n" + + "{\"plan\":{\n" + + "\"rationale\": \"the list does not contain functions to tell jokes or" + + " something funny\",\n" + + "\"function\": \"\",\n" + + "\"parameters\": {\n" + + "}}}\n" + + "#END-OF-PLAN\n"; + } + + private String populateList(ReadOnlySkillCollection skills) { + return skills.getAllFunctions().getAll().stream() + .filter(skill -> !SkillName.equalsIgnoreCase(skill.getSkillName())) + .map( + func -> { + StringBuilder result = new StringBuilder(); + // Function description + if (func.getDescription() != null) { + result.append("// " + addPeriod(func.getDescription()) + "\n"); + } else { + LOGGER.warn( + "{0}.{1} is missing a description", + func.getSkillName(), func.getName()); + result.append( + "// Function " + + func.getSkillName() + + "." + + func.getName() + + ".\n"); + } + + // Function name + result.append(func.getSkillName() + "." + func.getName() + "\n"); + + func.describe() + .getParameters() + .forEach( + parameter -> { + String description; + if (parameter.getDescription() == null + || parameter.getDefaultValue().isEmpty()) { + description = parameter.getName(); + } else { + description = parameter.getDescription(); + } + + String defaultValueString; + if (parameter.getDefaultValue() == null + || parameter.getDefaultValue().isEmpty()) { + defaultValueString = ""; + } else { + defaultValueString = + " (default value: " + + parameter.getDefaultValue() + + ")"; + } + + result.append( + "Parameter \"" + + parameter.getName() + + "\": " + + addPeriod(description) + + " " + + defaultValueString + + "\n"); + }); + + return result.toString(); + }) + .reduce("", (a, b) -> a + b, (a, b) -> a + b); + } + + private static String addPeriod(String x) { + return x.endsWith(".") ? x : x + "."; + } +} diff --git a/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/Plan.java b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/Plan.java new file mode 100644 index 0000000000..71317665e4 --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/actionplanner/Plan.java @@ -0,0 +1,559 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.actionplanner; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.Verify; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.orchestration.AbstractSkFunction; +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.orchestration.WritableContextVariables; +import com.microsoft.semantickernel.planner.PlanningException; +import com.microsoft.semantickernel.planner.PlanningException.ErrorCodes; +import com.microsoft.semantickernel.skilldefinition.FunctionView; +import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier; +import com.microsoft.semantickernel.skilldefinition.ParameterView; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** Standard Semantic Kernel callable plan. Plan is used to create trees of SKFunctions. */ +public class Plan extends AbstractSkFunction { + + private static final Pattern s_variablesRegex = Pattern.compile("\\$(\\w+)", Pattern.MULTILINE); + + private static final String DefaultResultKey = "PLAN.RESULT"; + + // State of the plan + private ContextVariables state; + + // Steps of the plan + private final List steps = new ArrayList<>(); + + // Parameters for the plan, used to pass information to the next step + @Nullable private ContextVariables parameters; + + // Outputs for the plan, used to pass information to the caller + private List outputs = new ArrayList<>(); + + @Nullable private SKFunction function = null; + + public Plan( + String goal, + ContextVariables state, + @Nullable KernelSkillsSupplier kernelSkillsSupplier) { + super( + new ArrayList<>(), + Plan.class.getName(), + "", + goal, + Collections.emptyList(), + kernelSkillsSupplier); + this.state = state; + } + + public Plan(String goal, @Nullable KernelSkillsSupplier kernelSkillsSupplier) { + this(goal, SKBuilders.variables().build(), kernelSkillsSupplier); + } + + public Plan( + SKFunction function, + ContextVariables state, + List functionOutputs, + KernelSkillsSupplier kernelSkillsSupplier) { + super( + function.describe().getParameters(), + function.getSkillName(), + function.getName(), + function.getDescription(), + formReturnParameters(functionOutputs), + kernelSkillsSupplier); + + this.parameters = null; + this.function = function; + this.outputs = new ArrayList<>(functionOutputs); + this.state = state; + } + + public Plan( + SKFunction function, + @Nullable ContextVariables parameters, + ContextVariables state, + List functionOutputs, + KernelSkillsSupplier kernelSkillsSupplier) { + super( + function.describe().getParameters(), + function.getSkillName(), + function.getName(), + function.getDescription(), + formReturnParameters(functionOutputs), + kernelSkillsSupplier); + this.parameters = parameters; + this.function = function; + this.outputs = new ArrayList<>(functionOutputs); + this.state = state; + } + + private static List formReturnParameters(List functionOutputs) { + return functionOutputs.stream().map(ParameterView::new).collect(Collectors.toList()); + } + + public Plan( + SKFunction function, + List functionOutputs, + KernelSkillsSupplier kernelSkillsSupplier) { + this(function, SKBuilders.variables().build(), functionOutputs, kernelSkillsSupplier); + } + + public Plan(SKFunction function, KernelSkillsSupplier kernelSkillsSupplier) { + this(function, SKBuilders.variables().build(), new ArrayList<>(), kernelSkillsSupplier); + } + + public Plan( + String goal, + ContextVariables parameters, + KernelSkillsSupplier kernelSkillsSupplier, + SKFunction... steps) { + this(goal, parameters, kernelSkillsSupplier); + this.addSteps(steps); + } + + public Plan(String goal, KernelSkillsSupplier kernelSkillsSupplier, SKFunction... steps) { + this(goal, kernelSkillsSupplier); + this.addSteps(steps); + } + + @Override + public void registerOnKernel(Kernel kernel) { + kernel.registerSemanticFunction(this); + } + + @Override + @Nullable + public FunctionView describe() { + if (function == null) { + return null; + } + return function.describe(); + } + + @Override + @Nullable + public Class getType() { + if (function == null) { + return null; + } + return function.getType(); + } + + /** + * Adds one or more existing plans to the end of the current plan as steps. When you add a plan + * as a step to the current plan, the steps of the added plan are executed after the steps of + * the current plan have completed. + * + * @param steps The plans to add as steps to the current plan. + */ + public void addSteps(Plan... steps) { + this.steps.addAll(Arrays.asList(steps)); + } + + /** + * Adds one or more new steps to the end of the current plan. When you add a new step to the + * current plan, it is executed after the previous step in the plan has completed. Each step can + * be a function call or another plan. + * + * @param steps The steps to add to the current plan. + */ + public void addSteps(SKFunction... steps) { + List plans = + Arrays.stream(steps) + .map(step -> new Plan(step, getSkillsSupplier())) + .collect(Collectors.toList()); + this.steps.addAll(plans); + } + + public void setParameters(ContextVariables functionVariables) { + this.parameters = functionVariables; + } + + public void addOutputs(List outputs) { + this.outputs.addAll(outputs); + } + + /** + * Invoke the next step of the plan + * + * @param context Context to use + * @param settings Settings to use + * @return The updated plan + */ + public Mono invokeNextStepAsync( + SKContext context, @Nullable CompletionRequestSettings settings) { + + // Execute the step + SKContext initialContext = + SKBuilders.context() + .withVariables(context.getVariables().writableClone()) + .withMemory(context.getSemanticMemory()) + .withSkills(context.getSkills()) + .build(); + + return Flux.fromIterable(this.steps) + .reduce( + Mono.just(initialContext), + (currentContext, step) -> + executeStep(context, settings, currentContext, step)) + .flux() + .concatMap(it -> it) + .last(SKBuilders.context().build()) + .map( + result -> { + if (result.getVariables().get(DefaultResultKey) != null) { + result = result.update(result.getVariables().get(DefaultResultKey)); + } + return result; + }); + } + + private Mono executeStep( + SKContext context, + @Nullable CompletionRequestSettings settings, + Mono currentContext2, + Plan step) { + return currentContext2.flatMap( + currentContext -> { + // Merge the state with the current context variables for step execution + ContextVariables functionVariables = + this.getNextStepVariables(currentContext.getVariables(), step); + + // Execute the step + SKContext functionContext = + SKBuilders.context() + .withVariables(functionVariables) + .withMemory(context.getSemanticMemory()) + .withSkills(context.getSkills()) + .build(); + + return step.invokeAsync(functionContext, settings) + .flatMap( + result -> + processInvocationResult( + context, step, currentContext, result)) + .switchIfEmpty( + processInvocationResult( + context, + step, + currentContext, + functionContext.copy().update(""))); + }); + } + + private static Mono processInvocationResult( + SKContext context, Plan step, SKContext currentContext, SKContext result) { + String resultValue = result.getResult(); + + if (resultValue == null) { + return Mono.error( + new PlanningException(ErrorCodes.UNKNOWN_ERROR, "No result returned")); + } + + resultValue = resultValue.trim(); + + WritableContextVariables updatedContext = currentContext.getVariables().writableClone(); + + String finalResultValue = resultValue; + + step.outputs.forEach( + item -> { + if (result.getVariables().asMap().containsKey(item)) { + String variable = result.getVariables().get(item); + if (variable != null) { + updatedContext.setVariable(item, variable); + } + } else { + updatedContext.setVariable(item, finalResultValue); + } + }); + + // If this function produces an output, don't overwrite the + // current + // result + if (step.outputs.size() > 0) { + updatedContext.setVariable(ContextVariables.MAIN_KEY, currentContext.getResult()); + } else { + updatedContext.update(finalResultValue); + } + + updatedContext.setVariable(DefaultResultKey, finalResultValue); + + return Mono.just(SKBuilders.context().clone(context).withVariables(updatedContext).build()); + } + + public Mono invokeAsync( + @Nullable String input, + @Nullable CompletionRequestSettings settings, + @Nullable SemanticTextMemory memory) { + + WritableContextVariables variables = state.writableClone(); + + if (input != null) { + variables.update(input); + } + + KernelSkillsSupplier skillsSupplier = getSkillsSupplier(); + + SKContext context = + SKBuilders.context() + .withVariables(variables) + .withMemory(memory) + .withSkills(skillsSupplier == null ? null : skillsSupplier.get()) + .build(); + + return this.invokeAsync(context, settings); + } + + @Override + public Mono invokeAsync( + @Nullable String input, + @Nullable SKContext context, + @Nullable CompletionRequestSettings settings) { + if (input != null) { + this.state = state.writableClone().update(input); + } + + if (context == null) { + context = + SKBuilders.context() + .withVariables(state) + .withSkills( + getSkillsSupplier() == null ? null : getSkillsSupplier().get()) + .build(); + } else { + ContextVariables variables = context.getVariables().writableClone().update(state, true); + context = context.update(variables); + } + + return super.invokeAsync(input, context, settings); + } + + @Override + protected Mono invokeAsyncInternal( + SKContext contextIn, @Nullable CompletionRequestSettings settings) { + if (function != null) { + return ((SKFunction) function).invokeAsync(contextIn, settings); + } else { + // loop through steps and execute until completion + SKContext c = addVariablesToContext(this.state, contextIn); + return this.invokeNextStepAsync(c, null); + } + } + + /** + * Expand variables in the input string. + * + * @param variables Variables to use for expansion. + * @param input Input string to expand. + * @return Expanded string. + */ + private String expandFromVariables(ContextVariables variables, String input) { + String result = input; + Matcher matches = s_variablesRegex.matcher(input); + while (matches.find()) { + + String varName = matches.group(1); + + String value = variables.get(varName); + + if (value == null) { + value = state.get(varName); + } + + if (value == null) { + value = ""; + } + + result = result.replaceAll("\\$" + varName, value); + } + + return result; + } + + /** Add any missing variables from a plan state variables to the context. */ + private static SKContext addVariablesToContext(ContextVariables vars, SKContext context) { + WritableContextVariables clone = context.getVariables().writableClone(); + vars.asMap() + .forEach( + (key, value) -> { + if (Verify.isNullOrEmpty(clone.get(key))) { + clone.setVariable(key, value); + } + }); + + return SKBuilders.context().clone(context).withVariables(clone).build(); + } + + /** + * Get the variables for the next step in the plan. + * + * @param variables The current context variables. + * @param step The next step in the plan. + * @return The context variables for the next step in the plan. + */ + private ContextVariables getNextStepVariables(ContextVariables variables, Plan step) { + // Priority for Input + // - Parameters (expand from variables if needed) + // - SKContext.Variables + // - Plan.State + // - Empty if sending to another plan + // - Plan.Description + + String input = ""; + if (step.parameters != null + && !Verify.isNullOrEmpty(step.parameters.getInput()) + && !step.parameters.getInput().equals(SKFunctionParameters.NO_DEFAULT_VALUE)) { + input = + this.expandFromVariables( + variables, Objects.requireNonNull(step.parameters.getInput())); + } else if (!Verify.isNullOrEmpty(variables.getInput())) { + input = Objects.requireNonNull(variables.getInput()); + } else if (!Verify.isNullOrEmpty(this.state.getInput())) { + input = Objects.requireNonNull(this.state.getInput()); + } else if (steps.size() > 0) { + input = ""; + } else if (!Verify.isNullOrEmpty(this.getDescription())) { + input = this.getDescription(); + } + + WritableContextVariables stepVariables = + SKBuilders.variables() + .withInput(Objects.requireNonNull(input)) + .build() + .writableClone(); + + // Priority for remaining stepVariables is: + // - Function Parameters (pull from variables or state by a key value) + // - Step Parameters (pull from variables or state by a key value) + FunctionView functionParameters = step.describe(); + if (functionParameters != null) { + for (ParameterView param : functionParameters.getParameters()) { + if (param.getName().equals(ContextVariables.MAIN_KEY)) { + continue; + } + + if (!Verify.isNullOrEmpty(variables.get(param.getName()))) { + String variable = Objects.requireNonNull(variables.get(param.getName())); + stepVariables.setVariable(param.getName(), variable); + } else if (!Verify.isNullOrEmpty(this.state.get(param.getName()))) { + String variable = Objects.requireNonNull(this.state.get(param.getName())); + stepVariables.setVariable(param.getName(), variable); + } + } + } + + if (step.parameters != null) { + step.parameters + .asMap() + .forEach( + (key, value) -> { + // Don't overwrite variable values that are already set + if (!Verify.isNullOrEmpty(stepVariables.get(key))) { + return; + } + + String expandedValue = this.expandFromVariables(variables, value); + if (expandedValue != null + && !expandedValue.equalsIgnoreCase(value)) { + stepVariables.setVariable(key, expandedValue); + } else if (!Verify.isNullOrEmpty(variables.get(key))) { + String variable = variables.get(key); + if (variable != null) { + stepVariables.setVariable(key, variable); + } + } else if (!Verify.isNullOrEmpty(state.get(key))) { + String variable = state.get(key); + if (variable != null) { + stepVariables.setVariable(key, variable); + } + } else { + if (expandedValue != null) { + stepVariables.setVariable(key, expandedValue); + } + } + }); + } + + return stepVariables; + } + + public String toPlanString() { + return toPlanString(" "); + } + + private String toPlanString(String indent) { + String goalHeader = indent + "Goal: " + getDescription() + "\n\n" + indent + "Steps:\n"; + + String stepItems = + steps.stream() + .map(step -> stepToString(indent, step)) + .collect(Collectors.joining("\n")); + + return goalHeader + stepItems; + } + + private static String stepToString(String indent, Plan step) { + if (step.steps.size() == 0) { + String skillName = step.getSkillName(); + String stepName = step.getName(); + + String parameters = + step.getParametersView().stream() + .map( + param -> { + String value = param.getDefaultValue(); + if (step.getParameters() != null + && step.getParameters().get(param.getName()) + != null) { + value = step.getParameters().get(param.getName()); + } + return "\t" + param.getName() + ": \"" + value + "\""; + }) + .collect(Collectors.joining(" ")); + + if (!Verify.isNullOrEmpty(parameters)) { + parameters = " " + parameters; + } + + String outputs = step.outputs.stream().findFirst().orElse(""); + if (!Verify.isNullOrEmpty(outputs)) { + outputs = " => " + outputs; + } + + return indent + + indent + + "- " + + String.join(".", skillName, stepName) + + "\t\t\t" + + parameters + + outputs; + } + + return step.toPlanString(indent + indent); + } + + @Nullable + private ContextVariables getParameters() { + return parameters; + } +} diff --git a/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/DefaultSequentialPlannerSKContext.java b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/DefaultSequentialPlannerSKContext.java new file mode 100644 index 0000000000..20f94314da --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/DefaultSequentialPlannerSKContext.java @@ -0,0 +1,256 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.sequentialplanner; + +import com.microsoft.semantickernel.memory.MemoryQueryResult; +import com.microsoft.semantickernel.memory.NullMemory; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class DefaultSequentialPlannerSKContext { + + public static final String PlannerMemoryCollectionName = "Planning.SKFunctionsManual"; + + public static final String PlanSKFunctionsAreRemembered = "Planning.SKFunctionsAreRemembered"; + private final SKContext delegate; + + public DefaultSequentialPlannerSKContext(SKContext delegate) { + this.delegate = delegate; + } + + /** + * Returns a string containing the manual for all available functions. + * + * @param semanticQuery The semantic query for finding relevant registered functions + * @param config The planner skill config + * @param includeFunctionOutputs Whether to include function outputs in the manual + * @return A string containing the manual for all available functions. + */ + public Mono getFunctionsManualAsync( + @Nullable String semanticQuery, + @Nullable SequentialPlannerRequestSettings config, + boolean includeFunctionOutputs) { + if (config == null) { + config = new SequentialPlannerRequestSettings(); + } + + Mono>> functions = + getAvailableFunctionsAsync(config, semanticQuery); + + return functions.map( + funcs -> + funcs.stream() + .map(it -> it.toManualString(includeFunctionOutputs)) + .collect(Collectors.joining("\n\n"))); + } + + /// + /// Returns a list of functions that are available to the user based on the semantic query and + // the excluded skills and functions. + /// + /// The SKContext + /// The planner config. + /// The semantic query for finding relevant registered + // functions + /// A list of functions that are available to the user based on the semantic query and + // the excluded skills and functions. + public Mono>> getAvailableFunctionsAsync( + SequentialPlannerRequestSettings config, @Nullable String semanticQuery) { + Set excludedSkills = config.getExcludedSkills(); + Set excludedFunctions = config.getExcludedFunctions(); + Set includedFunctions = config.getIncludedFunctions(); + + // context.ThrowIfSkillCollectionNotSet(); + + ReadOnlySkillCollection skills = delegate.getSkills(); + List> functions; + if (skills != null) { + functions = skills.getAllFunctions().getAll(); + } else { + functions = Collections.emptyList(); + } + + List> availableFunctions = + functions.stream() + /* + // Is there any function that should be excluded? + .filter( + it -> + it instanceof SemanticSKFunction + || it instanceof NativeSKFunction) + + */ + .filter( + s -> + !excludedSkills.contains(s.getSkillName()) + && !excludedFunctions.contains(s.getName())) + .collect(Collectors.toList()); + + Comparator> comparator = + Comparator., String>comparing(SKFunction::getSkillName) + .thenComparing(SKFunction::getName); + + if (semanticQuery == null + || semanticQuery.isEmpty() + || delegate.getSemanticMemory() == null + || delegate.getSemanticMemory() instanceof NullMemory + || config.getRelevancyThreshold() == null) { + // If no semantic query is provided, return all available functions. + // If a Memory provider has not been registered, return all available functions. + TreeSet> result = new TreeSet<>(comparator); + result.addAll(availableFunctions); + return Mono.just(result); + } else { + // Remember functions in memory so that they can be searched. + return rememberFunctionsAsync(availableFunctions) + .flatMap( + updatedContext -> { + SemanticTextMemory updatedMemory = + updatedContext.getSemanticMemory(); + if (updatedMemory == null) { + return Mono.just(new ArrayList>()); + } + // Search for functions that match the semantic query. + return updatedMemory + .searchAsync( + PlannerMemoryCollectionName, + semanticQuery, + config.getMaxRelevantFunctions(), + config.getRelevancyThreshold(), + false) + .flatMap( + memories -> + getRelevantFunctionsAsync( + availableFunctions, memories)); + }) + .map( + memories -> { + List added = + memories.stream() + .map(SKFunction::getName) + .collect(Collectors.toList()); + + List> missingFunctions = + getMissingFunctions( + includedFunctions, availableFunctions, added); + + ArrayList> res = new ArrayList<>(memories); + res.addAll(missingFunctions); + return res; + }) + .map( + res -> { + TreeSet> result = new TreeSet<>(comparator); + result.addAll(availableFunctions); + return result; + }); + } + } + + private static List> getMissingFunctions( + Set includedFunctions, + List> availableFunctions, + List added) { + return includedFunctions.stream() + .filter(func -> !added.contains(func)) + .flatMap( + missing -> + availableFunctions.stream() + .filter(it -> it.getName().equals(missing))) + .collect(Collectors.toList()); + } + + public Mono>> getRelevantFunctionsAsync( + List> availableFunctions, List memories) { + return Flux.fromIterable(memories) + .map( + memoryEntry -> + availableFunctions.stream() + .filter( + it -> + Objects.equals( + it.toFullyQualifiedName(), + memoryEntry.getMetadata().getId())) + .findFirst() + .orElse(null)) + .filter(Objects::nonNull) + .collectList(); + } + + /// + /// Saves all available functions to memory. + /// + /// The SKContext to save the functions to. + /// The available functions to save. + Mono rememberFunctionsAsync(List> availableFunctions) { + // Check if the functions have already been saved to memory. + if (delegate.getVariables().asMap().containsKey(PlanSKFunctionsAreRemembered)) { + return Mono.just(delegate); + } + + SemanticTextMemory memory = delegate.getSemanticMemory(); + + if (memory == null) { + delegate.setVariable(PlanSKFunctionsAreRemembered, "true"); + return Mono.just(delegate); + } + + return Flux.fromIterable(availableFunctions) + .concatMap( + function -> { + String functionName = function.toFullyQualifiedName(); + String key = functionName; + String description = + function.getDescription() == null + || function.getDescription().isEmpty() + ? functionName + : function.getDescription(); + String textToEmbed = function.toEmbeddingString(); + + // It'd be nice if there were a saveIfNotExists method on the memory + // interface + return memory.getAsync(PlannerMemoryCollectionName, key, false) + .filter(Objects::nonNull) + .flatMap( + memoryEntry -> { + // 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. + return memory.saveInformationAsync( + PlannerMemoryCollectionName, + textToEmbed, + key, + description, + ""); + }) + .flatMap( + newKey -> + memory.getAsync( + PlannerMemoryCollectionName, + newKey, + true)); + }) + .ignoreElements() + .map( + newMemory -> { + delegate.setVariable(PlanSKFunctionsAreRemembered, "true"); + return delegate; + }); + } +} diff --git a/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/EmbeddedResource.java b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/EmbeddedResource.java new file mode 100644 index 0000000000..630477d874 --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/EmbeddedResource.java @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.sequentialplanner; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +public class EmbeddedResource { + + public static String read(String name) { + try (InputStream stream = SequentialPlanner.class.getResourceAsStream(name)) { + byte[] buffer = new byte[stream.available()]; + stream.read(buffer); + return new String(buffer, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanParser.java b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanParser.java new file mode 100644 index 0000000000..c6e4c4cbec --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanParser.java @@ -0,0 +1,206 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.sequentialplanner; + +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.orchestration.WritableContextVariables; +import com.microsoft.semantickernel.planner.PlanningException; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.skilldefinition.FunctionView; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/** Parse sequential plan text into a plan. */ +public class SequentialPlanParser { + private static final Logger LOGGER = LoggerFactory.getLogger(SequentialPlanParser.class); + + // The tag name used in the plan xml for the user's goal/ask. + private static final String GoalTag = "goal"; + + // The tag name used in the plan xml for the solution. + private static final String SolutionTag = "plan"; + + // The tag name used in the plan xml for a step that calls a skill function. + private static final String FunctionTag = "function."; + + // The attribute tag used in the plan xml for setting the context variable name to set the + // output of a function to. + private static final String SetContextVariableTag = + "setContextVariable".toLowerCase(Locale.ROOT); + + // The attribute tag used in the plan xml for appending the output of a function to the final + // result for a plan. + private static final String AppendToResultTag = "appendToResult".toLowerCase(Locale.ROOT); + + /** + * Convert a plan xml string to a plan + * + * @param xmlString The plan xml string + * @param goal The goal for the plan + * @param skills The skills to use + * @return The plan + * @throws PlanningException + */ + public static Plan toPlanFromXml(String xmlString, String goal, ReadOnlySkillCollection skills) + throws PlanningException { + + try { + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + + Document doc = + db.parse( + new ByteArrayInputStream( + ("" + xmlString + "") + .getBytes(StandardCharsets.UTF_8))); + + NodeList solution = doc.getElementsByTagName(SolutionTag); + + Plan plan = new Plan(goal, () -> skills); + + for (int i = 0; i < solution.getLength(); i++) { + Node solutionNode = solution.item(i); + String parentNodeName = solutionNode.getNodeName(); + + for (int j = 0; j < solutionNode.getChildNodes().getLength(); j++) { + Node childNode = solutionNode.getChildNodes().item(j); + if (childNode.getNodeName().equals("#text")) { + if (childNode.getNodeValue() != null + && !childNode.getNodeValue().trim().isEmpty()) { + plan.addSteps(new Plan(childNode.getNodeValue().trim(), () -> skills)); + } + continue; + } + + if (childNode.getNodeName().toLowerCase(Locale.ROOT).startsWith(FunctionTag)) { + String[] skillFunctionNameParts = + childNode.getNodeName().split(FunctionTag, -1); + String skillFunctionName = ""; + + if (skillFunctionNameParts.length > 1) { + skillFunctionName = skillFunctionNameParts[1]; + } + + String skillName = getSkillName(skillFunctionName); + String functionName = getFunctionName(skillFunctionName); + + if (functionName != null + && !functionName.isEmpty() + && skills.hasFunction(skillName, functionName)) { + SKFunction skillFunction = + Objects.requireNonNull(skills.getFunctions(skillName)) + .getFunction(functionName, SKFunction.class); + + WritableContextVariables functionVariables = + getFunctionVariables(skillFunction, childNode); + List functionOutputs = getFunctionOutputs(childNode); + List functionResults = getFunctionResults(childNode); + + Plan planStep = + new Plan( + skillFunction, + functionVariables, + SKBuilders.variables().build(), + functionOutputs, + () -> skills); + + plan.addOutputs(functionResults); + plan.addSteps(planStep); + } else { + LOGGER.trace( + "{}: appending function node {}", + parentNodeName, + skillFunctionName); + plan.addSteps(new Plan(childNode.getTextContent(), () -> skills)); + } + + continue; + } + + plan.addSteps(new Plan(childNode.getTextContent(), () -> skills)); + } + } + return plan; + + } catch (RuntimeException | ParserConfigurationException | IOException | SAXException e) { + throw new PlanningException( + PlanningException.ErrorCodes.INVALID_PLAN, "Failed to parse plan xml.", e); + } + } + + private static WritableContextVariables getFunctionVariables( + SKFunction skillFunction, Node node) { + WritableContextVariables functionVariables = SKBuilders.variables().build().writableClone(); + + FunctionView description = skillFunction.describe(); + + if (description != null) { + description + .getParameters() + .forEach( + p -> { + functionVariables.setVariable(p.getName(), p.getDefaultValue()); + }); + } + + if (node.getAttributes() != null) { + for (int k = 0; k < node.getAttributes().getLength(); k++) { + Node attr = node.getAttributes().item(k); + String nodeName = attr.getNodeName().toLowerCase(Locale.ROOT); + if (!nodeName.equals(SetContextVariableTag) + && !nodeName.equals(AppendToResultTag)) { + functionVariables.setVariable(attr.getNodeName(), attr.getTextContent()); + } + } + } + return functionVariables; + } + + private static List getFunctionOutputs(Node node) { + List functionOutputs = new ArrayList<>(); + for (int k = 0; k < node.getAttributes().getLength(); k++) { + Node attr = node.getAttributes().item(k); + String nodeName = attr.getNodeName().toLowerCase(Locale.ROOT); + if (nodeName.equals(SetContextVariableTag) || nodeName.equals(AppendToResultTag)) { + functionOutputs.add(attr.getTextContent()); + } + } + return functionOutputs; + } + + private static List getFunctionResults(Node node) { + List functionResults = new ArrayList<>(); + for (int k = 0; k < node.getAttributes().getLength(); k++) { + Node attr = node.getAttributes().item(k); + String nodeName = attr.getNodeName().toLowerCase(Locale.ROOT); + if (nodeName.equals(AppendToResultTag)) { + functionResults.add(attr.getTextContent()); + } + } + return functionResults; + } + + private static String getSkillName(String skillFunctionName) { + String[] skillFunctionNameParts = skillFunctionName.split("\\.", -1); + return skillFunctionNameParts.length > 0 ? skillFunctionNameParts[0] : ""; + } + + private static String getFunctionName(String skillFunctionName) { + String[] skillFunctionNameParts = skillFunctionName.split("\\.", -1); + return skillFunctionNameParts.length > 1 ? skillFunctionNameParts[1] : skillFunctionName; + } +} diff --git a/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanner.java b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanner.java new file mode 100644 index 0000000000..06d319550c --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/java/com/microsoft/semantickernel/planner/sequentialplanner/SequentialPlanner.java @@ -0,0 +1,134 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.sequentialplanner; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.PlanningException; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +/** A planner that uses semantic function to create a sequential plan. */ +public class SequentialPlanner { + + private static final Logger LOGGER = LoggerFactory.getLogger(SequentialPlanner.class); + private static final String StopSequence = " + +[AVAILABLE FUNCTIONS] + + _GLOBAL_FUNCTIONS_.GetEmailAddress: + description: Gets email address for given contact + inputs: + - input: the name to look up + + _GLOBAL_FUNCTIONS_.SendEmail: + description: email the input text to a recipient + inputs: + - input: the text to email + - recipient: the recipient's email address. Multiple addresses may be included if separated by ';'. + + AuthorAbility.Summarize: + description: summarizes the input text + inputs: + - input: the text to summarize + + Magician.TranslateTo: + description: translate the input to another language + inputs: + - input: the text to translate + - translate_to_language: the language to translate to + +[END AVAILABLE FUNCTIONS] + +Summarize an input, translate to french, and e-mail to John Doe + + + + + + + +[AVAILABLE FUNCTIONS] + + _GLOBAL_FUNCTIONS_.NovelOutline : + description: Outlines the input text as if it were a novel + inputs: + - input: the title of the novel to outline + - chapterCount: the number of chapters to outline + + Emailer.EmailTo: + description: email the input text to a recipient + inputs: + - input: the text to email + - recipient: the recipient's email address. Multiple addresses may be included if separated by ';'. + + Everything.Summarize: + description: summarize input text + inputs: + - input: the text to summarize + +[END AVAILABLE FUNCTIONS] + +Create an outline for a children's book with 3 chapters about a group of kids in a club and then summarize it. + + + + + +[END EXAMPLES] + +[AVAILABLE FUNCTIONS] + +{{$available_functions}} + +[END AVAILABLE FUNCTIONS] + +{{$input}} diff --git a/java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/stepwiseplanner/config.json b/java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/stepwiseplanner/config.json new file mode 100644 index 0000000000..51ef104e45 --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/stepwiseplanner/config.json @@ -0,0 +1,32 @@ +{ + "schema": 1, + "description": "Given a request or command or goal generate multi-step plan to reach the goal. After each step LLM is called to perform the reasoning for the next step.", + "type": "completion", + "completion": { + "max_tokens": 1024, + "temperature": 0, + "top_p": 0, + "presence_penalty": 0, + "frequency_penalty": 0, + "stop_sequences": ["[OBSERVATION]", "\n[THOUGHT]"] + }, + "input": { + "parameters": [ + { + "name": "question", + "description": "The question to answer", + "defaultValue": "" + }, + { + "name": "agentScratchPad", + "description": "The agent's scratch pad", + "defaultValue": "" + }, + { + "name": "functionDescriptions", + "description": "The manual of the agent's functions", + "defaultValue": "" + } + ] + } +} diff --git a/java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/stepwiseplanner/skprompt.txt b/java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/stepwiseplanner/skprompt.txt new file mode 100644 index 0000000000..723b68d74c --- /dev/null +++ b/java/extensions/semantickernel-planners/src/main/resources/com/microsoft/semantickernel/planner/stepwiseplanner/skprompt.txt @@ -0,0 +1,49 @@ +[INSTRUCTION] +Answer the following questions as accurately as possible using the provided functions. + +[AVAILABLE FUNCTIONS] +The function definitions below are in the following format: +: + - : + - ... + +{{$functionDescriptions}} +[END AVAILABLE FUNCTIONS] + +[USAGE INSTRUCTIONS] +To use the functions, specify a JSON blob representing an action. The JSON blob should contain an "action" key with the name of the function to use, and an "action_variables" key with a JSON object of string values to use when calling the function. +Do not call functions directly; they must be invoked through an action. +The "action_variables" value should always include an "input" key, even if the input value is empty. Additional keys in the "action_variables" value should match the defined [PARAMETERS] of the named "action" in [AVAILABLE FUNCTIONS]. +Dictionary values in "action_variables" must be strings and represent the actual values to be passed to the function. +Ensure that the $JSON_BLOB contains only a SINGLE action; do NOT return multiple actions. +IMPORTANT: Use only the available functions listed in the [AVAILABLE FUNCTIONS] section. Do not attempt to use any other functions that are not specified. + +Here is an example of a valid $JSON_BLOB: +{ + "action": "FUNCTION.NAME", + "action_variables": {"INPUT": "some input", "PARAMETER_NAME": "some value", "PARAMETER_NAME_2": "42"} +} +[END USAGE INSTRUCTIONS] +[END INSTRUCTION] + +[THOUGHT PROCESS] +[QUESTION] +the input question I must answer +[THOUGHT] +To solve this problem, I should carefully analyze the given question and identify the necessary steps. Any facts I discover earlier in my thought process should be repeated here to keep them readily available. +[ACTION] +$JSON_BLOB +[OBSERVATION] +The result of the action will be provided here. +... (These Thought/Action/Observation can repeat until the final answer is reached.) +[FINAL ANSWER] +Once I have gathered all the necessary observations and performed any required actions, I can provide the final answer in a clear and human-readable format. +[END THOUGHT PROCESS] + +Let's break down the problem step by step and think about the best approach. Questions and observations should be followed by a single thought and an optional single action to take. + +Begin! + +[QUESTION] +{{$question}} +{{$agentScratchPad}} diff --git a/java/extensions/semantickernel-settings-loader/pom.xml b/java/extensions/semantickernel-settings-loader/pom.xml new file mode 100644 index 0000000000..68052d2d15 --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/pom.xml @@ -0,0 +1,32 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-settings-loader + Semantic Kernel Settings Loader + Semantic Kernel Settings Loader + + + + com.microsoft.semantic-kernel + semantickernel-api + + + org.mockito + mockito-core + + + org.junit.jupiter + junit-jupiter + + + diff --git a/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/SemanticKernelHttpSettings.java b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/SemanticKernelHttpSettings.java new file mode 100644 index 0000000000..fe4bea7f1d --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/SemanticKernelHttpSettings.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.azure.core.util.ClientOptions; +import com.azure.core.util.Header; +import java.util.Collections; +import java.util.Map; +import javax.annotation.Nullable; + +public class SemanticKernelHttpSettings { + + public static final String DEFAULT_USER_AGENT = "Semantic-Kernel-Java"; + + public static ClientOptions getUserAgent(@Nullable Map configuredSettings) { + + String useragent; + + if (configuredSettings == null) { + useragent = DEFAULT_USER_AGENT; + } else { + useragent = configuredSettings.getOrDefault("useragent", DEFAULT_USER_AGENT); + } + + return new ClientOptions() + .setHeaders(Collections.singletonList(new Header("User-Agent", useragent))); + } + + public static ClientOptions getUserAgent() { + return getUserAgent(null); + } +} diff --git a/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/AbstractOpenAIClientSettings.java b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/AbstractOpenAIClientSettings.java new file mode 100644 index 0000000000..f13bc83885 --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/AbstractOpenAIClientSettings.java @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.util; + +import com.microsoft.semantickernel.exceptions.ConfigurationException; + +/** + * Settings for an OpenAI client that uses a specific OpenAI provider such as openai.com or Azure + * OpenAI. + */ +public abstract class AbstractOpenAIClientSettings { + + public static final String KEY_SUFFIX = "key"; + + /** + * Check if the settings are valid + * + * @return true if the settings are valid + */ + public abstract boolean assertIsValid() throws ConfigurationException; + + /** + * Get the OpenAI client key + * + * @return OpenAI client key + */ + public abstract String getKey() throws ConfigurationException; +} diff --git a/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/AzureOpenAISettings.java b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/AzureOpenAISettings.java new file mode 100644 index 0000000000..789f129cb9 --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/AzureOpenAISettings.java @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.util; + +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import java.util.Map; +import javax.annotation.Nullable; + +/** Settings for Azure OpenAI client */ +public class AzureOpenAISettings extends AbstractOpenAIClientSettings { + private static final String DEFAULT_SETTINGS_PREFIX = "client.azureopenai"; + private static final String AZURE_OPEN_AI_ENDPOINT_SUFFIX = "endpoint"; + private static final String AZURE_OPEN_AI_DEPLOYMENT_NAME_SUFFIX = "deploymentname"; + + @Nullable private final String key; + + @Nullable private final String endpoint; + + @Nullable private final String deploymentName; + private final String settingsPrefix; + + public AzureOpenAISettings(Map settings) { + this(DEFAULT_SETTINGS_PREFIX, settings); + } + + public AzureOpenAISettings(String settingsPrefix, Map settings) { + this.settingsPrefix = settingsPrefix; + key = settings.get(settingsPrefix + "." + KEY_SUFFIX); + endpoint = settings.get(settingsPrefix + "." + AZURE_OPEN_AI_ENDPOINT_SUFFIX); + deploymentName = settings.get(settingsPrefix + "." + AZURE_OPEN_AI_DEPLOYMENT_NAME_SUFFIX); + } + + /** + * Get the Azure OpenAI endpoint + * + * @return Azure OpenAI endpoint + */ + public String getEndpoint() throws ConfigurationException { + if (endpoint == null) { + throw new ConfigurationException( + ConfigurationException.ErrorCodes.VALUE_NOT_FOUND, + AZURE_OPEN_AI_ENDPOINT_SUFFIX); + } + return endpoint; + } + + /** + * Get the Azure OpenAI deployment name + * + * @return Azure OpenAI deployment name + */ + public String getDeploymentName() throws ConfigurationException { + if (deploymentName == null) { + throw new ConfigurationException( + ConfigurationException.ErrorCodes.VALUE_NOT_FOUND, + AZURE_OPEN_AI_DEPLOYMENT_NAME_SUFFIX); + } + return deploymentName; + } + + public String getKey() throws ConfigurationException { + if (key == null) { + throw new ConfigurationException( + ConfigurationException.ErrorCodes.VALUE_NOT_FOUND, KEY_SUFFIX); + } + return key; + } + + @Override + public boolean assertIsValid() throws ConfigurationException { + if (key == null) { + throw new ConfigurationException( + ConfigurationException.ErrorCodes.VALUE_NOT_FOUND, + settingsPrefix + "." + KEY_SUFFIX); + } + if (endpoint == null) { + throw new ConfigurationException( + ConfigurationException.ErrorCodes.VALUE_NOT_FOUND, + settingsPrefix + "." + AZURE_OPEN_AI_ENDPOINT_SUFFIX); + } + + return true; + } +} diff --git a/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/ClientType.java b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/ClientType.java new file mode 100644 index 0000000000..e292914468 --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/ClientType.java @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.util; + +/** OpenAI client type */ +public enum ClientType { + OPEN_AI, + AZURE_OPEN_AI +}; diff --git a/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/OpenAIClientProvider.java b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/OpenAIClientProvider.java new file mode 100644 index 0000000000..0904b8cc92 --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/OpenAIClientProvider.java @@ -0,0 +1,254 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.util; + +import static com.microsoft.semantickernel.exceptions.ConfigurationException.ErrorCodes.NO_VALID_CONFIGURATIONS_FOUND; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.KeyCredential; +import com.azure.core.util.ClientOptions; +import com.microsoft.semantickernel.SemanticKernelHttpSettings; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.settings.SettingsMap; +import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.slf4j.Logger; + +/** + * Builds an OpenAI client instance, see {@link SettingsMap} documentation for details on how the + * settings are loaded. + * + *

If clientType is not set via OPENAI_CLIENT_TYPE setting, then this will attempt to first + * instantiate an OpenAI client, and if that fails, then it will attempt to instantiate an Azure + * OpenAI client. + */ +public class OpenAIClientProvider { + + private static final Logger LOGGER = + org.slf4j.LoggerFactory.getLogger(OpenAIClientProvider.class); + + public static final String OPENAI_CLIENT_TYPE = "OPENAI_CLIENT_TYPE"; + + @Nullable private static final OpenAIClientProvider DEFAULT_INST; + + static { + // Build a configuration following the default precedence + OpenAIClientProvider DEFAULT_INST_TMP; + try { + DEFAULT_INST_TMP = buildProvider(null, null); + } catch (ConfigurationException e) { + LOGGER.error("Failed to load default settings", e); + DEFAULT_INST_TMP = null; + } + DEFAULT_INST = DEFAULT_INST_TMP; + } + + @Nullable private final ClientType clientType; + private final Map configuredSettings; + private final ClientOptions clientOptions; + + /** + * Create a new OpenAI client provider + * + * @param configuredSettings settings to use to configure the client + * @param clientType client type + */ + public OpenAIClientProvider( + Map configuredSettings, @Nullable ClientType clientType) { + this.configuredSettings = Collections.unmodifiableMap(configuredSettings); + this.clientType = clientType; + this.clientOptions = SemanticKernelHttpSettings.getUserAgent(configuredSettings); + } + + private static OpenAIClientProvider buildProvider( + @Nullable List propertyFileLocations, @Nullable ClientType clientType) + throws ConfigurationException { + Map settings = getSettings(propertyFileLocations); + + if (clientType == null) { + String clientValue = settings.get(OPENAI_CLIENT_TYPE); + if (clientValue != null) { + clientType = ClientType.valueOf(clientValue); + } + } + + return new OpenAIClientProvider(settings, clientType); + } + + private static Map getSettings(@Nullable List propertyFileLocations) + throws ConfigurationException { + Map settings; + + if (propertyFileLocations != null) { + settings = SettingsMap.get(propertyFileLocations); + } else { + settings = SettingsMap.getDefault(); + } + return settings; + } + + /** + * Get a client, overrides the default locations that are searched for settings + * + * @param propertyFileLocations locations to look for settings in + * @param clientType client type + * @return A client instance + * @throws ConfigurationException if the settings are not found + */ + public static OpenAIAsyncClient get( + List propertyFileLocations, @Nullable ClientType clientType) + throws ConfigurationException { + return buildProvider(propertyFileLocations, clientType).getAsyncClient(); + } + + /** + * Get a client, overrides the default locations that are searched for settings + * + * @param propertyFileLocations locations to look for settings in + * @return A client instance + * @throws ConfigurationException if the settings are not found + */ + public static OpenAIAsyncClient get(List propertyFileLocations) + throws ConfigurationException { + return get(propertyFileLocations, null); + } + + /** + * Get a client, looks for settings in the default locations as defined by this class, PLUS the + * additional locations provided + * + * @param propertyFileLocations additional locations to look for settings + * @param clientType client type + * @return A client instance + */ + public static OpenAIAsyncClient getWithAdditional( + List propertyFileLocations, @Nullable ClientType clientType) + throws ConfigurationException { + Map settings = SettingsMap.getWithAdditional(propertyFileLocations); + + if (clientType == null && settings.containsKey(OPENAI_CLIENT_TYPE)) { + clientType = ClientType.valueOf(settings.get(OPENAI_CLIENT_TYPE)); + } + + return new OpenAIClientProvider(settings, clientType).getAsyncClient(); + } + + /** + * Get a client, looks for settings in the default locations as defined by this class, PLUS the + * additional locations provided + * + * @param propertyFileLocations additional locations to look for settings + * @return A client instance + */ + public static OpenAIAsyncClient getWithAdditional(List propertyFileLocations) + throws ConfigurationException { + return getWithAdditional(propertyFileLocations, null); + } + + /** + * Builds an OpenAI client instance, see {@link SettingsMap} documentation for details on how + * the settings are loaded. + * + * @return A client instance + * @throws ConfigurationException If the settings are not found + */ + public static OpenAIAsyncClient getClient() throws ConfigurationException { + if (DEFAULT_INST == null) { + throw new ConfigurationException(NO_VALID_CONFIGURATIONS_FOUND); + } + return DEFAULT_INST.getAsyncClient(); + } + + /** + * Builds an OpenAI client instance, the settings for the client are loaded from the following + * sources in the order of precedence (lower number in this list overrides a higher number): + * + *

    + *
  • 1. Environment variables. + *
  • 2. System properties. + *
  • 3. Properties file set via CONF_PROPERTIES environment variable. + *
  • 4. Properties file: ./conf.properties (Not used if CONF_PROPERTIES was set). + *
  • 5. Properties file: ~/.sk/conf.properties (Not used if CONF_PROPERTIES was set). + *
+ * + *

If clientType is not set via OPENAI_CLIENT_TYPE setting, then this will attempt to first + * instantiate an OpenAI client, and if that fails, then it will attempt to instantiate an Azure + * OpenAI client. + * + * @return A client instance + * @throws ConfigurationException If the settings are not found + */ + public OpenAIAsyncClient getAsyncClient() throws ConfigurationException { + // No client type is specified, search for a valid client type + if (clientType == null) { + LOGGER.debug("No OpenAI client type specified, searching for a valid client type"); + try { + LOGGER.debug("Trying OpenAI client"); + OpenAIAsyncClient client = buildOpenAIClient(); + LOGGER.debug("Successfully instantiated OpenAI client"); + return client; + } catch (ConfigurationException e) { + LOGGER.debug("No OpenAI client found"); + } + + try { + LOGGER.debug("Trying Azure OpenAI client"); + OpenAIAsyncClient client = buildAzureOpenAIClient(); + LOGGER.debug("Successfully instantiated Azure OpenAI client"); + return client; + } catch (ConfigurationException e) { + LOGGER.debug("No Azure OpenAI client found"); + throw new ConfigurationException(NO_VALID_CONFIGURATIONS_FOUND); + } + } else { + switch (clientType) { + case OPEN_AI: + return buildOpenAIClient(); + case AZURE_OPEN_AI: + return buildAzureOpenAIClient(); + default: + throw new ConfigurationException(NO_VALID_CONFIGURATIONS_FOUND); + } + } + } + + private OpenAIAsyncClient buildOpenAIClient() throws ConfigurationException { + OpenAISettings settings = new OpenAISettings(configuredSettings); + try { + settings.assertIsValid(); + } catch (ConfigurationException e) { + LOGGER.warn("Settings are not valid for OpenAI client"); + LOGGER.warn(e.getMessage()); + throw e; + } + + return new OpenAIClientBuilder() + .credential(new KeyCredential(settings.getKey())) + .clientOptions(clientOptions) + .buildAsyncClient(); + } + + private OpenAIAsyncClient buildAzureOpenAIClient() throws ConfigurationException { + AzureOpenAISettings settings = new AzureOpenAISettings(configuredSettings); + + try { + settings.assertIsValid(); + } catch (ConfigurationException e) { + LOGGER.warn("Could not instantiate Azure OpenAI client"); + LOGGER.warn(e.getMessage()); + throw e; + } + + OpenAIClientBuilder builder = + new OpenAIClientBuilder() + .endpoint(settings.getEndpoint()) + .clientOptions(clientOptions) + .credential(new AzureKeyCredential(settings.getKey())); + + return builder.buildAsyncClient(); + } +} diff --git a/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/OpenAISettings.java b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/OpenAISettings.java new file mode 100644 index 0000000000..6a47cf9ef0 --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/connectors/ai/openai/util/OpenAISettings.java @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.util; + +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import java.util.Map; +import javax.annotation.Nullable; + +public class OpenAISettings extends AbstractOpenAIClientSettings { + public static final String OPEN_AI_ORGANIZATION_SUFFIX = "organizationid"; + private static final String DEFAULT_SETTINGS_PREFIX = "client.openai"; + + @Nullable private final String key; + @Nullable private final String organizationId; + private final String settingsPrefix; + + public OpenAISettings(Map settings) { + this(DEFAULT_SETTINGS_PREFIX, settings); + } + + public OpenAISettings(String settingsPrefix, Map settings) { + this.settingsPrefix = settingsPrefix; + key = settings.get(settingsPrefix + "." + KEY_SUFFIX); + organizationId = settings.get(settingsPrefix + "." + OPEN_AI_ORGANIZATION_SUFFIX); + } + + public String getKey() throws ConfigurationException { + if (key == null) { + throw new ConfigurationException( + ConfigurationException.ErrorCodes.VALUE_NOT_FOUND, "key"); + } + return key; + } + + public String getOrganizationId() throws ConfigurationException { + if (organizationId == null) { + throw new ConfigurationException( + ConfigurationException.ErrorCodes.VALUE_NOT_FOUND, "organizationid"); + } + return organizationId; + } + + @Override + public boolean assertIsValid() throws ConfigurationException { + if (key == null) { + throw new ConfigurationException( + ConfigurationException.ErrorCodes.VALUE_NOT_FOUND, + settingsPrefix + "." + KEY_SUFFIX); + } + return true; + } +} diff --git a/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/settings/SettingsMap.java b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/settings/SettingsMap.java new file mode 100644 index 0000000000..bfbfa5d9bd --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/src/main/java/com/microsoft/semantickernel/settings/SettingsMap.java @@ -0,0 +1,173 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.settings; + +import static com.microsoft.semantickernel.exceptions.ConfigurationException.ErrorCodes.CONFIGURATION_NOT_FOUND; +import static com.microsoft.semantickernel.exceptions.ConfigurationException.ErrorCodes.COULD_NOT_READ_CONFIGURATION; +import static com.microsoft.semantickernel.exceptions.ConfigurationException.ErrorCodes.NO_VALID_CONFIGURATIONS_FOUND; + +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import org.slf4j.Logger; + +/** + * Creates a map of settings to be used in configuration, the settings are loaded from the following + * sources in the order of precedence (lower number in this list overrides a higher number): + * + *

    + *
  • 1. System properties. + *
  • 2. Environment variables. + *
  • 3. Properties file set via CONF_PROPERTIES environment variable. + *
  • 4. Properties file: ./conf.properties (Not used if CONF_PROPERTIES was set). + *
  • 5. Properties file: ~/.sk/conf.properties (Not used if CONF_PROPERTIES was set). + *
+ */ +public class SettingsMap { + private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(SettingsMap.class); + + public static final String CONF_PROPERTIES_NAME = "CONF_PROPERTIES"; + public static final String CONF_PROPERTIES = + getEnvOrProperty(CONF_PROPERTIES_NAME, "conf.properties"); + + private static final List DEFAULT_PROPERTIES_LOCATIONS = + Arrays.asList( + new File(new File(System.getProperty("user.home"), ".sk"), "conf.properties"), + new File("conf.properties")); + @Nullable private static Map DEFAULT_INST; + + private static void initSettings() { + if (DEFAULT_INST != null) { + return; + } + + // Create the default instance + Map DEFAULT_INST_TMP; + try { + DEFAULT_INST_TMP = get(DEFAULT_PROPERTIES_LOCATIONS); + } catch (ConfigurationException e) { + LOGGER.error("Failed to load settings", e); + DEFAULT_INST_TMP = null; + } + DEFAULT_INST = DEFAULT_INST_TMP; + } + + /** + * Get settings, looks for settings in the default locations + * + * @return A map of settings + */ + public static Map getDefault() throws ConfigurationException { + initSettings(); + if (DEFAULT_INST == null) { + throw new ConfigurationException(NO_VALID_CONFIGURATIONS_FOUND); + } + return Collections.unmodifiableMap(DEFAULT_INST); + } + + /** + * Get settings, looks for settings in the locations plus the additional locations provided + * + * @param propertyFileLocations additional locations to look for settings + * @return A client instance + */ + public static Map get(List propertyFileLocations) + throws ConfigurationException { + return Collections.unmodifiableMap(loadAllSettings(propertyFileLocations)); + } + + /** + * Get settings, looks for settings in the default locations plus the additional locations + * provided + * + * @param propertyFileLocations additional locations to look for settings + * @return A client instance + */ + public static Map getWithAdditional(List propertyFileLocations) + throws ConfigurationException { + ArrayList locations = new ArrayList<>(DEFAULT_PROPERTIES_LOCATIONS); + locations.addAll(propertyFileLocations); + return get(locations); + } + + private static Map loadAllSettings(List propertyFileLocations) + throws ConfigurationException { + Properties properties = new Properties(); + + if (getEnvOrProperty(CONF_PROPERTIES_NAME, null) != null) { + // User has explicitly set CONF_PROPERTIES, so ONLY use that and System properties + if (Files.isRegularFile(new File(CONF_PROPERTIES).toPath())) { + try (FileInputStream fis = new FileInputStream(CONF_PROPERTIES)) { + properties.load(fis); + } catch (FileNotFoundException e) { + throw new ConfigurationException(CONFIGURATION_NOT_FOUND, CONF_PROPERTIES); + } catch (IOException e) { + throw new ConfigurationException(COULD_NOT_READ_CONFIGURATION, CONF_PROPERTIES); + } + } + } else { + // Use default locations + propertyFileLocations.forEach( + file -> { + if (Files.isRegularFile(file.toPath())) { + try (FileInputStream fis = new FileInputStream(file)) { + properties.load(fis); + LOGGER.info("Added settings from: {}", file); + } catch (FileNotFoundException e) { + LOGGER.info("No config file found at: {}", file); + } catch (IOException e) { + LOGGER.info("Failed to read config file at: {}", file); + } + } else { + LOGGER.info("Did not find configuration file: {}", file); + } + }); + } + + // lowercase and replace _ with ., to convert environment variables to properties + Map envVariables = + System.getenv().entrySet().stream() + .collect( + Collectors.toMap( + key -> key.getKey().toLowerCase().replace("_", "."), + Entry::getValue)); + + // Overlay environment variables + properties.putAll(envVariables); + + // Overlay system properties + properties.putAll(System.getProperties()); + + return properties.stringPropertyNames().stream() + .collect( + HashMap::new, + (m, k) -> m.put(k, properties.getProperty(k)), + HashMap::putAll); + } + + private static String getEnvOrProperty(String propertyName, String defaultValue) { + String env = System.getenv(propertyName); + if (env != null && !env.isEmpty()) { + return env; + } + + String property = System.getProperty(propertyName); + if (property != null && !property.isEmpty()) { + return property; + } + + return defaultValue; + } +} diff --git a/java/extensions/semantickernel-settings-loader/src/test/java/com/microsoft/semantickernel/connectors/ai/openai/util/ConfigLoadingTest.java b/java/extensions/semantickernel-settings-loader/src/test/java/com/microsoft/semantickernel/connectors/ai/openai/util/ConfigLoadingTest.java new file mode 100644 index 0000000000..859945538b --- /dev/null +++ b/java/extensions/semantickernel-settings-loader/src/test/java/com/microsoft/semantickernel/connectors/ai/openai/util/ConfigLoadingTest.java @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.util; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ConfigLoadingTest { + + @Test + public void openAiConfigIsLoaded() throws ConfigurationException, IOException { + List entries = Arrays.asList("client.openai.key: 123"); + + OpenAIAsyncClient client = runWithConfig(entries); + Assertions.assertNotNull(client); + } + + @Test + public void azureOpenAiConfigIsLoaded() throws ConfigurationException, IOException { + List entries = + Arrays.asList( + "client.azureopenai.key: 123", + "client.azureopenai.endpoint: https://endpoint"); + + OpenAIAsyncClient client = runWithConfig(entries); + Assertions.assertNotNull(client); + } + + private static OpenAIAsyncClient runWithConfig(List entries) + throws IOException, ConfigurationException { + Path dir = Files.createTempDirectory("testConfig"); + File props = createConfig(dir, entries); + return OpenAIClientProvider.get(Arrays.asList(props)); + } + + private static File createConfig(Path dir, List entries) throws IOException { + File props = Files.createTempFile(dir, "a", ".properties").toFile(); + + try (FileWriter fos = new FileWriter(props)) { + entries.forEach( + e -> { + try { + fos.write(e + System.lineSeparator()); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + }); + } + return props; + } +} diff --git a/java/mvnw b/java/mvnw new file mode 100755 index 0000000000..8d937f4c14 --- /dev/null +++ b/java/mvnw @@ -0,0 +1,308 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.2.0 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "$(uname)" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin ; then + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "\"$javaExecutable\"")" + fi + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$(cd "$wdir/.." || exit 1; pwd) + fi + # end of workaround + done + printf '%s' "$(cd "$basedir" || exit 1; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; + esac + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget > /dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/java/mvnw.cmd b/java/mvnw.cmd new file mode 100644 index 0000000000..c4586b564e --- /dev/null +++ b/java/mvnw.cmd @@ -0,0 +1,205 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/java/plugins/semantickernel-plugin-core/pom.xml b/java/plugins/semantickernel-plugin-core/pom.xml new file mode 100644 index 0000000000..58a9086776 --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/pom.xml @@ -0,0 +1,39 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../../pom.xml + + + semantickernel-plugin-core + Semantic Kernel Core Plugins + Core plugins used by the Semantic Kernel + + + + com.microsoft.semantic-kernel + semantickernel-api + + + org.junit.jupiter + junit-jupiter-api + test + + + io.projectreactor + reactor-test + test + 3.5.6 + + + org.mockito + mockito-core + test + + + diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/ConversationSummarySkill.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/ConversationSummarySkill.java new file mode 100644 index 0000000000..a3f3ab1d71 --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/ConversationSummarySkill.java @@ -0,0 +1,157 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.text.TextChunker; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import java.util.List; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/** Semantic skill that enables conversations summarization */ +public class ConversationSummarySkill { + // The max tokens to process in a single semantic function call. + private static final int MaxTokens = 1024; + + private final CompletionSKFunction summarizeConversationFunction; + private final CompletionSKFunction conversationActionItemsFunction; + private final CompletionSKFunction conversationTopicsFunction; + private final Kernel kernel; + + /** + * Initializes a new instance of the ConversationSummarySkill class + * + * @param kernel Kernel instance + */ + public ConversationSummarySkill(Kernel kernel) { + this.kernel = kernel; + this.summarizeConversationFunction = + SKBuilders.completionFunctions() + .withKernel(kernel) + .withPromptTemplate( + SemanticFunctionConstants.SummarizeConversationDefinition) + .withFunctionName("summarize") + .withSkillName("ConversationSummarySkill") + .withDescription( + "Given a section of a conversation transcript, summarize the part" + + " of the conversation.") + .withCompletionConfig( + SKBuilders.completionConfig() + .maxTokens(MaxTokens) + .temperature(0.1) + .topP(0.5) + .build()) + .build(); + + this.conversationActionItemsFunction = + SKBuilders.completionFunctions() + .withKernel(kernel) + .withPromptTemplate( + SemanticFunctionConstants.GetConversationActionItemsDefinition) + .withFunctionName("ActionItems") + .withSkillName("ConversationSummarySkill") + .withDescription( + "Given a section of a conversation transcript, identify action" + + " items.") + .withCompletionConfig( + SKBuilders.completionConfig() + .maxTokens(MaxTokens) + .temperature(0.1) + .topP(0.5) + .build()) + .build(); + + this.conversationTopicsFunction = + SKBuilders.completionFunctions() + .withKernel(kernel) + .withPromptTemplate( + SemanticFunctionConstants.GetConversationTopicsDefinition) + .withFunctionName("Topics") + .withSkillName("ConversationSummarySkill") + .withDescription( + "Analyze a conversation transcript and extract key topics worth" + + " remembering.") + .withCompletionConfig( + SKBuilders.completionConfig() + .maxTokens(MaxTokens) + .temperature(0.1) + .topP(0.5) + .build()) + .build(); + } + + /** + * Given a long conversation transcript, summarize the conversation + * + * @param input A long conversation transcript + * @param context The SKContext for function execution + * @return A context containing the summarized conversation + */ + @DefineSKFunction( + description = "Given a long conversation transcript, summarize the conversation.", + name = "SummarizeConversation") + public Mono summarizeConversationAsync( + @SKFunctionInputAttribute(description = "A long conversation transcript.") String input, + @Nullable SKContext context) { + List lines = TextChunker.splitPlainTextLines(input, MaxTokens); + List paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens); + + if (context == null) { + context = SKBuilders.context().withSkills(kernel.getSkills()).build(); + } + + SKContext completionContext = context.copy(); + + return this.summarizeConversationFunction.aggregatePartitionedResultsAsync( + paragraphs, completionContext); + } + + /** + * Given a long conversation transcript, identify action items + * + * @param input A long conversation transcript + * @param context The SKContext for function execution + * @return A context containing the action items + */ + @DefineSKFunction( + description = "Given a long conversation transcript, identify action items.", + name = "GetConversationActionItems") + public Mono getConversationActionItemsAsync( + @SKFunctionInputAttribute(description = "A long conversation transcript.") String input, + SKContext context) { + List lines = TextChunker.splitPlainTextLines(input, MaxTokens); + List paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens); + + SKContext completionContext = context.copy(); + + return this.conversationActionItemsFunction.aggregatePartitionedResultsAsync( + paragraphs, completionContext); + } + + /** + * Given a long conversation transcript, identify topics + * + * @param input A long conversation transcript + * @param context The SKContext for function execution + * @return A context containing the topics + */ + @DefineSKFunction( + description = + "Given a long conversation transcript, identify topics worth remembering.", + name = "GetConversationTopics") + public Mono getConversationTopicsAsync( + @SKFunctionInputAttribute(description = "A long conversation transcript.") String input, + SKContext context) { + List lines = TextChunker.splitPlainTextLines(input, MaxTokens); + List paragraphs = TextChunker.splitPlainTextParagraphs(lines, MaxTokens); + + SKContext completionContext = context.copy(); + + return this.conversationTopicsFunction.aggregatePartitionedResultsAsync( + paragraphs, completionContext); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/FileIOSkill.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/FileIOSkill.java new file mode 100644 index 0000000000..41637362cb --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/FileIOSkill.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Read and write from a file. + * + *

Usage: kernel.ImportSkill("file", new FileIOSkill()); + * + *

Examples: + * + *

{@code
+ * file.readAsync($path) => "hello world"
+ * file.writeAsync()
+ * }
+ */ +public class FileIOSkill { + + /** + * Read a file. + * + *

Example: + * + *

{@code
+     * file.readAsync($path) => "hello world"
+     * }
+ * + * @param path Source file. + * @return File content. + */ + @DefineSKFunction(description = "Read a file", name = "readAsync") + public String readFileAsync( + @SKFunctionInputAttribute(description = "Source file") String path, + @SKFunctionParameters( + name = "charset", + description = "Character set to use to read the file", + defaultValue = "UTF-8") + String charset) + throws IOException { + Path filePath = Paths.get(path); + byte[] fileBytes; + fileBytes = Files.readAllBytes(filePath); + String fileContents = new String(fileBytes, Charset.forName(charset)); + return fileContents; + } + + /** + * Write a file. + * + *

Example: + * + *

{@code
+     * file.writeAsync()
+     * }
+ * + * @param path The destination file. + * @param content Contains the 'content' to write + */ + @DefineSKFunction(description = "Write a file", name = "writeAsync") + public void writeFileAsync( + @SKFunctionInputAttribute(description = "Destination file") String path, + @SKFunctionParameters( + name = "content", + description = "File content", + defaultValue = "", + type = String.class) + String content, + @SKFunctionParameters( + name = "charset", + description = "Character set to use to read the file", + defaultValue = "UTF-8") + String charset) + throws IOException { + Path filePath = Paths.get(path); + Files.write(filePath, content.getBytes(charset)); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/HttpSkill.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/HttpSkill.java new file mode 100644 index 0000000000..03ec2ef3ce --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/HttpSkill.java @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.HttpMethod; +import com.azure.core.http.HttpRequest; +import com.azure.core.http.HttpResponse; +import reactor.core.publisher.Mono; + +/** + * A skill that provides HTTP functionality. + * + *

Usage: + * + *

Usage: kernel.importSkill(new HttpSkill(), "http"); + * + *

Examples: + * + *

{{http.getAsync $url}} + * + *

{{http.postAsync $url}} + * + *

{{http.putAsync $url}} + * + *

{{http.deleteAsync $url}} + */ +public class HttpSkill { + + private final HttpClient httpClient; + + public HttpSkill() { + this.httpClient = HttpClient.createDefault(); + } + + public HttpSkill(HttpClient httpClient) { + this.httpClient = httpClient; + } + + /** + * Sends an HTTP GET request to the specified URI and returns body as a string. + * + * @param url The URI to send the request to. + * @return The response body as a string. + */ + public Mono getAsync(String url) { + if (url == null || url.isEmpty()) { + return Mono.error(new IllegalArgumentException("url cannot be `null` or empty")); + } + HttpRequest request = new HttpRequest(HttpMethod.GET, url); + return httpClient.send(request).flatMap(response -> response.getBodyAsString()); + } + + /** + * Sends an HTTP POST request to the specified URI and returns body as a string. + * + * @param url The URI to send the request to. + * @param body The response body as a string. + * @return + */ + public Mono postAsync(String url, String body) { + if (url == null || url.isEmpty()) { + return Mono.error(new IllegalArgumentException("url cannot be `null` or empty")); + } + HttpRequest request = new HttpRequest(HttpMethod.POST, url); + request.setBody(body); + return httpClient.send(request).flatMap(response -> response.getBodyAsString()); + } + + /** + * Sends an HTTP PUT request to the specified URI and returns body as a string. + * + * @param url The URI to send the request to. + * @param body The response body as a string. + * @return + */ + public Mono putAsync(String url, String body) { + if (url == null || url.isEmpty()) { + return Mono.error(new IllegalArgumentException("url cannot be `null` or empty")); + } + HttpRequest request = new HttpRequest(HttpMethod.PUT, url); + request.setBody(body); + return httpClient.send(request).flatMap(response -> response.getBodyAsString()); + } + + /** + * Sends an HTTP DELETE request to the specified URI and returns body as a string. + * + * @param url The URI to send the request to. + * @return The response body as a string. + */ + public Mono deleteAsync(String url) { + if (url == null || url.isEmpty()) { + return Mono.error(new IllegalArgumentException("url cannot be `null` or empty")); + } + HttpRequest request = new HttpRequest(HttpMethod.DELETE, url); + return httpClient.send(request).flatMap(response -> Mono.just(response)); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/MathSkill.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/MathSkill.java new file mode 100644 index 0000000000..9c070925ef --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/MathSkill.java @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.math.BigDecimal; + +/** + * MathSkill provides a set of functions to make Math calculations. + * + *

    + *
  • input is the first number in the operation. + *
  • amount is the second number in the operation. + *
+ * + *

Usage: + * + *

+ * + *
+ * kernel.ImportSkill("math", new MathSkill());
+ *
+ * {{math.add}}         => Returns the sum of input and amount
+ * {{math.subtract}}    => Returns the differentce of input from amount
+ * 
+ * + *
+ * + *

This skill uses BigDecimal to perform the number conversion and the calculations. + */ +public class MathSkill { + + /** + * Returns the addition result of input and amount values provided. + * + *

This skill attempts to convert the numbers to BigDecimal and then add them. + * + *

If a conversion error occurs, the skill will throw an exception. + * + * @param input Initial value as string to add the specified amount + * @param amount The amount to be added to input + * @return The resulting sum as a String. + */ + @DefineSKFunction(description = "Adds amount to a value.", name = "add") + public String add( + @SKFunctionInputAttribute(description = "The value to add to.") String input, + @SKFunctionParameters(name = "amount", description = "The amount to be added to value.") + String amount) { + + BigDecimal bValue = new BigDecimal(input); + + return bValue.add(new BigDecimal(amount)).toString(); + } + + /** + * Returns the subtraction result of input and amount values provided. + * + *

This skill attempts to convert the numbers to BigDecimal and then subtract them. + * + *

If a conversion error occurs, the skill will throw an exception. + * + * @param input Initial value as string to subtract the specified amount + * @param amount The amount to be subtracted from input + * @return The resulting difference as a String. + */ + @DefineSKFunction(description = "Subtracts amount from value.", name = "Subtract") + public String subtract( + @SKFunctionInputAttribute(description = "The value to subtract from.") String input, + @SKFunctionParameters( + name = "amount", + description = "The amount to be subtracted from value.") + String amount) { + + BigDecimal bValue = new BigDecimal(input); + + return bValue.subtract(new BigDecimal(amount)).toString(); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/SemanticFunctionConstants.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/SemanticFunctionConstants.java new file mode 100644 index 0000000000..ccd9ee37f8 --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/SemanticFunctionConstants.java @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +class SemanticFunctionConstants { + public static final String SummarizeConversationDefinition = + "BEGIN CONTENT TO SUMMARIZE:\n" + + "{{$INPUT}}\n" + + "\n" + + "END CONTENT TO SUMMARIZE.\n" + + "\n" + + "Summarize the conversation in 'CONTENT TO SUMMARIZE', identifying main points of" + + " discussion and any conclusions that were reached.\n" + + "Do not incorporate other general knowledge.\n" + + "Summary is in plain text, in complete sentences, with no markup or tags.\n" + + "\n" + + "BEGIN SUMMARY:"; + + public static final String GetConversationActionItemsDefinition = + "You are an action item extractor. You will be given chat history and need to make note" + + " of action items mentioned in the chat.\n" + + "Extract action items from the content if there are any. If there are no action," + + " return nothing. If a single field is missing, use an empty string.\n" + + "Return the action items in json.\n" + + "\n" + + "Possible statuses for action items are: Open, Closed, In Progress.\n" + + "\n" + + "EXAMPLE INPUT WITH ACTION ITEMS:\n" + + "\n" + + "John Doe said: \"I will record a demo for the new feature by Friday\"\n" + + "I said: \"Great, thanks John. We may not use all of it but it's good to get it" + + " out there.\"\n" + + "\n" + + "EXAMPLE OUTPUT:\n" + + "{\n" + + " \"actionItems\": [\n" + + " {\n" + + " \"owner\": \"John Doe\",\n" + + " \"actionItem\": \"Record a demo for the new feature\",\n" + + " \"dueDate\": \"Friday\",\n" + + " \"status\": \"Open\",\n" + + " \"notes\": \"\"\n" + + " }\n" + + " ]\n" + + "}\n" + + "\n" + + "EXAMPLE INPUT WITHOUT ACTION ITEMS:\n" + + "\n" + + "John Doe said: \"Hey I'm going to the store, do you need anything?\"\n" + + "I said: \"No thanks, I'm good.\"\n" + + "\n" + + "EXAMPLE OUTPUT:\n" + + "{\n" + + " \"action_items\": []\n" + + "}\n" + + "\n" + + "CONTENT STARTS HERE.\n" + + "\n" + + "{{$INPUT}}\n" + + "\n" + + "CONTENT STOPS HERE.\n" + + "\n" + + "OUTPUT:"; + + public static final String GetConversationTopicsDefinition = + "Analyze the following extract taken from a conversation transcript and extract key" + + " topics.\n" + + "- Topics only worth remembering.\n" + + "- Be brief. Short phrases.\n" + + "- Can use broken English.\n" + + "- Conciseness is very important.\n" + + "- Topics can include names of memories you want to recall.\n" + + "- NO LONG SENTENCES. SHORT PHRASES.\n" + + "- Return in JSON\n" + + "[Input]\n" + + "My name is Macbeth. I used to be King of Scotland, but I died. My wife's name is" + + " Lady Macbeth and we were married for 15 years. We had no children. Our beloved" + + " dog Toby McDuff was a famous hunter of rats in the forest.\n" + + "My tragic story was immortalized by Shakespeare in a play.\n" + + "[Output]\n" + + "{\n" + + " \"topics\": [\n" + + " \"Macbeth\",\n" + + " \"King of Scotland\",\n" + + " \"Lady Macbeth\",\n" + + " \"Dog\",\n" + + " \"Toby McDuff\",\n" + + " \"Shakespeare\",\n" + + " \"Play\",\n" + + " \"Tragedy\"\n" + + " ]\n" + + "}\n" + + "+++++\n" + + "[Input]\n" + + "{{$INPUT}}\n" + + "[Output]"; +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TextMemorySkill.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TextMemorySkill.java new file mode 100644 index 0000000000..3abc41791a --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TextMemorySkill.java @@ -0,0 +1,243 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.memory.MemoryException; +import com.microsoft.semantickernel.memory.MemoryQueryResult; +import com.microsoft.semantickernel.memory.MemoryRecordMetadata; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import reactor.core.publisher.Mono; + +/** + * TextMemorySkill provides a skill to save or recall information from the long or short term. + * Usage: {@code kernel.ImportSkill(new TextMemorySkill(), "memory");} Example: {@code + * {{memory.recall "what is the capital of France?" }} => "Paris"} + */ +public class TextMemorySkill { + + /** Name of the context variable used to specify which memory collection to use. */ + public static final String COLLECTION_PARAM = "collection"; + + /** Name of the context variable used to specify the information to store. */ + public static final String INFO_PARAM = "info"; + + /** Name of the context variable used to specify the input to the skill. */ + public static final String INPUT_PARAM = "input"; + + /** Name of the context variable used to specify memory search relevance score. */ + public static final String RELEVANCE_PARAM = "relevance"; + + /** + * Name of the context variable used to specify a unique key associated with stored information. + */ + public static final String KEY_PARAM = "key"; + + /** Name of the context variable used to specify the number of memories to recall */ + public static final String LIMIT_PARAM = "limit"; + + /** Default value for the collection name. */ + public static final String DEFAULT_COLLECTION = "generic"; + + /** Default value for the relevance score. */ + public static final String DEFAULT_RELEVANCE = "0.75"; + + /** Default value for the limit. */ + public static final String DEFAULT_LIMIT = "1"; + + /** + * Key-based lookup for a specific memory. + * + * @param collection The collection containing the memory to retrieve + * @param key The key associated with the memory to retrieve + * @param context The context containing the semantic memory + * @return The memory associated with the key + */ + @DefineSKFunction(description = "Key-based lookup for a specific memory", name = "Retrieve") + public Mono retrieveAsync( + @SKFunctionParameters( + name = COLLECTION_PARAM, + description = + "Memories collection associated with the memory to retrieve", + defaultValue = DEFAULT_COLLECTION) + String collection, + @SKFunctionParameters( + name = KEY_PARAM, + description = "The key associated with the memory to retrieve") + String key, + SKContext context) { + + SemanticTextMemory memory = context.getSemanticMemory(); + + if (memory == null) { + return Mono.error(new RuntimeException("Memory not present")); + } + + return memory.getAsync(collection, key, false) + .map(it -> it.getMetadata().getText()) + .defaultIfEmpty(""); + } + + /** + * Save information to semantic memory. + * + * @param info The information to save + * @param collection Memories collection associated with the information to save + * @param key The key associated with the information to save + * @param context The context containing the semantic memory + * @return The key associated with the saved information + */ + @DefineSKFunction(description = "Save information to semantic memory", name = "Save") + public Mono saveAsync( + @SKFunctionParameters( + name = INFO_PARAM, + description = "The information to save", + defaultValue = "", + type = String.class) + String info, + @SKFunctionParameters( + name = COLLECTION_PARAM, + description = + "Memories collection associated with the information to save", + defaultValue = DEFAULT_COLLECTION, + type = String.class) + String collection, + @SKFunctionParameters( + name = KEY_PARAM, + description = "The key associated with the information to save", + defaultValue = "", + type = String.class) + String key, + SKContext context) { + + SemanticTextMemory memory = context.getSemanticMemory(); + if (memory == null) { + return Mono.error( + new MemoryException(MemoryException.ErrorCodes.UNKNOWN, "Memory not present")); + } + + return memory.saveInformationAsync(collection, info, key, null, null) + .map( + it -> { + context.setVariable(TextMemorySkill.KEY_PARAM, it); + return SKBuilders.context() + .withVariables(context.getVariables()) + .withSkills(context.getSkills()) + .withMemory(context.getSemanticMemory()) + .build(); + }); + } + + /** + * Semantic search and return up to N memories related to the input text + * + * @param input The input text to find related memories for + * @param collection Memories collection to search + * @param relevance The relevance score, from 0.0 to 1.0, where 1.0 means perfect match + * @param limit The maximum number of relevant memories to recall + * @param context Contains the memory to search + * @return The list of memories related to the input text + */ + @DefineSKFunction( + description = "Semantic search and return up to N memories related to the input text", + name = "Recall") + public Mono> recallAsync( + @SKFunctionParameters( + name = INPUT_PARAM, + description = "The information to recall", + defaultValue = "", + type = String.class) + @Nonnull + String input, + @SKFunctionParameters( + name = COLLECTION_PARAM, + description = + "Memories collection associated with the information to recall", + defaultValue = DEFAULT_COLLECTION, + type = String.class) + String collection, + @SKFunctionParameters( + name = RELEVANCE_PARAM, + description = + "The relevance score, from 0.0 to 1.0, where 1.0 means perfect" + + " match", + defaultValue = DEFAULT_RELEVANCE, + type = Double.class) + double relevance, + @SKFunctionParameters( + name = LIMIT_PARAM, + description = "The maximum number of relevant memories to recall", + defaultValue = DEFAULT_LIMIT, + type = Integer.class) + int limit, + @Nonnull SKContext context) { + + SemanticTextMemory memory = context.getSemanticMemory(); + if (memory == null) { + return Mono.error( + new MemoryException(MemoryException.ErrorCodes.UNKNOWN, "Memory not present")); + } + + // Validate parameters + if (collection == null || collection.trim().isEmpty()) { + collection = context.getVariables().get(TextMemorySkill.COLLECTION_PARAM); + if (collection == null) collection = DEFAULT_COLLECTION; + } + final String _collection = collection; + final float _relevance = (float) Math.min(1.0, Math.max(0.0, relevance)); + final int _limit = Math.max(1, limit); + + // context.Log.LogTrace("Searching memories in collection '{0}', relevance '{1}'", + // collection, relevance); + + // Search memory + return memory.searchAsync(_collection, input, _limit, _relevance, false) + .flatMap( + results -> { + List memories = + results.stream() + .map(MemoryQueryResult::getMetadata) + .map(MemoryRecordMetadata::getText) + .collect(Collectors.toList()); + return Mono.just(memories); + }); + } + + /** + * Remove information from semantic memory + * + * @param collection Memories collection associated with the information to remove + * @param key The key associated with the information to remove + * @param context Contains the memory to remove + * @return The reactive stream + */ + @DefineSKFunction(description = "Remove information from semantic memory", name = "Remove") + public Mono removeAsync( + @SKFunctionParameters( + name = COLLECTION_PARAM, + description = + "Memories collection associated with the information to remove", + defaultValue = DEFAULT_COLLECTION, + type = String.class) + String collection, + @SKFunctionParameters( + name = KEY_PARAM, + description = "The key associated with the information to remove", + defaultValue = "", + type = String.class) + String key, + SKContext context) { + SemanticTextMemory memory = context.getSemanticMemory(); + if (memory == null) { + return Mono.error( + new MemoryException(MemoryException.ErrorCodes.UNKNOWN, "Memory not present")); + } + + return memory.removeAsync(collection, key); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TextSkill.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TextSkill.java new file mode 100644 index 0000000000..39221001d7 --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TextSkill.java @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import java.util.Locale; + +/** TextSkill provides a set of functions to manipulate strings. */ +public class TextSkill { + + @DefineSKFunction(description = "Change all string chars to uppercase.", name = "Uppercase") + public String uppercase( + @SKFunctionInputAttribute(description = "Text to uppercase") String text) { + return text.toUpperCase(Locale.ROOT); + } + + @DefineSKFunction(description = "Remove spaces to the left of a string.", name = "LStrip") + public String lStrip(@SKFunctionInputAttribute(description = "Text to edit") String text) { + return text.replaceAll("^ +", ""); + } + + @DefineSKFunction(description = "Remove spaces to the right of a string.", name = "RStrip") + public String rStrip(@SKFunctionInputAttribute(description = "Text to edit") String text) { + return text.replaceAll(" +$", ""); + } + + @DefineSKFunction( + description = "Remove spaces to the left and right of a string", + name = "Strip") + public String strip(@SKFunctionInputAttribute(description = "Text to edit") String input) { + return input.trim(); + } + + @DefineSKFunction(description = "Change all string chars to lowercase", name = "lowercase") + public String lowercase( + @SKFunctionInputAttribute(description = "Text to lowercase") String input) { + return input.toLowerCase(Locale.ROOT); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TimeSkill.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TimeSkill.java new file mode 100644 index 0000000000..14b97deea2 --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/TimeSkill.java @@ -0,0 +1,428 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import com.microsoft.semantickernel.util.LocaleParser; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.TextStyle; +import java.util.Locale; + +/** + * Description: TimeSkill provides a set of functions to get the current time and date. + * + *

Usage: kernel.importSkill(new TimeSkill(), "time"); + * + *

Examples: + * + *

{{time.date}} => Sunday, 12 January, 2031 + * + *

{{time.today}} => Sunday, 12 January, 2031 + * + *

{{time.now}} => Sunday, January 12, 2031 9:15 PM + * + *

{{time.utcNow}} => Sunday, January 13, 2031 5:15 AM + * + *

{{time.time}} => 09:15:07 PM + * + *

{{time.year}} => 2031 + * + *

{{time.month}} => January + * + *

{{time.monthNumber}} => 01 + * + *

{{time.day}} => 12 + * + *

{{time.dayOfWeek}} => Sunday + * + *

{{time.hour}} => 9 PM + * + *

{{time.hourNumber}} => 21 + * + *

{{time.days_ago $days}} => Sunday, 7 May, 2023 + * + *

{{time.last_matching_day $dayName}} => Sunday, 7 May, 2023 + * + *

{{time.minute}} => 15 + * + *

{{time.second}} => 7 + * + *

{{time.timeZoneOffset}} => -08:00 + * + *

{{time.timeZoneName}} => Pacific Time + */ +public class TimeSkill { + + public static final String DAY_MONTH_DAY_YEAR = "EEEE, MMMM d, yyyy"; + + /** + * Get the current date and time for the system default timezone. + * + * @return a ZonedDateTime object with the current date and time. + */ + public ZonedDateTime now() { + return ZonedDateTime.now(ZoneId.systemDefault()); + } + + /** + * Get the current date. + * + *

Example: {{time.date}} => Sunday, January 12, 2025 + * + * @return The current date. + */ + @DefineSKFunction(name = "date", description = "Get the current date") + public String date( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + // Example: Sunday, 12 January, 2025 + return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR) + .withLocale(parseLocale(locale)) + .format(now()); + } + + /** + * Get the current time. + * + *

Example: {{time.time}} => 9:15:00 AM + * + * @return The current time. + */ + @DefineSKFunction(name = "time", description = "Get the current time") + public String time( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + // Example: 09:15:07 PM + return DateTimeFormatter.ofPattern("hh:mm:ss a") + .withLocale(parseLocale(locale)) + .format(now()); + } + + /** + * Get the current UTC date and time. + * + *

Example: {{time.utcNow}} => Sunday, January 13, 2025 5:15 AM + * + * @return The current UTC date and time. + */ + @DefineSKFunction(name = "utcNow", description = "Get the current UTC date and time") + public String utcNow( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR + " h:mm a") + .withLocale(parseLocale(locale)) + .format(now().withZoneSameInstant(ZoneOffset.UTC)); + } + + /** + * Get the current date (alias for date() method). + * + *

Example: {{time.today}} => Sunday, January 12, 2025 + * + * @return The current date. + */ + @DefineSKFunction(name = "today", description = "Get the current date") + public String today( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return date(locale); + } + + /** + * Get the current date and time in the local time zone. + * + *

Example: {{time.now}} => Sunday, January 12, 2025 9:15 AM + * + * @return The current date and time in the local time zone. + */ + @DefineSKFunction( + name = "now", + description = "Get the current date and time in the local time zone") + public String now( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR + " h:mm a") + .withLocale(parseLocale(locale)) + .format(now()); + } + + /** + * Get the current year. + * + *

Example: {{time.year}} => 2025 + * + * @return The current year. + */ + @DefineSKFunction(name = "year", description = "Get the current year") + public String year( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("yyyy").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the current month name. + * + *

Example: {{time.month}} => January + * + * @return The current month name. + */ + @DefineSKFunction(name = "month", description = "Get the current month name") + public String month( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("MMMM").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the current month number. + * + *

Example: {{time.monthNumber}} => 01 + * + * @return The current month number. + */ + @DefineSKFunction(name = "monthNumber", description = "Get the current month number") + public String monthNumber( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("MM").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the current day of the month. + * + *

Example: {{time.day}} => 12 + * + * @return The current day of the month. + */ + @DefineSKFunction(name = "day", description = "Get the current day of the month") + public String day( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("d").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the current day of the week. + * + *

Example: {{time.dayOfWeek}} => Sunday + * + * @return The current day of the week. + */ + @DefineSKFunction(name = "dayOfWeek", description = "Get the current day of the week") + public String dayOfWeek( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("EEEE").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the current clock hour. + * + *

Example: {{time.hour}} => 9 AM + * + * @return The current clock hour. + */ + @DefineSKFunction(name = "hour", description = "Get the current clock hour") + public String hour( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("h a").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the current clock 24-hour number. + * + *

Example: {{time.hourNumber}} => 09 + * + * @return The current clock 24-hour number. + */ + @DefineSKFunction(name = "hourNumber", description = "Get the current clock 24-hour number") + public String hourNumber( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("HH").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the date of offset from today by a provided number of days + * + *

Example: SKContext context = SKBuilders.context().build(); context.setVariable("input", + * "3"); {{time.daysAgo $input}} => Saturday, January 11, 2031 + * + * @param days Number of days to subtract from the current day + * @return The date of offset from today by a provided number of days + */ + @DefineSKFunction( + name = "daysAgo", + description = "Get the date of offset from today by a provided number of days") + public String daysAgo( + @SKFunctionInputAttribute(description = "Number of days to offset from today.") + String days, + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + int offsetDays = Integer.parseInt(days); + return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR) + .withLocale(parseLocale(locale)) + .format(now().minusDays(offsetDays)); + } + + /** + * Get the date of the last day matching the supplied week day name + * + *

Example: {{time.dateMatchingLastDayName "Monday"}} => Monday, January 6, 2031 + * + * @param dayName Name of the day to match + * @return The date of the last day matching the supplied week day name + */ + @DefineSKFunction( + name = "dateMatchingLastDayName", + description = "Get the date of the last day matching the supplied week day name") + public String dateMatchingLastDayName( + @SKFunctionInputAttribute(description = "Week name day.") String dayName, + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + ZonedDateTime currentDate = now(); + for (int i = 1; i <= 7; i++) { + currentDate = currentDate.minusDays(1); + String currentDayName = + currentDate.getDayOfWeek().getDisplayName(TextStyle.FULL, parseLocale(locale)); + + if (currentDayName.equalsIgnoreCase(dayName)) { + return DateTimeFormatter.ofPattern(DAY_MONTH_DAY_YEAR) + .withLocale(parseLocale(locale)) + .format(currentDate); + } + } + throw new IllegalArgumentException("dayName is not recognized"); + } + + /** + * Get the minutes on the current hour. + * + *

Example: {{time.minute}} => 15 + * + * @return The minutes on the current hour. + */ + @DefineSKFunction(name = "minute", description = "Get the minutes on the current hour") + public String minute( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("mm").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the seconds on the current minute. + * + *

Example: {{time.second}} => 00 + * + * @return The seconds on the current minute. + */ + @DefineSKFunction(name = "second", description = "Get the seconds on the current minute") + public String second( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("ss").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the local time zone offset from UTC. + * + *

Example: {{time.timeZoneOffset}} => +03:00 + * + * @return The local time zone offset from UTC. + */ + @DefineSKFunction( + name = "timeZoneOffset", + description = "Get the local time zone offset from UTC") + public String timeZoneOffset( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + return DateTimeFormatter.ofPattern("XXX").withLocale(parseLocale(locale)).format(now()); + } + + /** + * Get the local time zone name. + * + *

Example: {{time.timeZoneName}} => Pacific Time + * + * @return The local time zone name. + */ + @DefineSKFunction(name = "timeZoneName", description = "Get the local time zone name") + public String timeZoneName( + @SKFunctionParameters( + name = "locale", + description = "Locale to use when formatting the date", + required = false) + String locale) { + ZoneId zoneId = ZoneId.systemDefault(); + return zoneId.getDisplayName(TextStyle.FULL, parseLocale(locale)); + } + + /** + * Parse the locale string into a Locale object. + * + *

By default, it parses using the LocaleParser utility class. + * + * @param locale string + * @return a locale object + */ + protected Locale parseLocale(String locale) { + return LocaleParser.parseLocale(locale); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/WaitSkill.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/WaitSkill.java new file mode 100644 index 0000000000..64070abc4d --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/coreskills/WaitSkill.java @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import java.time.Duration; +import reactor.core.publisher.Mono; + +/** WaitSkill provides a set of functions to wait before making the rest of operations. */ +public class WaitSkill { + + /** + * Wait for a certain number of seconds. + * + *

Examples: + * + *

SKContext context = SKBuilders.context().build(); + * + *

context.setVariable("input","10"); + * + *

{{wait.seconds $input}} + * + * @param seconds The number of seconds to wait as a string. + * @return A Mono that completes after the specified delay. + * @throws IllegalArgumentException If the input is not a valid number. + */ + @DefineSKFunction(name = "seconds", description = "Wait a given amount of seconds") + public Mono wait(String seconds) { + try { + double sec = Math.max(Double.parseDouble(seconds), 0); + long milliseconds = (long) (sec * 1000); + return Mono.delay(Duration.ofMillis(milliseconds)).then(); + } catch (NumberFormatException e) { + return Mono.error(new IllegalArgumentException("seconds text must be a number", e)); + } + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/text/TextChunker.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/text/TextChunker.java new file mode 100644 index 0000000000..0d9a6dfdfc --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/text/TextChunker.java @@ -0,0 +1,296 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.text; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Split text in chunks, attempting to leave meaning intact. For plain text, split looking at new + * lines first, then periods, and so on. For markdown, split looking at punctuation first, and so + * on. + */ +public class TextChunker { + private static final String s_spaceChar = " "; + private static final List s_plaintextSplitOptions = + Stream.of("[\n\r]", "\\.", "[\\?\\!]", ";", ":", ",", "[\\)\\]\\}]", " ", "\\-", null) + .map(it -> it == null ? null : Pattern.compile(it, Pattern.MULTILINE)) + .collect(Collectors.toList()); + + private static final List s_markdownSplitOptions = + Stream.of("\\.", "[\\?\\!]", ";", ":", ",", "[\\)\\]\\}]", " ", "\\-", "[\n\r]", null) + .map(it -> it == null ? null : Pattern.compile(it, Pattern.MULTILINE)) + .collect(Collectors.toList()); + + /** + * Split plain text into lines + * + * @param text Text to split + * @param maxTokensPerLine Maximum number of tokens per line + * @return List of lines + */ + public static List splitPlainTextLines(String text, int maxTokensPerLine) { + return internalSplitLines(text, maxTokensPerLine, true, s_plaintextSplitOptions); + } + + /** + * Split markdown text into lines + * + * @param text Text to split + * @param maxTokensPerLine Maximum number of tokens per line + * @return List of lines + */ + public static List splitMarkDownLines(String text, int maxTokensPerLine) { + List result = new ArrayList<>(); + internalSplitLines(text, maxTokensPerLine, true, s_markdownSplitOptions); + return result; + } + + /** + * Split plain text into paragraphs + * + * @param lines Lines of text + * @param maxTokensPerParagraph Maximum number of tokens per paragraph. + * @return List of paragraphs + */ + public static List splitPlainTextParagraphs( + List lines, int maxTokensPerParagraph) { + return internalSplitTextParagraphs( + lines, + maxTokensPerParagraph, + (text) -> + internalSplitLines( + text, maxTokensPerParagraph, false, s_plaintextSplitOptions)); + } + + /** + * Split markdown text into paragraphs + * + * @param lines Lines of text + * @param maxTokensPerParagraph Maximum number of tokens per paragraph + * @return List of paragraphs + */ + public static List splitMarkdownParagraphs( + List lines, int maxTokensPerParagraph) { + return internalSplitTextParagraphs( + lines, + maxTokensPerParagraph, + (text) -> + internalSplitLines( + text, maxTokensPerParagraph, false, s_markdownSplitOptions)); + } + + private static List internalSplitTextParagraphs( + List lines, + int maxTokensPerParagraph, + Function> longLinesSplitter) { + if (lines.size() == 0) { + return new ArrayList<>(); + } + + // Split long lines first + ArrayList truncatedLines = new ArrayList<>(); + for (String line : lines) { + truncatedLines.addAll(longLinesSplitter.apply(line)); + } + + lines = truncatedLines; + + // Group lines in paragraphs + List paragraphs = new ArrayList<>(); + StringBuilder currentParagraph = new StringBuilder(); + + for (String line : lines) { + // "+1" to account for the "new line" added by AppendLine() + if (currentParagraph.length() > 0 + && TokenCount(currentParagraph.length()) + TokenCount(line.length()) + 1 + >= maxTokensPerParagraph) { + paragraphs.add(currentParagraph.toString().trim()); + currentParagraph = new StringBuilder(); + } + + currentParagraph.append(line).append("\n"); + } + + if (currentParagraph.length() > 0) { + paragraphs.add(currentParagraph.toString().trim()); + } + + // distribute text more evenly in the last paragraphs when the last paragraph is too short. + if (paragraphs.size() > 1) { + String lastParagraph = paragraphs.get(paragraphs.size() - 1); + String secondLastParagraph = paragraphs.get(paragraphs.size() - 2); + + if (TokenCount(lastParagraph.length()) < maxTokensPerParagraph / 4) { + List lastParagraphTokens = + Arrays.stream(lastParagraph.split(s_spaceChar)) + .filter(it -> it.length() != 0) + .collect(Collectors.toList()); + List secondLastParagraphTokens = + Arrays.stream(secondLastParagraph.split(s_spaceChar)) + .filter(it -> it.length() != 0) + .collect(Collectors.toList()); + + int lastParagraphTokensCount = lastParagraphTokens.size(); + int secondLastParagraphTokensCount = secondLastParagraphTokens.size(); + + if (lastParagraphTokensCount + secondLastParagraphTokensCount + <= maxTokensPerParagraph) { + StringBuilder newSecondLastParagraph = new StringBuilder(); + for (int i = 0; i < secondLastParagraphTokensCount; i++) { + if (newSecondLastParagraph.length() != 0) { + newSecondLastParagraph.append(' '); + } + + newSecondLastParagraph.append(secondLastParagraphTokens.get(i)); + } + + for (int i = 0; i < lastParagraphTokensCount; i++) { + if (newSecondLastParagraph.length() != 0) { + newSecondLastParagraph.append(' '); + } + + newSecondLastParagraph.append(lastParagraphTokens.get(i)); + } + + paragraphs.set(paragraphs.size() - 2, newSecondLastParagraph.toString().trim()); + paragraphs.remove(paragraphs.size() - 1); + } + } + } + + return paragraphs; + } + + private static class SplitString { + public final boolean inputWasSplit; + public final List result; + + private SplitString(boolean inputWasSplit, List result) { + this.inputWasSplit = inputWasSplit; + this.result = result; + } + } + + private static List internalSplitLines( + String text, int maxTokensPerLine, boolean trim, List splitOptions) { + text = text.replaceAll("\\r?\\n|\\r", "\n"); + + SplitString result = + split(text, maxTokensPerLine, Collections.singletonList(splitOptions.get(0)), trim); + if (result.inputWasSplit) { + for (int i = 1; i < splitOptions.size(); i++) { + result = + split( + result.result, + maxTokensPerLine, + Collections.singletonList(splitOptions.get(i)), + trim); + + if (!result.inputWasSplit) { + break; + } + } + } + return result.result; + } + + private static SplitString split( + List input, int maxTokens, List separators, boolean trim) { + List result = new ArrayList<>(); + boolean modified = false; + for (String str : input) { + SplitString r = split(str, maxTokens, separators, trim); + result.addAll(r.result); + + modified |= r.inputWasSplit; + } + return new SplitString(modified, result); + } + + private static int indexOfAny(List separators, String input) { + return separators.stream() + .map( + it -> { + Matcher matcher = it.matcher(input); + if (matcher.find()) { + return matcher.start(); + } else { + return -1; + } + }) + .filter(it -> it != -1) + .min(Integer::compareTo) + .orElse(-1); + } + + private static SplitString split( + String input, int maxTokens, List separators, boolean trim) { + // Debug.Assert(inputString is null || input.SequenceEqual(inputString.AsSpan())); + boolean inputWasSplit; + if (TokenCount(input.length()) > maxTokens) { + + inputWasSplit = true; + + int half = input.length() / 2; + int cutPoint = -1; + + if (separators.size() == 1 && separators.get(0) == null) { + cutPoint = half; + } else if (input.length() > 2) { + int pos = 0; + while (true) { + int index = indexOfAny(separators, input.substring(pos, input.length() - 1)); + if (index < 0) { + break; + } + + index += pos; + + if (Math.abs(half - index) < Math.abs(half - cutPoint)) { + cutPoint = index + 1; + } + + pos = index + 1; + } + } + + List result = Collections.singletonList(input); + + if (cutPoint > 0) { + String firstHalf = input.substring(0, cutPoint); + String secondHalf = input.substring(cutPoint); + if (trim) { + firstHalf = firstHalf.trim(); + secondHalf = secondHalf.trim(); + } + + // Recursion + SplitString first = split(firstHalf, maxTokens, separators, trim); + SplitString second = split(secondHalf, maxTokens, separators, trim); + + result = + Stream.concat(first.result.stream(), second.result.stream()) + .collect(Collectors.toList()); + inputWasSplit = first.inputWasSplit || second.inputWasSplit; + } + + return new SplitString(inputWasSplit, result); + } + + return new SplitString(false, Collections.singletonList(input)); + } + + private static int TokenCount(int inputLength) { + // TODO: partitioning methods should be configurable to allow for different tokenization + // strategies + // depending on the model to be called. For now, we use an extremely rough estimate. + return inputLength / 4; + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/util/LocaleParser.java b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/util/LocaleParser.java new file mode 100644 index 0000000000..84104aab0e --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/main/java/com/microsoft/semantickernel/util/LocaleParser.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.util; + +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.util.Locale; + +/** + * Locale parser to support Java 8 and Java 9+ due to JEP 252. + * + *

Supports parsing strings containing languageCode_countryCode and languageCode-countryCode + * styles. + */ +public final class LocaleParser { + + private LocaleParser() {} + + /** + * Parses the locale. If the input is "en-US", it will return a Locale based on the language + * tag. If the input is "en_US", it will return a Locale based on the language and country code. + * Otherwise, it will return a Locale based on the input. + * + *

'en' 'US' used as example above. + * + * @param locale the locale in String text. + * @return + */ + public static final Locale parseLocale(String locale) { + Locale parsedLocale = null; + + if (locale == null + || "".equals(locale.trim()) + || SKFunctionParameters.NO_DEFAULT_VALUE.equals(locale)) { + return Locale.getDefault(); + } else if (locale.indexOf("-") > -1) { + parsedLocale = Locale.forLanguageTag(locale); + } else if (locale.indexOf("_") > -1) { + String[] parts = locale.split("_"); + parsedLocale = new Locale(parts[0], parts[1]); + } else { + parsedLocale = new Locale(locale); + } + + return parsedLocale; + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/FileIOSkillTest.java b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/FileIOSkillTest.java new file mode 100644 index 0000000000..ffc35904c6 --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/FileIOSkillTest.java @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class FileIOSkillTest { + + @Test + public void testReadFileAsync() throws IOException { + // Create a temporary file with some content + String content = "Hello, World!"; + Path tempFile = Files.createTempFile("test", ".txt"); + Files.write(tempFile, content.getBytes(StandardCharsets.UTF_8)); + + // Create an instance of FileIOSkill + FileIOSkill fileIOSkill = new FileIOSkill(); + + // Call the readFileAsync method with the temporary file path + String filePath = tempFile.toAbsolutePath().toString(); + String outcome = fileIOSkill.readFileAsync(filePath, "UTF-8"); + + // Assert content (expected) is the same as the outcome (actual) + Assertions.assertEquals(content, outcome); + + // Delete the temporary file + Files.delete(tempFile); + } + + @Test + public void testWriteFileAsync() throws IOException { + // Create a temporary file + Path tempFile = Files.createTempFile("test", ".txt"); + + // Create an instance of FileIOSkill + FileIOSkill fileIOSkill = new FileIOSkill(); + + // Define the content to write + String content = "Hello, World!"; + + // Call the writeFileAsync method with the temporary file path and content + fileIOSkill.writeFileAsync(tempFile.toAbsolutePath().toString(), content, "UTF-8"); + + // Read the written file to verify the content + String fileContents = new String(Files.readAllBytes(tempFile), StandardCharsets.UTF_8); + Assertions.assertEquals(content, fileContents); + + // Delete the temporary file + Files.delete(tempFile); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/HttpSkillTest.java b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/HttpSkillTest.java new file mode 100644 index 0000000000..2d14c7f837 --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/HttpSkillTest.java @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.HttpRequest; +import com.azure.core.http.HttpResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +public class HttpSkillTest { + + private HttpSkill httpSkill; + + @Mock private HttpClient httpClient; + + @Mock private HttpResponse httpResponse; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + httpSkill = new HttpSkill(httpClient); + } + + @Test + public void testGetAsync() { + String url = "https://example.com"; + String responseBody = "Response body"; + when(httpResponse.getBodyAsString()).thenReturn(Mono.just(responseBody)); + when(httpClient.send(any(HttpRequest.class))).thenReturn(Mono.just(httpResponse)); + Mono responseMono = httpSkill.getAsync(url); + StepVerifier.create(responseMono).expectNext(responseBody).verifyComplete(); + } + + @Test + public void testPostAsync() { + String url = "https://example.com"; + String body = "{\"key\": \"value\"}"; + String responseBody = "Response body"; + when(httpResponse.getBodyAsString()).thenReturn(Mono.just(responseBody)); + when(httpClient.send(any(HttpRequest.class))).thenReturn(Mono.just(httpResponse)); + Mono responseMono = httpSkill.postAsync(url, body); + StepVerifier.create(responseMono).expectNext(responseBody).verifyComplete(); + } + + @Test + public void testPutAsync() { + String url = "https://example.com"; + String body = "{\"key\": \"value\"}"; + String responseBody = "Response body"; + when(httpResponse.getBodyAsString()).thenReturn(Mono.just(responseBody)); + when(httpClient.send(any(HttpRequest.class))).thenReturn(Mono.just(httpResponse)); + Mono responseMono = httpSkill.putAsync(url, body); + StepVerifier.create(responseMono).expectNext(responseBody).verifyComplete(); + } + + @Test + public void testDeleteAsync() { + String url = "https://example.com"; + when(httpClient.send(any(HttpRequest.class))).thenReturn(Mono.just(httpResponse)); + Mono responseMono = httpSkill.deleteAsync(url); + StepVerifier.create(responseMono).expectNext(httpResponse).verifyComplete(); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/MathSkillTest.java b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/MathSkillTest.java new file mode 100644 index 0000000000..9d5efbbcec --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/MathSkillTest.java @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class MathSkillTest { + + @Test + public void testAddition() { + MathSkill mathSkill = new MathSkill(); + String result = mathSkill.add("1", "2"); + assertEquals("3", result); + } + + @Test + public void testSubtraction() { + MathSkill mathSkill = new MathSkill(); + String result = mathSkill.subtract("1", "2"); + assertEquals("-1", result); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/TimeSkillTest.java b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/TimeSkillTest.java new file mode 100644 index 0000000000..e7e9cce077 --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/TimeSkillTest.java @@ -0,0 +1,145 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Locale; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +@SuppressWarnings("ReturnValueIgnored") +public class TimeSkillTest { + + private static final String defaultLocale = "en-US"; + + private static final ZonedDateTime mockDateTime; + + static { + mockDateTime = ZonedDateTime.of(2025, 1, 12, 9, 15, 7, 0, ZoneId.systemDefault()); + } + + private TimeSkill timeSkill; + + @BeforeEach + public void setUp() { + timeSkill = spy(new TimeSkill()); + when(timeSkill.now()).thenReturn(mockDateTime); + } + + @Test + public void testDate() { + String result = timeSkill.date(defaultLocale); + assertEquals("Sunday, January 12, 2025", result); + } + + @Test + public void testTime() { + String result = timeSkill.time(defaultLocale); + assertEqualsIgnoreCase("09:15:07 AM", result); + } + + @Test + public void testToday() { + String result = timeSkill.today(defaultLocale); + assertEquals("Sunday, January 12, 2025", result); + } + + @Test + public void testNow() { + String result = timeSkill.now(defaultLocale); + assertEqualsIgnoreCase("Sunday, January 12, 2025 9:15 AM", result); + } + + @Test + public void testYear() { + String result = timeSkill.year(defaultLocale); + assertEquals("2025", result); + } + + @Test + public void testMonth() { + String result = timeSkill.month(defaultLocale); + assertEquals("January", result); + } + + @Test + public void testMonthNumber() { + String result = timeSkill.monthNumber(defaultLocale); + assertEquals("01", result); + } + + @Test + public void testDay() { + String result = timeSkill.day(defaultLocale); + assertEquals("12", result); + } + + @Test + public void testDayOfWeek() { + String result = timeSkill.dayOfWeek(defaultLocale); + assertEquals("Sunday", result); + } + + @Test + public void testHour() { + String result = timeSkill.hour(defaultLocale); + assertEqualsIgnoreCase("9 AM", result); + } + + @Test + public void testHourNumber() { + String result = timeSkill.hourNumber(defaultLocale); + assertEquals("09", result); + } + + @Test + public void testMinute() { + String result = timeSkill.minute(defaultLocale); + assertEquals("15", result); + } + + @Test + public void testSecond() { + String result = timeSkill.second(defaultLocale); + assertEquals("07", result); + } + + @Test + public void daysAgo() { + assertEquals("Thursday, January 9, 2025", timeSkill.daysAgo("3", defaultLocale)); + assertEquals("Tuesday, January 7, 2025", timeSkill.daysAgo("5", defaultLocale)); + } + + @Test + public void testDateMatchingLastDayName() { + assertEquals( + "Sunday, January 5, 2025", + timeSkill.dateMatchingLastDayName("Sunday", defaultLocale)); + assertEquals( + "Monday, January 6, 2025", + timeSkill.dateMatchingLastDayName("Monday", defaultLocale)); + assertEquals( + "Tuesday, January 7, 2025", + timeSkill.dateMatchingLastDayName("Tuesday", defaultLocale)); + assertEquals( + "Wednesday, January 8, 2025", + timeSkill.dateMatchingLastDayName("wednesday", defaultLocale)); + assertEquals( + "Thursday, January 9, 2025", + timeSkill.dateMatchingLastDayName("thursday", defaultLocale)); + assertEquals( + "Friday, January 10, 2025", + timeSkill.dateMatchingLastDayName("Friday", defaultLocale)); + assertEquals( + "Saturday, January 11, 2025", + timeSkill.dateMatchingLastDayName("Saturday", defaultLocale)); + } + + public void assertEqualsIgnoreCase(String a, String b) { + Assertions.assertEquals(a.toUpperCase(Locale.ROOT), b.toUpperCase(Locale.ROOT)); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/WaitSkillTest.java b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/WaitSkillTest.java new file mode 100644 index 0000000000..dd22eb0c9a --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/coreskills/WaitSkillTest.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import java.time.Duration; +import org.junit.jupiter.api.Test; +import reactor.test.StepVerifier; + +class WaitSkillTest { + + WaitSkill waitSkill = new WaitSkill(); + + @Test + void secondsAsync_givenPositiveSeconds_shouldDelay() { + Duration expectedDelay = Duration.ofMillis(1500); + + String seconds = "1.5"; + StepVerifier.withVirtualTime(() -> waitSkill.wait(seconds)) + .expectSubscription() + .expectNoEvent(expectedDelay) + .expectComplete() + .verify(); + } + + @Test + void secondsAsync_givenZeroSeconds_shouldNotDelay() { + String seconds = "0"; + StepVerifier.withVirtualTime(() -> waitSkill.wait(seconds)) + .expectSubscription() + .expectComplete() + .verify(); + } + + @Test + void secondsAsync_givenNegativeSeconds_shouldNotDelay() { + String seconds = "-1.5"; + StepVerifier.withVirtualTime(() -> waitSkill.wait(seconds)) + .expectSubscription() + .expectComplete() + .verify(); + } +} diff --git a/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/text/TextChunkerTest.java b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/text/TextChunkerTest.java new file mode 100644 index 0000000000..dcfb44189a --- /dev/null +++ b/java/plugins/semantickernel-plugin-core/src/test/java/com/microsoft/semantickernel/text/TextChunkerTest.java @@ -0,0 +1,363 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.text; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TextChunkerTest { + + @Test + public void canSplitPlainTextLines() { + String input = "This is a test of the emergency broadcast system. This is only a test."; + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system.", + "This is only a test."); + + List result = TextChunker.splitPlainTextLines(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitPlainTextLinesWithComma() { + String input = "This is a test, of the emergency broadcast system. This is only a test."; + List expected = + Arrays.asList( + "This is a test,", + "of the emergency broadcast system.", + "This is only a test."); + + List result = TextChunker.splitPlainTextLines(input, 10); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitPlainTextLinesLongString() { + String input = + "This is a very very very very very very long string with nothing to split on."; + List expected = + Arrays.asList( + "This is a very very very very very very", + "long string with nothing to split on."); + + List result = TextChunker.splitPlainTextLines(input, 10); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitPlainTextLinesLongStringWithSmallTokenCount() { + String input = + "This is a very very very very very very very very very very very long string."; + List expected = + Arrays.asList( + "This is a", + "very very", + "very very", + "very very", + "very very", + "very very", + "very long", + "string."); + + List result = TextChunker.splitPlainTextLines(input, 2); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitPlainTextLinesNoSeparator() { + String input = "Thisisaveryveryveryveryveryverylongstringwithnothingtospliton"; + List expected = + Arrays.asList("Thisisaveryveryveryveryveryver", "ylongstringwithnothingtospliton"); + + List result = TextChunker.splitPlainTextLines(input, 10); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitMarkdownParagraphs() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system. This is only a test.", + "We repeat, this is only a test. A unit test."); + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system.", + "This is only a test.", + "We repeat, this is only a test. A unit test."); + + List result = TextChunker.splitMarkdownParagraphs(input, 13); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphs() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system. This is only a test.", + "We repeat, this is only a test. A unit test."); + + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system.", + "This is only a test.", + "We repeat, this is only a test. A unit test."); + + List result = TextChunker.splitPlainTextParagraphs(input, 13); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitMarkdownParagraphsWithEmptyInput() { + List input = Collections.emptyList(); + + List expected = Collections.emptyList(); + + List result = TextChunker.splitMarkdownParagraphs(input, 13); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsEvenly() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system. This is only a test.", + "We repeat, this is only a test. A unit test.", + "A small note. And another. And once again. Seriously, this is the end." + + " We're finished. All set. Bye.", + "Done."); + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system.", + "This is only a test.", + "We repeat, this is only a test. A unit test.", + "A small note. And another. And once again.", + "Seriously, this is the end. We're finished. All set. Bye. Done."); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsOnNewlines() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system\r\nThis is only a test", + "We repeat this is only a test\nA unit test", + "A small note\n" + + "And another\r\n" + + "And once again\r" + + "Seriously this is the end\n" + + "We're finished\n" + + "All set\n" + + "Bye\n", + "Done"); + + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system", + "This is only a test", + "We repeat this is only a test\nA unit test", + "A small note\nAnd another\nAnd once again", + "Seriously this is the end\nWe're finished\nAll set\nBye Done"); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsOnPunctuation() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system. This is only a test", + "We repeat, this is only a test? A unit test", + "A small note! And another? And once again! Seriously, this is the end." + + " We're finished. All set. Bye.", + "Done."); + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system.", + "This is only a test", + "We repeat, this is only a test? A unit test", + "A small note! And another? And once again!", + "Seriously, this is the end.", + "We're finished. All set. Bye.\nDone."); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsOnSemicolons() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system; This is only a test", + "We repeat; this is only a test; A unit test", + "A small note; And another; And once again; Seriously, this is the end;" + + " We're finished; All set; Bye.", + "Done."); + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system;", + "This is only a test", + "We repeat; this is only a test; A unit test", + "A small note; And another; And once again;", + "Seriously, this is the end; We're finished; All set; Bye. Done."); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsOnColons() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system: This is only a test", + "We repeat: this is only a test: A unit test", + "A small note: And another: And once again: Seriously, this is the end:" + + " We're finished: All set: Bye.", + "Done."); + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system:", + "This is only a test", + "We repeat: this is only a test: A unit test", + "A small note: And another: And once again:", + "Seriously, this is the end: We're finished: All set: Bye. Done."); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsOnCommas() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system, This is only a test", + "We repeat, this is only a test, A unit test", + "A small note, And another, And once again, Seriously, this is the end," + + " We're finished, All set, Bye.", + "Done."); + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system,", + "This is only a test", + "We repeat, this is only a test, A unit test", + "A small note, And another, And once again, Seriously,", + "this is the end, We're finished, All set, Bye." + "\n" + "Done."); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsOnClosingBrackets() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system) This is only a test", + "We repeat) this is only a test) A unit test", + "A small note] And another) And once again] Seriously this is the end}" + + " We're finished} All set} Bye.", + "Done."); + + List expected = + Arrays.asList( + "This is a test of the emergency broadcast system)", + "This is only a test", + "We repeat) this is only a test) A unit test", + "A small note] And another) And once again]", + "Seriously this is the end} We're finished} All set} Bye. Done."); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsOnHyphens() { + List input = + Arrays.asList( + "This is a test of the emergency broadcast system-This is only a test", + "We repeat-this is only a test-A unit test", + "A small note-And another-And once again-Seriously, this is the end-We're" + + " finished-All set-Bye.", + "Done."); + List expected = + Arrays.asList( + "This is a test of the emergency", + "broadcast system-This is only a test", + "We repeat-this is only a test-A unit test", + "A small note-And another-And once again-Seriously,", + "this is the end-We're finished-All set-Bye." + "\n" + "Done."); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitTextParagraphsWithNoDelimiters() { + List input = + Arrays.asList( + "Thisisatestoftheemergencybroadcastsystem", + "Thisisonlyatest", + "WerepeatthisisonlyatestAunittest", + "AsmallnoteAndanotherAndonceagain", + "SeriouslythisistheendWe'refinishedAllsetByeDoneThisOneWillBeSplitToMeetTheLimit"); + List expected = + Arrays.asList( + "Thisisatestoftheemergencybroadcastsystem" + "\n" + "Thisisonlyatest", + "WerepeatthisisonlyatestAunittest", + "AsmallnoteAndanotherAndonceagain", + "SeriouslythisistheendWe'refinishedAllse", + "tByeDoneThisOneWillBeSplitToMeetTheLimit"); + + List result = TextChunker.splitPlainTextParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } + + @Test + public void canSplitMarkdownParagraphsOnNewlines() { + List input = + Arrays.asList( + "This_is_a_test_of_the_emergency_broadcast_system\r\nThis_is_only_a_test", + "We_repeat_this_is_only_a_test\nA_unit_test", + "A_small_note\n" + + "And_another\r\n" + + "And_once_again\r" + + "Seriously_this_is_the_end\n" + + "We're_finished\n" + + "All_set\n" + + "Bye\n", + "Done"); + + List expected = + Arrays.asList( + "This_is_a_test_of_the_emergency_broadcast_system", + "This_is_only_a_test", + "We_repeat_this_is_only_a_test\nA_unit_test", + "A_small_note\nAnd_another\nAnd_once_again", + "Seriously_this_is_the_end\nWe're_finished\nAll_set\nBye Done"); + + List result = TextChunker.splitMarkdownParagraphs(input, 15); + + Assertions.assertEquals(expected, result); + } +} diff --git a/java/pom.xml b/java/pom.xml new file mode 100644 index 0000000000..2b4e910e19 --- /dev/null +++ b/java/pom.xml @@ -0,0 +1,813 @@ + + + + + 4.0.0 + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + pom + https://www.github.com/microsoft/semantic-kernel + Semantic Kernel Parent + Parent pom for the Semantic Kernel Project + + + 1.0.0-beta.5 + 10.12.2 + 0.10.10 + 2.19.1 + 1.17.0 + 1.6.0 + 5.10.0 + 2.20.0 + 3.1.0 + 2.12.1 + 3.3.0 + 3.3.1 + 3.11.0 + 8 + 8 + 8 + 3.6.0 + 3.1.1 + 1.0 + 3.3.0 + 3.1.0 + 3.1.1 + 0.8.10 + 3.3.0 + 3.5.0 + 3.3.0 + 2.2.0 + 3.21.0 + 3.4.5 + 0.15 + 3.0.1 + 3.3.1 + 4.0.0-M9 + 3.5.0 + 3.3.0 + 4.7.3.5 + + 2.38.0 + 3.1.2 + 3.9.3 + 2.16.0 + 5.4.0 + 0.9.1 + 6.55.0 + UTF-8 + microsoft/semantic-kernel + git@github.com:${project.github.repository}.git + 4.7.3 + + + + connectors/semantickernel-connectors-ai-openai + connectors/semantickernel-connectors-memory-sqlite + connectors/semantickernel-connectors-memory-azurecognitivesearch + connectors/semantickernel-connectors-memory-jdbc + connectors/semantickernel-connectors-memory-postgresql + connectors/semantickernel-connectors-memory-mysql + + extensions/semantickernel-planners + extensions/semantickernel-gpt3-tokenizer + extensions/semantickernel-settings-loader + + plugins/semantickernel-plugin-core + + semantickernel-bom + semantickernel-api + semantickernel-core + + + + + + com.microsoft.semantic-kernel + semantickernel-bom + ${project.version} + pom + import + + + org.junit.jupiter + junit-jupiter + ${junit5.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit5.version} + test + + + org.apache.logging.log4j + log4j-api + ${log4j2.version} + test + + + org.apache.logging.log4j + log4j-core + ${log4j2.version} + test + + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j2.version} + test + + + org.mockito + mockito-core + ${mockito.version} + test + + + com.azure + azure-ai-openai + ${azure-ai-openai.version} + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + ${project.version} + + + com.microsoft.semantic-kernel.extensions + semantickernel-sequentialplanner-extension + ${project.version} + + + com.microsoft.semantic-kernel.extensions + semantickernel-actionplanner-extension + ${project.version} + + + + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + ${maven.spotbugs-plugin.version} + + + com.github.spotbugs + spotbugs + ${spotbugs.version} + + + + + + org.apache.maven.plugins + maven-changes-plugin + ${maven.changes-plugin.version} + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${maven.checkstyle-plugin.version} + + + com.puppycrawl.tools + checkstyle + ${checkstyle.version} + + + + + org.apache.maven.plugins + maven-clean-plugin + ${maven.clean-plugin.version} + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler-plugin.version} + + ${maven.compiler.release} + ${maven.compiler.release} + 8 + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven.dependency-plugin.version} + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven.deploy-plugin.version} + + + org.apache.maven.plugins + maven-enforcer-plugin + ${maven.enforcer-plugin.version} + + + enforce-maven + + enforce + + + + + ${maven.version} + + + + + + + + org.apache.maven.plugins + maven-install-plugin + ${maven.install-plugin.version} + + + org.apache.maven.plugins + maven-jar-plugin + ${maven.jar-plugin.version} + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven.javadoc-plugin.version} + + + false + true + public + + + + org.apache.maven.plugins + maven-jxr-plugin + ${maven.jxr-plugin.version} + + + org.apache.maven.plugins + maven-pmd-plugin + ${maven.pmd-plugin.version} + + + net.sourceforge.pmd + pmd-core + ${pmd.version} + + + net.sourceforge.pmd + pmd-java + ${pmd.version} + + + net.sourceforge.pmd + pmd-javascript + ${pmd.version} + + + net.sourceforge.pmd + pmd-jsp + ${pmd.version} + + + + + org.apache.maven.plugins + maven-release-plugin + ${maven.release-plugin.version} + + + org.apache.maven.plugins + maven-shade-plugin + ${maven.shade-plugin.version} + + + org.apache.maven.plugins + maven-source-plugin + ${maven.source-plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire-plugin.version} + + + org.apache.maven.plugins + maven-site-plugin + ${maven.site-plugin.version} + + + org.apache.maven.plugins + maven-project-info-reports-plugin + ${maven.project-info-reports-plugin.version} + + + org.apache.maven.plugins + maven-resources-plugin + ${maven.resources-plugin.version} + + + org.apache.maven.plugins + maven-antrun-plugin + ${maven.antrun-plugin.version} + + + org.apache.rat + apache-rat-plugin + ${maven.rat-plugin.version} + + + org.codehaus.mojo + exec-maven-plugin + ${maven.exec-plugin.version} + + + org.codehaus.mojo + license-maven-plugin + ${maven.license-plugin.version} + + Microsoft + 2023 + mit + ${basedir}/target/LICENSE + + + + org.codehaus.mojo + versions-maven-plugin + ${maven.versions-plugin.version} + + + org.commonjava.maven.plugins + directory-maven-plugin + ${maven.directory-maven-plugin.version} + + + org.jacoco + jacoco-maven-plugin + ${maven.jacoco-plugin.version} + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + org.codehaus.mojo + animal-sniffer-maven-plugin + 1.23 + + + android + test + + check + + + + + + + + + net.sf.androidscents.signature + android-api-level-26 + 8.0.0_r2 + + + + + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + + + org.apache.maven.plugins + maven-enforcer-plugin + + + org.codehaus.mojo + license-maven-plugin + + + + update-project-license + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.0 + + + attach-sources + verify + + jar-no-fork + + + + + + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + + + + org.mutabilitydetector + MutabilityDetector4FindBugs + ${mutability.detector.version} + + + + + + org.apache.maven.plugins + maven-changes-plugin + + + + + + changes-report + + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + checkstyle + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + ${maven.compiler.release} + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + org.apache.rat + apache-rat-plugin + + + org.codehaus.mojo + license-maven-plugin + + + org.codehaus.mojo + versions-maven-plugin + + + + dependency-updates-report + plugin-updates-report + property-updates-report + + + + + + org.jacoco + jacoco-maven-plugin + ${maven.jacoco-plugin.version} + + + + + + + central + + true + + + false + + https://repo1.maven.org/maven2/ + + + + + + compile-jdk8 + + 1.8 + 1.8 + + + + + compile-jdk17 + + true + + + 17 + 17 + + + samples + + + + bug-check + + false + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler-plugin.version} + + ${maven.compiler.release} + ${maven.compiler.release} + + 8 + ${project.build.sourceEncoding} + true + + -XDcompilePolicy=simple + + + -Xplugin:ErrorProne + -XepOpt:NullAway:AnnotatedPackages=com.microsoft.semantickernel + -Xep:AlmostJavadoc:OFF -Xep:MissingSummary:OFF + -Xep:UnusedVariable:OFF -Xep:EmptyBlockTag:OFF + + + + + com.google.errorprone + error_prone_core + ${google.errorprone.core.version} + + + com.uber.nullaway + nullaway + ${com.uber.nullaway.version} + + + + + + com.diffplug.spotless + spotless-maven-plugin + ${maven.spotless-plugin.version} + + + check + + check + + compile + + + apply + + apply + + process-sources + + + + + + ${google.java.format.version} + + true + + + // Copyright (c) Microsoft. All rights reserved. + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + ${maven.spotbugs-plugin.version} + + spotbugs-exclude.xml + Max + + Normal + + + + + spotbugs + check + + + + + + + org.codehaus.mojo + animal-sniffer-maven-plugin + + + + + + + with-samples + + samples + api-test + + + + release + + 1.8 + 1.8 + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + jar + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + true + + + + org.apache.maven.plugins + maven-release-plugin + + java-@{project.version} + + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + + + + ${releaseRepoId} + ${releaseRepoUrl} + ${releaseRepoName} + + + + + ${releaseRepoId} + ${releaseRepoUrl} + ${releaseRepoName} + + + + + + + + + microsoft + Microsoft + + + + + + MIT License + https://opensource.org/licenses/MIT + repo + + + + + https://github.com/microsoft/semantic-kernel + scm:git:https://github.com/microsoft/semantic-kernel.git + scm:git:https://github.com/microsoft/semantic-kernel.git + java-0.2.9-alpha + + diff --git a/java/samples/example.conf.properties b/java/samples/example.conf.properties new file mode 100644 index 0000000000..f41f25b4d2 --- /dev/null +++ b/java/samples/example.conf.properties @@ -0,0 +1,6 @@ +client.openai.key=OPEN_AI_KEY +client.openai.organizationid=OPEN_AI_ORGANIZATION_ID + +client.azureopenai.key=AZURE_OPEN_AI_KEY +client.azureopenai.endpoint=AZURE_OPEN_AI_ENDPOINT +client.azureopenai.deploymentname=AZURE_OPEN_AI_DEPLOYMENT_NAME diff --git a/java/samples/pom.xml b/java/samples/pom.xml new file mode 100644 index 0000000000..8cff0455f6 --- /dev/null +++ b/java/samples/pom.xml @@ -0,0 +1,173 @@ + + + 4.0.0 + + com.microsoft.semantic-kernel + samples + 0.2.10-alpha-SNAPSHOT + pom + Semantic Kernel Samples Parent + Parent pom for sample code for using the Semantic Kernel project + + + sample-code + semantickernel-samples-guice + + + + 0.10.10 + 2.19.1 + 2.20.0 + 3.11.0 + 17 + 17 + 17 + UTF-8 + + + + + + com.microsoft.semantic-kernel + semantickernel-bom + ${project.version} + import + pom + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler-plugin.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.release} + ${maven.compiler.release} + ${maven.compiler.release} + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.3.0 + + + enforce-maven + + enforce + + + + + 3.9.3 + + + + + + + + + + + + com.microsoft.semantic-kernel + semantickernel-api + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + + + com.microsoft.semantic-kernel + semantickernel-core + runtime + + + com.microsoft.semantic-kernel + semantickernel-plugin-core + ${project.version} + + + org.apache.logging.log4j + log4j-api + ${log4j2.version} + + + org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j2.version} + + + com.microsoft.semantic-kernel + semantickernel-planners + compile + + + + + + bug-check + + + false + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler-plugin.version} + + ${maven.compiler.release} + ${maven.compiler.release} + ${project.build.sourceEncoding} + true + + -XDcompilePolicy=simple + + + -Xplugin:ErrorProne + -XepOpt:NullAway:AnnotatedPackages=com.microsoft.semantickernel + -Xep:AlmostJavadoc:OFF -Xep:MissingSummary:OFF + -Xep:UnusedVariable:OFF -Xep:EmptyBlockTag:OFF + + + + + com.google.errorprone + error_prone_core + ${google.errorprone.core.version} + + + com.uber.nullaway + nullaway + ${com.uber.nullaway.version} + + + + + + + + + diff --git a/java/samples/sample-code/README.md b/java/samples/sample-code/README.md new file mode 100644 index 0000000000..56c951268b --- /dev/null +++ b/java/samples/sample-code/README.md @@ -0,0 +1,125 @@ +# Java Samples + +## TL;DR + +Run with: + +```shell +# AZURE: +OPENAI_CLIENT_TYPE=AZURE_OPEN_AI \ +AZURE_OPEN_AI_KEY="my-key" \ +AZURE_OPEN_AI_ENDPOINT="endpoint url" \ +../../mvnw clean package exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode + +# OPENAI: +OPENAI_CLIENT_TYPE=OPENAI \ +OPEN_AI_KEY="my-key" \ +OPEN_AI_ORGANIZATION_ID="organisation id" \ +../../mvnw clean package exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode +``` + +# Compile + +These samples can be compiled via: + +```shell + ../../mvnw clean package +``` + +They can then be run by: + +```shell +../../mvnw exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode +``` + +# Configuration + +You can define the provider of Open AI by setting the `OPENAI_CLIENT_TYPE` +property or environment variable to either [`OPENAI`](https://openai.com/api/) +or [`AZURE_OPEN_AI`](https://learn.microsoft.com/azure/cognitive-services/openai/). +By default, the samples will use the Open AI client. + +```shell +OPENAI_CLIENT_TYPE=OPEN_AI ../../mvnw exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode + +OR + + ../../mvnw exec:java -DOPENAI_CLIENT_TYPE=AZURE_OPEN_AI -Dsample=Example04_CombineLLMPromptsAndNativeCode +``` + +## Client Settings +The samples search for the client settings in the following order: +1. Properties file whose location is defined by the `CONF_PROPERTIES` property or environment variable. +1. System properties defined on the command line. +1. Environment variables. +1. Properties file at `java/samples/conf.properties`. +1. Properties file at `~/.sk/conf.properties`. + + +## Properties File + +You can set the location of a properties file, by setting the `CONF_PROPERTIES` property or environment variable, ie: + +```shell +CONF_PROPERTIES=my.properties \ +OPENAI_CLIENT_TYPE=OPEN_AI \ +../../mvnw exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode + +OR + +../../mvnw exec:java \ +-DCONF_PROPERTIES=my.properties \ +-DOPENAI_CLIENT_TYPE=AZURE_OPEN_AI \ +-Dsample=Example04_CombineLLMPromptsAndNativeCode +``` + +A properties file looks as follows: + +```properties +# If using openai.com +client.openai.key:"my-key" +client.openai.organizationid:"my-org-id" +# if using Azure Open AI +client.azureopenai.key:"my-key" +client.azureopenai.endpoint:"url of azure openai endpoint" +client.azureopenai.deploymentname:"deployment name" +``` + +## System Properties + +As an alternative to providing the key/endpoint properties via a file, you can set them directly via system properties, +ie: + +```shell +# OpenAI +../../mvnw exec:java \ +-DOPENAI_CLIENT_TYPE=AZURE_OPEN_AI \ +-Dclient.openai.key="my-key" \ +-Dclient.openai.organizationid="my-org-id" \ +-Dsample=Example04_CombineLLMPromptsAndNativeCode + +# Azure +../../mvnw exec:java \ +-DOPENAI_CLIENT_TYPE=AZURE_OPEN_AI \ +-Dclient.azureopenai.key="my-key" \ +-Dclient.azureopenai.endpoint="url of azure openai endpoint" \ +-Dsample=Example04_CombineLLMPromptsAndNativeCode +``` + +## Environment variables + +Alternative to properties, you can set environment variables as follows: + +```shell +# AZURE: +OPENAI_CLIENT_TYPE=AZURE_OPEN_AI \ +AZURE_OPEN_AI_KEY="my-key" \ +AZURE_OPEN_AI_ENDPOINT="endpoint url" \ +../../mvnw clean package exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode + +# OPENAI: +OPENAI_CLIENT_TYPE=OPEN_AI \ +OPEN_AI_KEY="my-key" \ +OPEN_AI_ORGANIZATION_ID="organisation id" \ +../../mvnw clean package exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode +``` diff --git a/java/samples/sample-code/pom.xml b/java/samples/sample-code/pom.xml new file mode 100644 index 0000000000..fcef47df95 --- /dev/null +++ b/java/samples/sample-code/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + + com.microsoft.semantic-kernel + samples + 0.2.10-alpha-SNAPSHOT + ../pom.xml + + + sample-code + Semantic Kernel Samples + Sample code for using the Semantic Kernel project + jar + + + + com.microsoft.semantic-kernel + semantickernel-api + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + + + com.microsoft.semantic-kernel + semantickernel-core + + + + + com.microsoft.semantic-kernel + semantickernel-plugin-core + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-azurecognitivesearch + + + + org.apache.logging.log4j + log4j-api + 2.20.0 + + + org.apache.logging.log4j + log4j-core + 2.20.0 + + + org.apache.logging.log4j + log4j-slf4j2-impl + 2.20.0 + + + com.microsoft.semantic-kernel + semantickernel-planners + compile + + + com.microsoft.semantic-kernel + semantickernel-gpt3-tokenizer + compile + + + com.fasterxml.jackson.core + jackson-databind + compile + + + com.fasterxml.jackson.core + jackson-core + compile + + + com.microsoft.semantic-kernel + semantickernel-settings-loader + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + run-sample + + java + + + + + com.microsoft.semantickernel.samples.syntaxexamples.${sample} + + + + + + diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example99_BlogAnnouncement.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example99_BlogAnnouncement.java new file mode 100644 index 0000000000..e0d03619fb --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example99_BlogAnnouncement.java @@ -0,0 +1,74 @@ +package com.microsoft.semantickernel; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import com.microsoft.semantickernel.textcompletion.TextCompletion; + +import java.io.IOException; + +/** + * Code for Microsoft Developer Blog + * + * Introducing Semantic Kernel for Java + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example99_BlogAnnouncement { + + static { + System.setProperty("client.openai.key", ""); + } + + public static void main(String[] args) throws IOException, ConfigurationException { + OpenAIAsyncClient client = OpenAIClientProvider.getClient(); + + TextCompletion textCompletionService = SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build(); + + Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletionService).build(); + kernel.importSkill(new MyAppSkills(), "MyAppSkills"); + + SequentialPlanner planner = new SequentialPlanner(kernel, null, null); + + Plan plan = planner.createPlanAsync( + "For any input with passwords, redact the passwords and send redacted input to sysadmin@corp.net") + .block(); + + System.out.println(plan.toPlanString()); + + String message = "Password changed to password.db=123456abc"; + String result = plan.invokeAsync(message).block().getResult(); + + System.out.println(" === Result of the plan === "); + System.out.println(result); + } + + public static class MyAppSkills { + @DefineSKFunction(name = "redactPassword", description = "Redacts passwords from a message") + public String redactPassword( + @SKFunctionInputAttribute( + description = "The input message to redact passwords from" + ) String input) { + System.out.println("[redactPassword] Redacting passwords from input: " + input); + return input.replaceAll("password.*", "******"); + } + + @DefineSKFunction(name = "sendEmail", description = "Sends a message to an email") + public String sendEmail( + @SKFunctionParameters(name = "message") String message, + @SKFunctionParameters(name = "email") String email) { + return String.format("[sendEmail] Emailing to %s the following message: %n -> %s%n", email, message); + } + } + +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example_PlanWithNativeFunctions.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example_PlanWithNativeFunctions.java new file mode 100644 index 0000000000..2c5cf6836f --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/Example_PlanWithNativeFunctions.java @@ -0,0 +1,121 @@ +package com.microsoft.semantickernel; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import com.microsoft.semantickernel.textcompletion.TextCompletion; + +/** + * Example of a planner which uses native functions. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example_PlanWithNativeFunctions { + + public static void main(String[] args) throws ConfigurationException { + OpenAIAsyncClient client = OpenAIClientProvider.getClient(); + + TextCompletion textCompletionService = SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build(); + + Kernel kernel = SKBuilders.kernel() + .withDefaultAIService(textCompletionService) + .build(); + + kernel.importSkill(new StringFunctions(), "StringFunctions"); + kernel.importSkill(new Emailer(), "Emailer"); + kernel.importSkill(new Names(), "Names"); + + SequentialPlanner planner = new SequentialPlanner(kernel, null, null); + + + Plan plan = planner + .createPlanAsync("Send the input as an email to Steven and make sure I use his preferred name in the email") + .block(); + + System.out.println("\n\n=============================== Plan to execute ==============================="); + System.out.println(plan.toPlanString()); + System.out.println("==============================================================================="); + + + SKContext context = SKBuilders.context().build(); + context.setVariable("subject", "Update"); + + String message = "Hay Steven, just wanted to let you know I have finished."; + + System.out.println("\n\nExecuting plan..."); + SKContext planResult = plan.invokeAsync(message, context, null).block(); + + System.out.println("\n\nPlan Result: " + planResult.getResult()); + } + + public static class StringFunctions { + @DefineSKFunction( + name = "stringReplace", + description = "Takes a message and substitutes string 'from' to 'to'") + public String stringReplace( + @SKFunctionInputAttribute(description = "The string to perform the replacement on") + String input, + @SKFunctionParameters(name = "from", description = "The string to replace") + String from, + @SKFunctionParameters(name = "to", description = "The string to replace with") + String to + ) { + return input.replaceAll(from, to); + } + } + + public static class Names { + @DefineSKFunction(name = "getNickName", description = "Retrieves the nick name for a given user") + public String getNickName( + @SKFunctionInputAttribute(description = "The name of the person to get an nick name for") + String name) { + switch (name) { + case "Steven": + return "Code King"; + default: + throw new RuntimeException("Unknown user: " + name); + } + } + + } + + public static class Emailer { + @DefineSKFunction(name = "getEmailAddress", description = "Retrieves the email address for a given user") + public String getEmailAddress( + @SKFunctionInputAttribute(description = "The name of the person to get an email address for") + String name) { + switch (name) { + case "Steven": + return "codeking@example.com"; + default: + throw new RuntimeException("Unknown user: " + name); + } + } + + @DefineSKFunction(name = "sendEmail", description = "Sends an email") + public String sendEmail( + @SKFunctionParameters(name = "subject", description = "The email subject") String subject, + @SKFunctionParameters(name = "message", description = "The message to email") String message, + @SKFunctionParameters(name = "emailAddress", description = "The emailAddress to send the message to") String emailAddress) { + System.out.println("================= Sending Email ===================="); + System.out.printf("To: %s%n", emailAddress); + System.out.printf("Subject: %s%n", subject); + System.out.printf("Message: %s%n", message); + System.out.println("===================================================="); + return "Message sent"; + } + } + +} + diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/SamplesConfig.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/SamplesConfig.java new file mode 100644 index 0000000000..f7df3e89f7 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/SamplesConfig.java @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider; +import com.microsoft.semantickernel.exceptions.ConfigurationException; + +import java.io.File; +import java.util.List; + +/** + * Helper for creating + * Refer to the + * README for configuring your environment to run the examples. + */ +public class SamplesConfig { + + public static final List DEFAULT_PROPERTIES_LOCATIONS = List.of( + new File("java/samples/conf.properties") + ); + + + public static OpenAIAsyncClient getClient() throws ConfigurationException { + return OpenAIClientProvider.getWithAdditional(DEFAULT_PROPERTIES_LOCATIONS); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example00_GettingStarted.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example00_GettingStarted.java new file mode 100755 index 0000000000..d787c55cd5 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example00_GettingStarted.java @@ -0,0 +1,81 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha +//DEPS org.slf4j:slf4j-jdk14:2.0.7 +//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java +package com.microsoft.semantickernel.samples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.samples.syntaxexamples.SampleSkillsUtil; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import reactor.core.publisher.Mono; + +import java.io.IOException; + +/** + * Getting started + *

+ * Get + * started with Azure OpenAI + * Get started with OpenAI + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example00_GettingStarted { + + /** + * Returns a Semantic Kernel with Text Completion. + * + * @param client Client that will handle requests to AzureOpenAI or OpenAI. + * @return Kernel. + */ + public static Kernel getKernel(OpenAIAsyncClient client) { + Kernel kernel = SKBuilders.kernel() + .withDefaultAIService(SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build()) + .build(); + + return kernel; + } + + /** + * Imports 'FunSkill' from directory examples and runs the 'Joke' function + * within it. + * + * @param kernel Kernel with Text Completion. + */ + public static void joke(Kernel kernel) { + + ReadOnlyFunctionCollection skill = kernel.importSkillFromDirectory("FunSkill", SampleSkillsUtil.detectSkillDirLocation(), "FunSkill"); + + CompletionSKFunction function = skill.getFunction("Joke", + CompletionSKFunction.class); + + Mono result = function.invokeAsync("time travel to dinosaur age"); + + if (result != null) { + System.out.println(result.block().getResult()); + } + } + + public static void run(OpenAIAsyncClient client) { + Kernel kernel = getKernel(client); + joke(kernel); + } + + public static void main(String args[]) throws ConfigurationException, IOException { + run(OpenAIClientProvider.getClient()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example02_RunningPromptsFromFile.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example02_RunningPromptsFromFile.java new file mode 100755 index 0000000000..2a65656abf --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example02_RunningPromptsFromFile.java @@ -0,0 +1,63 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha +//DEPS org.slf4j:slf4j-jdk14:2.0.7 +//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java,Example00_GettingStarted.java +package com.microsoft.semantickernel.samples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.samples.syntaxexamples.SampleSkillsUtil; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; + +import java.io.IOException; + +/** + * Using Semantic Functions stored on disk + *

+ * A Semantic Skill is a collection of Semantic Functions, where each function + * is defined with natural language that can be provided with a text file. + * Refer to our glossary + * for an in-depth guide to the terms. + *

+ * The repository includes some examples under the samples + * folder. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example02_RunningPromptsFromFile { + + /** + * Imports skill 'FunSkill' stored in the samples folder and then returns the + * semantic function 'Joke' within it. + * + * @param kernel + with Text Completion + * @return Joke function + */ + public static CompletionSKFunction getJokeFunction(Kernel kernel) { + ReadOnlyFunctionCollection skill = kernel + .importSkillFromDirectory("FunSkill", SampleSkillsUtil.detectSkillDirLocation(), "FunSkill"); + + return skill.getFunction("Joke", CompletionSKFunction.class); + } + + public static void run(OpenAIAsyncClient client) throws IOException { + Kernel kernel = Example00_GettingStarted.getKernel(client); + CompletionSKFunction jokeFunction = getJokeFunction(kernel); + + System.out.println(jokeFunction.invokeAsync("time travel to dinosaur age").block().getResult()); + } + + public static void main(String args[]) throws ConfigurationException, IOException { + run(OpenAIClientProvider.getClient()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example03_SemanticFunctionInline.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example03_SemanticFunctionInline.java new file mode 100755 index 0000000000..be1d216025 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example03_SemanticFunctionInline.java @@ -0,0 +1,136 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha +//DEPS org.slf4j:slf4j-jdk14:2.0.7 +//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java,Example00_GettingStarted.java +package com.microsoft.semantickernel.samples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import reactor.core.publisher.Mono; + +import java.io.IOException; + +/** + * Define a Semantic Function inline with Java code. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example03_SemanticFunctionInline { + + /** + * Defines and runs an inline Semantic Function + * + * @param kernel Kernel with Text Completion + * @param prompt String prompt + * @param functionName Name of the function + * @param text Input to the function + */ + public static void inlineFunction(Kernel kernel, String prompt, String functionName, String text) { + SKFunction summarize = kernel + .getSemanticFunctionBuilder() + .withPromptTemplate(prompt) + .withFunctionName(functionName) + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig( + 0.2, + 0.5, + 0, + 0, + 2000)) + .build(); + + Mono result = summarize.invokeAsync(text); + + if (result != null) { + System.out.println(result.block().getResult()); + } + } + + /** + * Example prompt that summarizes text + * + * @param kernel + */ + public static void summarize(Kernel kernel) { + String prompt = """ + {{$input}} + Summarize the content above. + """; + + String text = """ + Demo (ancient Greek poet) + From Wikipedia, the free encyclopedia + Demo or Damo (Greek: ΔÎĩÎŧĪŽ, ΔαÎŧĪŽ; fl. c. AD 200) was a Greek woman of the Roman period, + known for a single epigram, engraved upon the Colossus of Memnon, which bears her name. + She speaks of herself therein as a lyric poetess dedicated to the Muses, but nothing is known of her life.[1] + Identity + Demo was evidently Greek, as her name, a traditional epithet of Demeter, signifies. + The name was relatively common in the Hellenistic world, in Egypt and elsewhere, + and she cannot be further identified. + The date of her visit to the Colossus of Memnon cannot be established with certainty, + but internal evidence on the left leg suggests her poem was inscribed there at some point in or after AD 196.[2] + Epigram + There are a number of graffiti inscriptions on the Colossus of Memnon. + Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac couplets, + entitled and presumably authored by "Demo" or "Damo" + (the Greek inscription is difficult to read), is a dedication to the Muses.[2] + The poem is traditionally published with the works of Balbilla, + though the internal evidence suggests a different author.[1] + In the poem, Demo explains that Memnon has shown her special respect. + In return, Demo offers the gift for poetry, as a gift to the hero. + At the end of this epigram, she addresses Memnon, + highlighting his divine status by recalling his strength and holiness.[2] + Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic dialect. + The language indicates she was knowledgeable in Homeric poetry—'bearing a pleasant gift', + for example, alludes to the use of that phrase throughout the Iliad and Odyssey.[a][2] + """; + + inlineFunction(kernel, prompt, "summarize", text); + } + + /** + * Example of a prompt returning a TLDR of a text + * + * @param kernel + */ + public static void TLDR(Kernel kernel) { + String prompt = """ + {{$input}} + + Give me the TLDR in 5 words. + """; + + String text = """ + 1) A robot may not injure a human being or, through inaction, + allow a human being to come to harm. + + 2) A robot must obey orders given it by human beings except where + such orders would conflict with the First Law. + + 3) A robot must protect its own existence as long as such protection + does not conflict with the First or Second Law. + """; + + inlineFunction(kernel, prompt, "tldr", text); + } + + public static void run(OpenAIAsyncClient client) throws IOException { + Kernel kernel = Example00_GettingStarted.getKernel(client); + + summarize(kernel); + TLDR(kernel); + } + + public static void main(String args[]) throws ConfigurationException, IOException { + run(OpenAIClientProvider.getClient()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example04_ContextVariablesChat.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example04_ContextVariablesChat.java new file mode 100755 index 0000000000..f8278ea766 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example04_ContextVariablesChat.java @@ -0,0 +1,120 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha +//DEPS org.slf4j:slf4j-jdk14:2.0.7 +//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java,Example00_GettingStarted.java +package com.microsoft.semantickernel.samples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import reactor.core.publisher.Mono; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.function.Function; + +/** + * Chatbot using context variables + *

+ * Context Variables object which in this demo functions similarly as a + * key-value store that you can use when running the kernel. + * The context is local (i.e. in your computer's RAM) and not persisted anywhere + * beyond the life of the JVM execution. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example04_ContextVariablesChat { + public static void startChat(Kernel kernel) + throws ExecutionException, InterruptedException, TimeoutException { + String 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. + + {{$history}} + User: {{$user_input}} + ChatBot: """; + + CompletionSKFunction chat = kernel + .getSemanticFunctionBuilder() + .withPromptTemplate(prompt) + .withFunctionName("ChatBot") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig( + 0.7, + 0.5, + 0, + 0, + 2000)) + .build(); + + SKContext readOnlySkContext = SKBuilders.context().withKernel(kernel).build(); + + chat("Hi, I'm looking for book suggestions?", chat, readOnlySkContext) + .flatMap( + chat( + "I love history and philosophy, I'd like to learn something new" + + " about Greece, any suggestion?", + chat)) + .flatMap(chat("that sounds interesting, what is it about?", chat)) + .flatMap( + chat( + "if I read that book, what exactly will I learn about Greece" + + " history?", + chat)) + .flatMap( + chat("could you list some more books I could read about this topic?", chat)) + .block(); + } + + private static Mono chat( + String input, CompletionSKFunction chat, SKContext context) + throws ExecutionException, InterruptedException, TimeoutException { + context = context.setVariable("user_input", input); + + System.out.println("User: " + input); + + SKContext finalContext = context; + return chat.invokeAsync(context, null) + .map( + result -> { + System.out.println("Bot: " + result.getResult() + "\n"); + + String existingHistoy = finalContext.getVariables().asMap().get("history"); + if (existingHistoy == null) { + existingHistoy = ""; + } + existingHistoy += "\nUser: " + input + "\nChatBot: " + result.getResult() + "\n"; + return finalContext.setVariable("history", existingHistoy); + }); + } + + private static Function> chat( + String input, CompletionSKFunction chat) { + return (context) -> { + try { + return chat(input, chat, context); + } catch (ExecutionException | InterruptedException | TimeoutException e) { + return Mono.error(e); + } + }; + } + + public static void run(OpenAIAsyncClient client) throws ExecutionException, InterruptedException, TimeoutException { + Kernel kernel = Example00_GettingStarted.getKernel(client); + + startChat(kernel); + } + + public static void main(String args[]) throws ConfigurationException, ExecutionException, InterruptedException, TimeoutException { + run(OpenAIClientProvider.getClient()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example05_UsingThePlanner.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example05_UsingThePlanner.java new file mode 100755 index 0000000000..78f1bc9273 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/Example05_UsingThePlanner.java @@ -0,0 +1,53 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? +//DEPS com.microsoft.semantic-kernel:semantickernel-core:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel:semantickernel-core-skills:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel.connectors:semantickernel-connectors:0.2.6-alpha +//DEPS com.microsoft.semantic-kernel.extensions:semantickernel-sequentialplanner-extension:0.2.6-alpha +//DEPS org.slf4j:slf4j-jdk14:2.0.7 +//SOURCES syntaxexamples/SampleSkillsUtil.java,Config.java,Example00_GettingStarted.java +package com.microsoft.semantickernel.samples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.connectors.ai.openai.util.OpenAIClientProvider; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner; +import com.microsoft.semantickernel.samples.syntaxexamples.SampleSkillsUtil; + +/** + * Sequential Planner + *

+ * See + * Semantic Kernel Planners: Sequential Planner + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example05_UsingThePlanner { + + public static SequentialPlanner getPlanner(Kernel kernel) { + kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(), "SummarizeSkill"); + kernel.importSkillFromDirectory("WriterSkill", SampleSkillsUtil.detectSkillDirLocation(), "WriterSkill"); + + return new SequentialPlanner(kernel, null, null); + } + + public static void run(OpenAIAsyncClient client) { + Kernel kernel = Example00_GettingStarted.getKernel(client); + + SequentialPlanner planner = getPlanner(kernel); + System.out.println(planner.createPlanAsync( + "Write a poem about John Doe, then translate it into Italian.") + .block().invokeAsync().block().getResult()); + + // TODO: execute the plan + } + + public static void main(String args[]) throws ConfigurationException { + run(OpenAIClientProvider.getClient()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example01_NativeFunctions.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example01_NativeFunctions.java new file mode 100644 index 0000000000..f4091e5695 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example01_NativeFunctions.java @@ -0,0 +1,20 @@ +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.microsoft.semantickernel.coreskills.TextSkill; + +/** + * Demonstrates a native function from the {@code com.microsoft.semantickernel.coreskills} package. + */ +public class Example01_NativeFunctions { + + public static void main(String[] args) { + + // Load native skill + TextSkill text = new TextSkill(); + + // Use function without kernel + String result = text.uppercase("ciao!"); + + System.out.println(result); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example02_Pipeline.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example02_Pipeline.java new file mode 100644 index 0000000000..990d89d786 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example02_Pipeline.java @@ -0,0 +1,29 @@ +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.coreskills.TextSkill; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import reactor.core.publisher.Mono; + +/** + * Demonstrates running a pipeline (a sequence of functions) over some input. + */ +public class Example02_Pipeline { + public static void main(String[] args) { + Kernel kernel = SKBuilders.kernel().build(); + + // Load native skill + ReadOnlyFunctionCollection text = kernel.importSkill(new TextSkill(), null); + + Mono result = + kernel.runAsync( + " i n f i n i t e s p a c e ", + text.getFunction("LStrip"), + text.getFunction("RStrip"), + text.getFunction("Uppercase")); + + System.out.println(result.block().getResult()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example03_Variables.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example03_Variables.java new file mode 100644 index 0000000000..aba0f41fde --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example03_Variables.java @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import reactor.core.publisher.Mono; + +import java.util.Locale; + +/** + * Demonstrates running a pipeline (a sequence of functions) on a + * {@code com.microsoft.semantickernel.orchestration.SKContext} + */ +public class Example03_Variables { + + public static class StaticTextSkill { + @DefineSKFunction(description = "Change all string chars to uppercase.", name = "Uppercase") + public static Mono uppercase( + @SKFunctionInputAttribute(description = "Text to uppercase") + String text) { + return Mono.just(text.toUpperCase(Locale.ROOT)); + } + + @DefineSKFunction(description = "Append the day variable", name = "appendDay") + public Mono appendDay( + @SKFunctionInputAttribute(description = "Text to append to") + String input, + @SKFunctionParameters(description = "Current day", name = "day") String day) { + return Mono.just(input + day); + } + } + + public static void main(String[] args) { + Kernel kernel = SKBuilders.kernel().build(); + + // Load native skill + ReadOnlyFunctionCollection functionCollection = + kernel.importSkill(new StaticTextSkill(), "text"); + + ContextVariables variables = + SKBuilders.variables() + .withInput("Today is: ") + .build() + .writableClone() + .setVariable("day", "Monday"); + + Mono result = + kernel.runAsync( + variables, + functionCollection.getFunction("AppendDay"), + functionCollection.getFunction("Uppercase")); + + System.out.println(result.block().getResult()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example04_CombineLLMPromptsAndNativeCode.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example04_CombineLLMPromptsAndNativeCode.java new file mode 100644 index 0000000000..42bec80b52 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example04_CombineLLMPromptsAndNativeCode.java @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import reactor.core.publisher.Mono; + +/** + * Demonstrates using skill in combination with LLM prompts. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example04_CombineLLMPromptsAndNativeCode { + + public static class SearchEngineSkill { + + @DefineSKFunction(description = "Search for answer", name = "search") + public Mono search( + @SKFunctionInputAttribute(description = "Text to search") + String input) { + return Mono.just("Gran Torre Santiago is the tallest building in South America"); + } + } + + public static void main(String[] args) throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + + TextCompletion textCompletion = SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build(); + + Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build(); + kernel.importSkill(new SearchEngineSkill(), null); + kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(), + "SummarizeSkill"); + + + // Run + String ask = "What's the tallest building in South America?"; + + Mono result = + kernel.runAsync(ask, kernel.getSkills().getFunction("Search", null)); + + result = + kernel.runAsync( + ask, + kernel.getSkills().getFunction("Search", null), + kernel.getSkill("SummarizeSkill").getFunction("Summarize", null)); + + System.out.println(result.block().getResult()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example05_InlineFunctionDefinition.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example05_InlineFunctionDefinition.java new file mode 100644 index 0000000000..0973fff715 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example05_InlineFunctionDefinition.java @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft. All rights reserved. + +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.TextCompletion; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; + +/** + * Demonstrates using prompt templates to define functions. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example05_InlineFunctionDefinition { + public static void main(String[] args) throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + + TextCompletion textCompletion = SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build(); + + Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build(); + + System.out.println("======== Inline Function Definition ========"); + + // Function defined using few-shot design pattern + String functionDefinition = """ + Generate a creative reason or excuse for the given event. + Be creative and be funny. Let your imagination run wild. + + Event: I am running late. + Excuse: I was being held ransom by giraffe gangsters. + + Event: I haven't been to the gym for a year + Excuse: I've been too busy training my pet dragon. + + Event: {{$input}} + """.stripIndent(); + + // Create function via builder + var excuseFunction = SKBuilders + .completionFunctions() + .withKernel(kernel) + .withPromptTemplate(functionDefinition) + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfigBuilder() + .maxTokens(100) + .temperature(0.4) + .topP(1) + .build()) + .build(); + + + var result = excuseFunction.invokeAsync("I missed the F1 final race").block(); + System.out.println(result.getResult()); + + result = excuseFunction.invokeAsync("sorry I forgot your birthday").block(); + System.out.println(result.getResult()); + + // Create function via kernel + var fixedFunction = kernel. + getSemanticFunctionBuilder() + .withPromptTemplate("Translate this date " + + DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(LocalDateTime.now()) + " to French format") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfigBuilder() + .maxTokens(100) + .temperature(0.4) + .topP(1) + .build()) + .build(); + + System.out.println(fixedFunction.invokeAsync().block().getResult()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example06_TemplateLanguage.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example06_TemplateLanguage.java new file mode 100644 index 0000000000..2b8254fdc4 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example06_TemplateLanguage.java @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.coreskills.TimeSkill; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; + +/** + * Show how to invoke a Native Function written in Java + * from a Semantic Function written in natural language + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example06_TemplateLanguage { + + public static void main(String[] args) throws ConfigurationException { + System.out.println("======== TemplateLanguage ========"); + + OpenAIAsyncClient client = SamplesConfig.getClient(); + + Kernel kernel = SKBuilders.kernel() + .withDefaultAIService(SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build()) + .build(); + + // Load native skill into the kernel skill collection, sharing its functions + // with prompt templates + // Functions loaded here are available as "time.*" + kernel.importSkill(new TimeSkill(), "time"); + + // Semantic Function invoking time.Date and time.Time native functions + String functionDefinition = """ + Today is: {{time.Date}} + Current time is: {{time.Time}} + + Answer to the following questions using JSON syntax, including the data used. + Is it morning, afternoon, evening, or night (morning/afternoon/evening/night)? + Is it weekend time (weekend/not weekend)? + """; + + // This allows to see the prompt before it's sent to OpenAI + System.out.println("--- Rendered Prompt"); + + var promptRenderer = SKBuilders.promptTemplate() + .withPromptTemplateConfig(new PromptTemplateConfig()) + .withPromptTemplate(functionDefinition) + .withPromptTemplateEngine(kernel.getPromptTemplateEngine()) + .build(); + + SKContext skContext = SKBuilders + .context() + .withSkills(kernel.getSkills()) + .build(); + + var renderedPrompt = promptRenderer.renderAsync(skContext); + System.out.println(renderedPrompt.block()); + + // Run the prompt / semantic function + var kindOfDay = kernel + .getSemanticFunctionBuilder() + .withPromptTemplate(functionDefinition) + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig( + 0, 0, 0, 0, 256)) + .build(); + + // Show the result + System.out.println("--- Semantic Function result"); + var result = kindOfDay.invokeAsync("").block().getResult(); + System.out.println(result); + /* + * OUTPUT: + * + * --- Rendered Prompt + * + * Today is: Friday, April 28, 2023 + * Current time is: 11:04:30 PM + * + * Answer to the following questions using JSON syntax, including the data used. + * Is it morning, afternoon, evening, or night + * (morning/afternoon/evening/night)? + * Is it weekend time (weekend/not weekend)? + * + * --- Semantic Function result + * + * { + * "date": "Friday, April 28, 2023", + * "time": "11:04:30 PM", + * "period": "night", + * "weekend": "weekend" + * } + */ + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example08_RetryHandler.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example08_RetryHandler.java new file mode 100644 index 0000000000..bae258d29c --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example08_RetryHandler.java @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.http.policy.ExponentialBackoffOptions; +import com.azure.core.http.policy.RetryOptions; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.connectors.ai.openai.util.AzureOpenAISettings; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.settings.SettingsMap; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; + +import java.time.Duration; + +import static com.microsoft.semantickernel.SamplesConfig.DEFAULT_PROPERTIES_LOCATIONS; + +/** + * Demonstrates customizing the configuration of the Open AI client. + *

+ * Refer to the + * README for endpoint and credential configuration. + */ +public class Example08_RetryHandler { + + public static void main(String[] args) throws ConfigurationException { + RetryOptions retryOptions = new RetryOptions(new ExponentialBackoffOptions() + .setMaxDelay(Duration.ofSeconds(180)) + .setBaseDelay(Duration.ofSeconds(60)) + .setMaxRetries(3)); + + AzureOpenAISettings settings = new AzureOpenAISettings(SettingsMap.getWithAdditional(DEFAULT_PROPERTIES_LOCATIONS)); + + OpenAIAsyncClient client = new OpenAIClientBuilder() + .retryOptions(retryOptions) + .endpoint(settings.getEndpoint()) + .credential(new AzureKeyCredential(settings.getKey())) + .buildAsyncClient(); + + String text = """ + Demo (ancient Greek poet) + From Wikipedia, the free encyclopedia + Demo or Damo (Greek: ΔÎĩÎŧĪŽ, ΔαÎŧĪŽ; fl. c. AD 200) was a Greek woman of the + Roman period, known for a single epigram, engraved upon the Colossus of + Memnon, which bears her name. She speaks of herself therein as a lyric + poetess dedicated to the Muses, but nothing is known of her life.[1] + Identity + Demo was evidently Greek, as her name, a traditional epithet of Demeter, + signifies. The name was relatively common in the Hellenistic world, in + Egypt and elsewhere, and she cannot be further identified. The date of her + visit to the Colossus of Memnon cannot be established with certainty, but + internal evidence on the left leg suggests her poem was inscribed there at + some point in or after AD 196.[2] + Epigram + There are a number of graffiti inscriptions on the Colossus of Memnon. + Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac + couplets, entitled and presumably authored by "Demo" or "Damo" (the + Greek inscription is difficult to read), is a dedication to the Muses.[2] + The poem is traditionally published with the works of Balbilla, though the + internal evidence suggests a different author.[1] + In the poem, Demo explains that Memnon has shown her special respect. In + return, Demo offers the gift for poetry, as a gift to the hero. At the end + of this epigram, she addresses Memnon, highlighting his divine status by + recalling his strength and holiness.[2] + Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic + dialect. The language indicates she was knowledgeable in Homeric + poetry—'bearing a pleasant gift', for example, alludes to the use of that + phrase throughout the Iliad and Odyssey.[a][2]; + """; + + String prompt = "{{$input}}\nSummarize the content above."; + + TextCompletion textCompletion = SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build(); + + Kernel kernel = SKBuilders + .kernel() + .withDefaultAIService(textCompletion) + .build(); + + CompletionSKFunction summarizeFunc = SKBuilders + .completionFunctions() + .withKernel(kernel) + .withPromptTemplate(prompt) + .withFunctionName("summarize") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig( + 0.2, 0.5, 0, 0, 2000)) + .build(); + + kernel.registerSemanticFunction(summarizeFunc); + + SKContext context = summarizeFunc.invokeAsync(text).block(); + + System.out.println(context.getResult()); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example09_FunctionTypes.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example09_FunctionTypes.java new file mode 100644 index 0000000000..bef8fa009b --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example09_FunctionTypes.java @@ -0,0 +1,285 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import reactor.core.publisher.Mono; + +import java.time.Duration; + +/** + * Demonstrates how the Kernel uses functions loaded from skills. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example09_FunctionTypes { + public static void main(String[] args) throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + + TextCompletion textCompletion = SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build(); + + Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build(); + + System.out.println("======== Native function types ========"); + + // Load native skill into the kernel skill collection, sharing its functions with prompt templates + var test = kernel + .importSkill(new LocalExampleSkill(), "test"); + + kernel.importSkillsFromDirectory(SampleSkillsUtil.detectSkillDirLocation(), "SummarizeSkill"); + + + var fakeContext = SKBuilders.context() + .withSkills(kernel.getSkills()) + .build(); + + // The kernel takes care of wiring the input appropriately + SKContext result = kernel.runAsync( + "", + test.getFunction("type01"), + test.getFunction("type02"), + test.getFunction("type03"), + test.getFunction("type04"), + test.getFunction("type05"), + test.getFunction("type06"), + test.getFunction("type07"), + test.getFunction("type08"), + test.getFunction("type09"), + test.getFunction("type10"), + test.getFunction("type11"), + test.getFunction("type12"), + test.getFunction("type13"), + test.getFunction("type14"), + test.getFunction("type15"), + test.getFunction("type16"), + test.getFunction("type17"), + test.getFunction("type18") + ) + .block(); + + kernel.getFunction("test", "type01").invokeAsync().block(); + test.getFunction("type01").invokeAsync().block(); + + kernel.getFunction("test", "type02").invokeAsync().block(); + test.getFunction("type02").invokeAsync().block(); + + kernel.getFunction("test", "type03").invokeAsync().block(); + test.getFunction("type03").invokeAsync().block(); + + kernel.getFunction("test", "type04").invokeAsync(fakeContext).block(); + test.getFunction("type04").invokeAsync(fakeContext).block(); + + kernel.getFunction("test", "type05").invokeAsync(fakeContext).block(); + test.getFunction("type05").invokeAsync(fakeContext).block(); + + kernel.getFunction("test", "type06").invokeAsync(fakeContext).block(); + test.getFunction("type06").invokeAsync(fakeContext).block(); + + kernel.getFunction("test", "type07").invokeAsync(fakeContext).block(); + test.getFunction("type07").invokeAsync(fakeContext).block(); + + kernel.getFunction("test", "type08").invokeAsync("").block(); + test.getFunction("type08").invokeAsync("").block(); + + kernel.getFunction("test", "type09").invokeAsync("").block(); + test.getFunction("type09").invokeAsync("").block(); + + kernel.getFunction("test", "type10").invokeAsync("").block(); + test.getFunction("type10").invokeAsync("").block(); + + kernel.getFunction("test", "type11").invokeAsync("").block(); + test.getFunction("type11").invokeAsync("").block(); + + kernel.getFunction("test", "type12").invokeAsync("").block(); + test.getFunction("type12").invokeAsync("").block(); + + kernel.getFunction("test", "type13").invokeAsync("").block(); + test.getFunction("type13").invokeAsync("").block(); + + kernel.getFunction("test", "type14").invokeAsync("").block(); + test.getFunction("type14").invokeAsync("").block(); + + kernel.getFunction("test", "type15").invokeAsync("").block(); + test.getFunction("type15").invokeAsync("").block(); + + kernel.getFunction("test", "type16").invokeAsync("").block(); + test.getFunction("type16").invokeAsync("").block(); + + kernel.getFunction("test", "type17").invokeAsync("").block(); + test.getFunction("type17").invokeAsync("").block(); + + kernel.getFunction("test", "type18").invokeAsync("").block(); + test.getFunction("type18").invokeAsync("").block(); + } + + + public static class LocalExampleSkill { + + @DefineSKFunction(name = "type01") + public void Type01() { + System.out.println("Running function type 1"); + } + + @DefineSKFunction(name = "type02") + public String Type02() { + System.out.println("Running function type 2"); + return ""; + } + + @DefineSKFunction(name = "type03") + public Mono Type03Async() { + return Mono.delay(Duration.ZERO) + .map(x -> { + System.out.println("Running function type 3"); + return ""; + }); + } + + + @DefineSKFunction(name = "type04") + public void Type04(SKContext context) { + System.out.println("Running function type 4"); + } + + + @DefineSKFunction(name = "type05") + public String Type05(SKContext context) { + System.out.println("Running function type 5"); + return ""; + } + + + @DefineSKFunction(name = "type06") + public Mono Type06Async(SKContext context) { + var summarizer = context.getSkills().getFunction("SummarizeSkill", "Summarize", null); + + return summarizer + .invokeAsync("blah blah blah") + .map(summary -> { + System.out.println("Running function type 6 " + summary.getResult()); + return ""; + }); + } + + @DefineSKFunction(name = "type07") + public Mono Type07Async(SKContext context) { + return Mono.delay(Duration.ZERO) + .map(x -> { + System.out.println("Running function type 7"); + return context; + }); + } + + @DefineSKFunction(name = "type08") + public void Type08( + @SKFunctionInputAttribute(description = "?") + String x) { + System.out.println("Running function type 8"); + } + + + @DefineSKFunction(name = "type09") + public String Type09( + @SKFunctionInputAttribute(description = "?") + String x) { + System.out.println("Running function type 9"); + return ""; + } + + @DefineSKFunction(name = "type10") + public Mono Type10Async( + @SKFunctionInputAttribute(description = "?") + String x) { + return Mono.delay(Duration.ZERO) + .map(x2 -> { + System.out.println("Running function type 10"); + return ""; + }); + } + + @DefineSKFunction(name = "type11") + public void Type11( + @SKFunctionInputAttribute(description = "?") + String x, + SKContext context) { + System.out.println("Running function type 11"); + } + + + @DefineSKFunction(name = "type12") + public String Type12( + @SKFunctionInputAttribute(description = "?") + String x, + SKContext context) { + System.out.println("Running function type 12"); + return ""; + } + + @DefineSKFunction(name = "type13") + public Mono Type13Async( + @SKFunctionInputAttribute(description = "?") + String x, SKContext context) { + return Mono.delay(Duration.ZERO) + .map(x2 -> { + System.out.println("Running function type 13"); + return ""; + }); + } + + @DefineSKFunction(name = "type14") + public Mono Type14Async( + @SKFunctionInputAttribute(description = "?") + String x, SKContext context) { + return Mono.delay(Duration.ZERO) + .ignoreElement() + .map(x2 -> { + System.out.println("Running function type 14"); + return context; + }); + } + + @DefineSKFunction(name = "type15") + public Mono Type15Async(String x) { + return Mono.delay(Duration.ZERO) + .ignoreElement() + .doFinally(ignore -> System.out.println("Running function type 15")) + .then(); + } + + @DefineSKFunction(name = "type16") + public Mono Type16Async(SKContext context) { + return Mono.delay(Duration.ZERO) + .ignoreElement() + .doFinally(ignore -> System.out.println("Running function type 16")) + .then(); + } + + @DefineSKFunction(name = "type17") + public Mono Type17Async(String x, SKContext context) { + return Mono.delay(Duration.ZERO) + .ignoreElement() + .doFinally(ignore -> System.out.println("Running function type 17")) + .then(); + } + + @DefineSKFunction(name = "type18") + public Mono Type18Async() { + return Mono.delay(Duration.ZERO) + .ignoreElement() + .doFinally(ignore -> System.out.println("Running function type 18")) + .then(); + } + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example12_SequentialPlanner.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example12_SequentialPlanner.java new file mode 100644 index 0000000000..68cb569d01 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example12_SequentialPlanner.java @@ -0,0 +1,221 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.coreskills.TextSkill; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.memory.VolatileMemoryStore; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlannerRequestSettings; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Set; + +/** + * Demonstrates the + * Sequential Planner + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example12_SequentialPlanner { + + private static final Logger LOGGER = LoggerFactory.getLogger(Example12_SequentialPlanner.class); + + public static void main(String[] args) throws ConfigurationException { + poetrySamplesAsync(); + emailSamplesAsync(); + bookSamplesAsync(); + //MemorySampleAsync(); + } + + private static void poetrySamplesAsync() throws ConfigurationException { + System.out.println("======== Sequential Planner - Create and Execute Poetry Plan ========"); + var kernel = initializeKernel(); + + kernel.importSkill(new TextSkill(), "TextSkill"); + + var planner = new SequentialPlanner(kernel, null, null); + + var plan = planner.createPlanAsync("Write a poem about John Doe, then translate it into Italian, then convert it to uppercase.").block(); + + // Original plan: + // Goal: Write a poem about John Doe, then translate it into Italian. + + // Steps: + // - WriterSkill.ShortPoem INPUT='John Doe is a friendly guy who likes to help others and enjoys reading books.' => + // - WriterSkill.Translate language='Italian' INPUT='' => + + SKContext result = plan.invokeAsync().block(); + + System.out.println("Result:"); + System.out.println(result.getResult()); + } + + public static class EmailSkill { + @DefineSKFunction(name = "SendEmail", description = "Given an e-mail and message body, send an email") + public void sendEmail( + @SKFunctionInputAttribute(description = "The body of the email message to send.") + String input, + @SKFunctionParameters(description = "The email address to send email to.", name = "email_address") + String emailAddress + ) { + LOGGER.info("Emailing to " + emailAddress + "\n" + input); + } + + @DefineSKFunction(name = "GetEmailAddressAsync", description = "Lookup an email address for a person given a name") + public String getEmailAddressAsync( + @SKFunctionInputAttribute(description = "The name of the person to email.") + String input) { + return "fake@example.com"; + } + } + + private static void emailSamplesAsync() throws ConfigurationException { + System.out.println("======== Sequential Planner - Create and Execute Email Plan ========"); + var kernel = initializeKernel(); + + kernel.importSkill(new EmailSkill(), "email"); + + + SequentialPlanner planner = initPlanner(kernel, 1024); + + var plan = planner.createPlanAsync("Summarize an input, translate to french, and e-mail to John Doe").block(); + + // Original plan: + // Goal: Summarize an input, translate to french, and e-mail to John Doe + + // Steps: + // - SummarizeSkill.Summarize INPUT='' => + // - WriterSkill.Translate language='French' INPUT='' => TRANSLATED_SUMMARY + // - email.GetEmailAddress INPUT='John Doe' => EMAIL_ADDRESS + // - email.SendEmail INPUT='$TRANSLATED_SUMMARY' email_address='$EMAIL_ADDRESS' => + + System.out.println("Original plan:"); + System.out.println(plan.toManualString(false)); + + var input = + "Once upon a time, in a faraway kingdom, there lived a kind and just king named Arjun. " + + "He ruled over his kingdom with fairness and compassion, earning him the love and admiration of his people. " + + "However, the kingdom was plagued by a terrible dragon that lived in the nearby mountains and terrorized the nearby villages, " + + "burning their crops and homes. The king had tried everything to defeat the dragon, but to no avail. " + + "One day, a young woman named Mira approached the king and offered to help defeat the dragon. She was a skilled archer " + + "and claimed that she had a plan to defeat the dragon once and for all. The king was skeptical, but desperate for a solution, " + + "so he agreed to let her try. Mira set out for the dragon's lair and, with the help of her trusty bow and arrow, " + + "she was able to strike the dragon with a single shot through its heart, killing it instantly. The people rejoiced " + + "and the kingdom was at peace once again. The king was so grateful to Mira that he asked her to marry him and she agreed. " + + "They ruled the kingdom together, ruling with fairness and compassion, just as Arjun had done before. They lived " + + "happily ever after, with the people of the kingdom remembering Mira as the brave young woman who saved them from the dragon."; + + plan.invokeAsync(input).blockOptional(); + } + + private static void bookSamplesAsync() throws ConfigurationException { + System.out.println("======== Sequential Planner - Create and Execute Book Creation Plan ========"); + var kernel = initializeKernel(); + + SequentialPlanner planner = initPlanner(kernel, 1024); + + var plan = planner.createPlanAsync("Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'").block(); + + // Original plan: + // Goal: Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.' + + // Steps: + // - WriterSkill.NovelOutline chapterCount='3' INPUT='A group of kids in a club called 'The Thinking Caps' that solve mysteries and puzzles using their creativity and logic.' endMarker='' => OUTLINE + // - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='0' => CHAPTER_1_SYNOPSIS + // - WriterSkill.NovelChapter chapterIndex='1' previousChapter='' INPUT='$CHAPTER_1_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_1 + // - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='1' => CHAPTER_2_SYNOPSIS + // - WriterSkill.NovelChapter chapterIndex='2' previousChapter='$CHAPTER_1_SYNOPSIS' INPUT='$CHAPTER_2_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_2 + // - MiscSkill.ElementAtIndex count='3' INPUT='$OUTLINE' index='2' => CHAPTER_3_SYNOPSIS + // - WriterSkill.NovelChapter chapterIndex='3' previousChapter='$CHAPTER_2_SYNOPSIS' INPUT='$CHAPTER_3_SYNOPSIS' theme='Children's mystery' => RESULT__CHAPTER_3 + System.out.println(plan.invokeAsync().block().getResult()); + } + + /* + TODO + private static void memorySampleAsync() throws IOException { + System.out.println("======== Sequential Planner - Create and Execute Plan using Memory ========"); + var kernel = initializeKernel(); + + SequentialPlanner planner = initPlanner(kernel, 1024); + + kernel.importSkillsFromDirectory("samples/skills", + "CalendarSkill", + "ChatSkill", + "ChildrensBookSkill", + "ClassificationSkill", + "CodingSkill", + "FunSkill", + "IntentDetectionSkill", + "MiscSkill", + "QASkill"); + + kernel.importSkill(new EmailSkill(), "email"); + kernel.importSkill(new StaticTextSkill(), "statictext"); + kernel.importSkill(new TextSkill(), "text"); + kernel.importSkill(new Microsoft.SemanticKernel.CoreSkills.TextSkill(), "coretext"); + + var goal = "Create a book with 3 chapters about a group of kids in a club called 'The Thinking Caps.'"; + + var planner = new SequentialPlanner(kernel, new SequentialPlannerConfig { + RelevancyThreshold =0.78 + }); + + var plan = await planner.CreatePlanAsync(goal); + + System.out.println("Original plan:"); + System.out.println(plan.ToPlanString()); + } + + */ + + private static Kernel initializeKernel() throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + var kernel = SKBuilders.kernel() + .withDefaultAIService(SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("gpt-35-turbo") + .build()) + .withMemory(SKBuilders + .semanticTextMemory() + .withEmbeddingGenerator( + SKBuilders.textEmbeddingGeneration() + .withOpenAIClient(client) + .withModelId("gpt-35-turbo") + .build() + ) + .withStorage(new VolatileMemoryStore()) + .build()) + .build(); + + + // Load additional skills to enable planner to do non-trivial asks. + kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(), "SummarizeSkill"); + kernel.importSkillFromDirectory("WriterSkill", SampleSkillsUtil.detectSkillDirLocation(), "WriterSkill"); + kernel.importSkillFromDirectory("MiscSkill", SampleSkillsUtil.detectSkillDirLocation(), "MiscSkill"); + + return kernel; + } + + private static SequentialPlanner initPlanner(Kernel kernel, int maxTokens) { + return new SequentialPlanner(kernel, new SequentialPlannerRequestSettings( + null, + 100, + Set.of(), + Set.of(), + Set.of(), + maxTokens + ), null); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example13_ConversationSummarySkill.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example13_ConversationSummarySkill.java new file mode 100644 index 0000000000..7408543599 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example13_ConversationSummarySkill.java @@ -0,0 +1,196 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.coreskills.ConversationSummarySkill; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import reactor.core.publisher.Mono; + +/** + * Demonstrate the {@code com.microsoft.semantickernel.coreskills.ConversationSummarySkill} + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example13_ConversationSummarySkill { + private static final String ChatTranscript = + """ + John: Hello, how are you? + Jane: I'm fine, thanks. How are you? + John: I'm doing well, writing some example code. + Jane: That's great! I'm writing some example code too. + John: What are you writing? + Jane: I'm writing a chatbot. + John: That's cool. I'm writing a chatbot too. + Jane: What language are you writing it in? + John: I'm writing it in C#. + Jane: I'm writing it in Python. + John: That's cool. I need to learn Python. + Jane: I need to learn C#. + John: Can I try out your chatbot? + Jane: Sure, here's the link. + John: Thanks! + Jane: You're welcome. + Jane: Look at this poem my chatbot wrote: + Jane: Roses are red + Jane: Violets are blue + Jane: I'm writing a chatbot + Jane: What about you? + John: That's cool. Let me see if mine will write a poem, too. + John: Here's a poem my chatbot wrote: + John: The singularity of the universe is a mystery. + John: The universe is a mystery. + John: The universe is a mystery. + John: The universe is a mystery. + John: Looks like I need to improve mine, oh well. + Jane: You might want to try using a different model. + Jane: I'm using the GPT-3 model. + John: I'm using the GPT-2 model. That makes sense. + John: Here is a new poem after updating the model. + John: The universe is a mystery. + John: The universe is a mystery. + John: The universe is a mystery. + John: Yikes, it's really stuck isn't it. Would you help me debug my code? + Jane: Sure, what's the problem? + John: I'm not sure. I think it's a bug in the code. + Jane: I'll take a look. + Jane: I think I found the problem. + Jane: It looks like you're not passing the right parameters to the model. + John: Thanks for the help! + Jane: I'm now writing a bot to summarize conversations. I want to make sure it works when the conversation is long. + John: So you need to keep talking with me to generate a long conversation? + Jane: Yes, that's right. + John: Ok, I'll keep talking. What should we talk about? + Jane: I don't know, what do you want to talk about? + John: I don't know, it's nice how CoPilot is doing most of the talking for us. But it definitely gets stuck sometimes. + Jane: I agree, it's nice that CoPilot is doing most of the talking for us. + Jane: But it definitely gets stuck sometimes. + John: Do you know how long it needs to be? + Jane: I think the max length is 1024 tokens. Which is approximately 1024*4= 4096 characters. + John: That's a lot of characters. + Jane: Yes, it is. + John: I'm not sure how much longer I can keep talking. + Jane: I think we're almost there. Let me check. + Jane: I have some bad news, we're only half way there. + John: Oh no, I'm not sure I can keep going. I'm getting tired. + Jane: I'm getting tired too. + John: Maybe there is a large piece of text we can use to generate a long conversation. + Jane: That's a good idea. Let me see if I can find one. Maybe Lorem Ipsum? + John: Yeah, that's a good idea. + Jane: I found a Lorem Ipsum generator. + Jane: Here's a 4096 character Lorem Ipsum text: + Jane: Lorem ipsum dolor sit amet, con + Jane: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc sit amet aliquam + Jane: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc sit amet aliquam + Jane: Darn, it's just repeating stuf now. + John: I think we're done. + Jane: We're not though! We need like 1500 more characters. + John: Oh Cananda, our home and native land. + Jane: True patriot love in all thy sons command. + John: With glowing hearts we see thee rise. + Jane: The True North strong and free. + John: From far and wide, O Canada, we stand on guard for thee. + Jane: God keep our land glorious and free. + John: O Canada, we stand on guard for thee. + Jane: O Canada, we stand on guard for thee. + Jane: That was fun, thank you. Let me check now. + Jane: I think we need about 600 more characters. + John: Oh say can you see? + Jane: By the dawn's early light. + John: What so proudly we hailed. + Jane: At the twilight's last gleaming. + John: Whose broad stripes and bright stars. + Jane: Through the perilous fight. + John: O'er the ramparts we watched. + Jane: Were so gallantly streaming. + John: And the rockets' red glare. + Jane: The bombs bursting in air. + John: Gave proof through the night. + Jane: That our flag was still there. + John: Oh say does that star-spangled banner yet wave. + Jane: O'er the land of the free. + John: And the home of the brave. + Jane: Are you a Seattle Kraken Fan? + John: Yes, I am. I love going to the games. + Jane: I'm a Seattle Kraken Fan too. Who is your favorite player? + John: I like watching all the players, but I think my favorite is Matty Beniers. + Jane: Yeah, he's a great player. I like watching him too. I also like watching Jaden Schwartz. + John: Adam Larsson is another good one. The big cat! + Jane: WE MADE IT! It's long enough. Thank you! + John: Can you automate generating long text next time? + Jane: I will. + John: You're welcome. I'm glad we could help. Goodbye! + Jane: Goodbye! + """.stripIndent(); + + public static void main(String[] args) throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + + conversationSummarySkillAsync(client); + getConversationActionItemsAsync(client); + getConversationTopicsAsync(client); + } + + private static void conversationSummarySkillAsync(OpenAIAsyncClient client) { + System.out.println("======== SampleSkills - Conversation Summary Skill - Summarize ========"); + Kernel kernel = initializeKernel(client); + + ReadOnlyFunctionCollection conversationSummarySkill = + kernel.importSkill(new ConversationSummarySkill(kernel), null); + + Mono summary = conversationSummarySkill + .getFunction("SummarizeConversation", SKFunction.class) + .invokeAsync(ChatTranscript); + + System.out.println("Generated Summary (This may take some time):"); + System.out.println(summary.block().getResult()); + } + + + private static void getConversationActionItemsAsync(OpenAIAsyncClient client) { + System.out.println("======== SampleSkills - Conversation Summary Skill - Action Items ========"); + Kernel kernel = initializeKernel(client); + + ReadOnlyFunctionCollection conversationSummarySkill = + kernel.importSkill(new ConversationSummarySkill(kernel), null); + + Mono summary = conversationSummarySkill + .getFunction("GetConversationActionItems", SKFunction.class) + .invokeAsync(ChatTranscript); + + System.out.println("Generated Action Items (This may take some time):"); + System.out.println(summary.block().getResult()); + } + + private static void getConversationTopicsAsync(OpenAIAsyncClient client) { + Kernel kernel = initializeKernel(client); + + ReadOnlyFunctionCollection conversationSummarySkill = + kernel.importSkill(new ConversationSummarySkill(kernel), null); + + Mono summary = conversationSummarySkill + .getFunction("GetConversationTopics", SKFunction.class) + .invokeAsync(ChatTranscript); + + System.out.println("Generated Topics:"); + System.out.println(summary.block().getResult()); + } + + private static Kernel initializeKernel(OpenAIAsyncClient client) { + TextCompletion textCompletion = SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build(); + + return SKBuilders.kernel() + .withAIService("text-davinci-003", textCompletion, true, TextCompletion.class).build(); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example14_SemanticMemory.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example14_SemanticMemory.java new file mode 100644 index 0000000000..d01b55c8e7 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example14_SemanticMemory.java @@ -0,0 +1,175 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.connectors.memory.azurecognitivesearch.AzureCognitiveSearchMemoryStore; +import com.microsoft.semantickernel.memory.VolatileMemoryStore; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + + +/** + * Demonstrate two examples about SK Semantic Memory: + * + * 1. Memory using Azure Cognitive Search. + * 2. Memory using a custom embedding generator and vector engine. + * + * Semantic Memory allows to store your data like traditional DBs, + * adding the ability to query it using natural language. + *

+ * You must + * create an Azure Cognitive Search service in the portal to run this example. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example14_SemanticMemory { + private static final String MEMORY_COLLECTION_NAME = "SKGitHub"; + + public static void main(String[] args) throws Exception { + System.out.println("=============================================================="); + System.out.println("======== Semantic Memory using Azure Cognitive Search ========"); + System.out.println("=============================================================="); + + var openAIAsyncClient = SamplesConfig.getClient(); + + /* This example leverages Azure Cognitive Search to provide SK with Semantic Memory. + * + * Azure Cognitive Search automatically indexes your data semantically, so you don't + * need to worry about embedding generation. + */ + var kernelWithACS = SKBuilders.kernel() + .withMemoryStorage( + new AzureCognitiveSearchMemoryStore(System.getenv("ACS_ENDPOINT"), System.getenv("ACS_API_KEY"))) + .withDefaultAIService(SKBuilders.textEmbeddingGeneration() + .withOpenAIClient(openAIAsyncClient) + .withModelId("text-embedding-ada-002") + .build()) + .build(); + + runExampleAsync(kernelWithACS).block(); + + System.out.println("===================================================="); + System.out.println("======== Semantic Memory (volatile, in RAM) ========"); + System.out.println("===================================================="); + + /* You can build your own semantic memory combining an Embedding Generator + * with a Memory storage that supports search by similarity (ie semantic search). + * + * In this example we use a volatile memory, a local simulation of a vector DB. + * + * You can replace VolatileMemoryStore with Qdrant (see QdrantMemoryStore connector) + * or implement your connectors for Pinecone, Vespa, Postgres + pgvector, SQLite VSS, etc. + */ + + var kernelWithCustomDb = SKBuilders.kernel() + .withDefaultAIService(SKBuilders.textEmbeddingGeneration() + .withOpenAIClient(openAIAsyncClient) + .withModelId("text-embedding-ada-002") + .build()) + .withMemoryStorage(new VolatileMemoryStore.Builder().build()) + .build(); + + runExampleAsync(kernelWithCustomDb).block(); + } + + public static Mono runExampleAsync(Kernel kernel) { + return storeMemoryAsync(kernel) + .then(searchMemoryAsync(kernel, "How do I get started?")) + + /* + Output: + + Query: How do I get started? + + Result 1: + URL: : https://github.com/microsoft/semantic-kernel/blob/main/README.md + Title : README: Installation, getting started, and how to contribute + + Result 2: + URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet-jupyter-notebooks/00-getting-started.ipynb + Title : Jupyter notebook describing how to get started with the Semantic Kernel + + */ + + .then(searchMemoryAsync(kernel, "Can I build a chat with SK?")); + + /* + Output: + + Query: Can I build a chat with SK? + + Result 1: + URL: : https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT + Title : Sample demonstrating how to create a chat skill interfacing with ChatGPT + + Result 2: + URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md + Title : README: README associated with a sample chat summary react-based webapp + + */ + } + + private static Mono searchMemoryAsync(Kernel kernel, String query) { + return kernel.getMemory().searchAsync(MEMORY_COLLECTION_NAME, query, 2, 0.5f, false) + .mapNotNull(memories -> { + System.out.println("\nQuery: " + query + "\n"); + for (int n = 0; n < memories.size(); n++) { + var memory = memories.get(n); + System.out.println("Result " + (n + 1) + ":"); + System.out.println(" URL: : " + memory.getMetadata().getId()); + System.out.println(" Title : " + memory.getMetadata().getDescription()); + System.out.println(); + } + System.out.println("----------------------"); + return null; + }); + } + + private static Mono storeMemoryAsync(Kernel kernel) { + /* Store some data in the semantic memory. + * + * When using Azure Cognitive Search the data is automatically indexed on write. + * + * When using the combination of VolatileStore and Embedding generation, SK takes + * care of creating and storing the index + */ + + return Flux.fromIterable(sampleData().entrySet()) + .doFirst(() -> System.out.println("\nAdding some GitHub file URLs and their descriptions to the semantic memory.")) + .map(entry -> { + System.out.println("Save '" + entry.getKey() + "' to memory."); + return kernel.getMemory().saveReferenceAsync( + MEMORY_COLLECTION_NAME, + entry.getValue(), + entry.getKey(), + "GitHub", + entry.getValue(), + null); + } + ) + .mapNotNull(Mono::block) + .doFinally(signalType -> System.out.println("\n----------------------")) + .then(); + } + + private static Map sampleData() { + return Arrays.stream(new String[][]{ + {"https://github.com/microsoft/semantic-kernel/blob/main/README.md", "README: Installation, getting started, and how to contribute"}, + {"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb", "Jupyter notebook describing how to pass prompts from a file to a semantic skill or function"}, + {"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/00-getting-started.ipynb", "Jupyter notebook describing how to get started with the Semantic Kernel"}, + {"https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT", "Sample demonstrating how to create a chat skill interfacing with ChatGPT"}, + {"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/VolatileMemoryStore.cs", "C# class that defines a volatile embedding store"}, + {"https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet/KernelHttpServer/README.md", "README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4"}, + {"https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md", "README: README associated with a sample chat summary react-based webapp"}, + }).collect(Collectors.toMap(element -> element[0], element -> element[1])); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example15_MemorySkill.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example15_MemorySkill.java new file mode 100644 index 0000000000..3198cdfefb --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example15_MemorySkill.java @@ -0,0 +1,229 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration; +import com.microsoft.semantickernel.coreskills.TextMemorySkill; +import com.microsoft.semantickernel.memory.MemoryStore; +import com.microsoft.semantickernel.memory.VolatileMemoryStore; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.util.List; +import java.util.stream.Collectors; +import reactor.core.publisher.Mono; + +/** + * Demonstrates saving and retrieving memories. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example15_MemorySkill { + private static final String MEMORY_COLLECTION_NAME = "aboutMe"; + + public static void main(String[] args) { + runAsync().block(); + } + + public static Mono runAsync() { + // ========= Create a kernel ========= + OpenAIAsyncClient client = null; + try { + client = SamplesConfig.getClient(); + } catch (Exception e) { + return Mono.error(e); + } + + TextCompletion textCompletionService = + SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build(); + + TextEmbeddingGeneration textEmbeddingGenerationService = + SKBuilders.textEmbeddingGeneration() + .withOpenAIClient(client) + .withModelId("text-embedding-ada-002") + .build(); + + MemoryStore memoryStore = new VolatileMemoryStore.Builder().build(); + + Kernel kernel = SKBuilders.kernel() + .withDefaultAIService(textCompletionService) + .withDefaultAIService(textEmbeddingGenerationService) + .withMemoryStorage(memoryStore) + .build(); + + // ========= Store memories using the kernel ========= + + kernel.getMemory().saveInformationAsync(MEMORY_COLLECTION_NAME, "My name is Andrea", "info1", null, null).block(); + kernel.getMemory().saveInformationAsync(MEMORY_COLLECTION_NAME, "I work as a tourist operator", "info2", null, null).block(); + kernel.getMemory().saveInformationAsync(MEMORY_COLLECTION_NAME, "I've been living in Seattle since 2005", "info3", null, null).block(); + kernel.getMemory().saveInformationAsync(MEMORY_COLLECTION_NAME, "I visited France and Italy five times since 2015", "info4", null, null).block(); + + // ========= Store memories using semantic function ========= + + // Add Memory as a skill for other functions + TextMemorySkill memorySkill = new TextMemorySkill(); + kernel.importSkill(memorySkill, "memory"); + + // Build a semantic function that saves info to memory + PromptTemplateConfig.CompletionConfig completionConfig = SKBuilders.completionConfig() + .temperature(0.2) + .topP(0.5) + .presencePenalty(0) + .frequencyPenalty(0) + .maxTokens(2000) + .build(); + + CompletionSKFunction saveFunctionDefinition = SKBuilders.completionFunctions() + .withKernel(kernel) + .withPromptTemplate("{{memory.save $info}}") + .withFunctionName("save") + .withDescription("save information to memory") + .withCompletionConfig(completionConfig) + .build(); + + CompletionSKFunction memorySaver = + kernel.registerSemanticFunction(saveFunctionDefinition); + + SKContext context = SKBuilders.context() + .withMemory(kernel.getMemory()) + .withSkills(kernel.getSkills()) + .build(); + + context.setVariable(TextMemorySkill.COLLECTION_PARAM, MEMORY_COLLECTION_NAME) + .setVariable(TextMemorySkill.KEY_PARAM, "info5") + .setVariable(TextMemorySkill.INFO_PARAM, "My family is from New York"); + + memorySaver.invokeAsync(context).block(); + + // ========= Test memory remember ========= + System.out.println("========= Example: Recalling a Memory ========="); + + // create a new context to avoid using the variables from the previous example + context = SKBuilders.context() + .withMemory(kernel.getMemory()) + .withSkills(kernel.getSkills()) + .build(); + + String answer = memorySkill.retrieveAsync(MEMORY_COLLECTION_NAME, "info1", context).block(); + System.out.printf("Memory associated with 'info1': %s%n", answer); + /* + Output: + "Memory associated with 'info1': My name is Andrea + */ + + // ========= Test memory recall ========= + System.out.println("========= Example: Recalling an Idea ========="); + + List answers = memorySkill.recallAsync( + "Where did I grow up?", + MEMORY_COLLECTION_NAME, + 0, + 2, + context).block(); + + System.out.println("Ask: Where did I grow up?"); + System.out.printf("Answer:%n\t%s%n", answers.stream().collect(Collectors.joining("\",\"", "[\"", "\"]"))); + + answers = memorySkill.recallAsync( + "Where do I live?", + MEMORY_COLLECTION_NAME, + 0, + 2, + context).block(); + + System.out.println("Ask: Where do I live?"); + System.out.printf("Answer:%n\t%s%n", answers.stream().collect(Collectors.joining("\",\"", "[\"", "\"]"))); + + /* + Output: + + Ask: where did I grow up? + Answer: + ["My family is from New York","I've been living in Seattle since 2005"] + + Ask: where do I live? + Answer: + ["I've been living in Seattle since 2005","My family is from New York"] + */ + + // ========= Use memory in a semantic function ========= + System.out.println("========= Example: Using Recall in a Semantic Function ========="); + + // Build a semantic function that uses memory to find facts + String prompt = + "Consider only the facts below when answering questions.\n" + + "About me: {{memory.recall 'where did I grow up?'}}\n" + + "About me: {{memory.recall 'where do I live?'}}\n" + + "Question: {{$input}}\n" + + "Answer: "; + + CompletionSKFunction recallFunctionDefinition = SKBuilders.completionFunctions() + .withKernel(kernel) + .withPromptTemplate(prompt) + .withCompletionConfig(completionConfig) + .build(); + + SKFunction aboutMeOracle = kernel.registerSemanticFunction(recallFunctionDefinition); + + context.setVariable(TextMemorySkill.COLLECTION_PARAM, MEMORY_COLLECTION_NAME) + .setVariable(TextMemorySkill.RELEVANCE_PARAM, "0.75"); + + SKContext result = aboutMeOracle.invokeAsync("Do I live in the same town where I grew up?", context, null).block(); + + System.out.println("Do I live in the same town where I grew up?\n"); + System.out.println(result.getResult()); + + /* + Output: + + Do I live in the same town where I grew up? + + No, I do not live in the same town where I grew up since my family is from New York and I have been living in Seattle since 2005. + */ + + // ========= Remove a memory ========= + System.out.println("========= Example: Forgetting a Memory ========="); + + context.setVariable("fact1", "What is my name?") + .setVariable("fact2", "What do I do for a living?") + .setVariable(TextMemorySkill.RELEVANCE_PARAM, "0.75"); + + result = aboutMeOracle.invokeAsync("Tell me a bit about myself", context, null).block(); + + System.out.println("Tell me a bit about myself\n"); + System.out.println(result.getResult()); + + /* + Approximate Output: + Tell me a bit about myself + + My name is Andrea and my family is from New York. I work as a tourist operator. + */ + + memorySkill.removeAsync(MEMORY_COLLECTION_NAME, "info1", context).block(); + + result = aboutMeOracle.invokeAsync("Tell me a bit about myself", context, null).block(); + + System.out.println("Tell me a bit about myself\n"); + System.out.println(result.getResult()); + + /* + Approximate Output: + Tell me a bit about myself + + I'm from a family originally from New York and I work as a tourist operator. I've been living in Seattle since 2005. + */ + + return Mono.empty(); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example17_ChatGPT.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example17_ChatGPT.java new file mode 100644 index 0000000000..ee93e82787 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example17_ChatGPT.java @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.connectors.ai.openai.chatcompletion.OpenAIChatHistory; +import com.microsoft.semantickernel.exceptions.ConfigurationException; + +/** + * Demonstrates the use of Semantic Kernel with OpenAI ChatGPT API + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example17_ChatGPT { + + public static void main(String[] args) throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + + Kernel kernel = SKBuilders.kernel() + .withAIService( + "chat-test", + SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("chat-test") + .build(), + true, + ChatCompletion.class + ) + .build(); + + ChatCompletion chatGPT = kernel.getService(null, ChatCompletion.class); + + OpenAIChatHistory chatHistory = chatGPT.createNewChat("You are a librarian, expert about books"); + + // First user message + chatHistory.addUserMessage("Hi, I'm looking for book suggestions"); + messageOutputAsync(chatHistory); + + // First bot assistant message + String reply = chatGPT.generateMessageAsync(chatHistory, null).block(); + chatHistory.addAssistantMessage(reply); + messageOutputAsync(chatHistory); + + // Second user message + chatHistory.addUserMessage( + "I love history and philosophy, I'd like to learn something new about Greece, any suggestion?"); + messageOutputAsync(chatHistory); + + // Second bot assistant message + reply = chatGPT.generateMessageAsync(chatHistory, null).block(); + chatHistory.addAssistantMessage(reply); + messageOutputAsync(chatHistory); + } + + private static void messageOutputAsync(ChatHistory chatHistory) { + ChatHistory.Message message = chatHistory.getMessages().get(chatHistory.getMessages().size() - 1); + + System.out.println(message.getAuthorRoles() + ": " + message.getContent()); + System.out.println("------------------------"); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example25_ReadOnlyMemoryStore.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example25_ReadOnlyMemoryStore.java new file mode 100644 index 0000000000..bb787775e8 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example25_ReadOnlyMemoryStore.java @@ -0,0 +1,287 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.memory.MemoryRecord; +import com.microsoft.semantickernel.memory.MemoryStore; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; +import reactor.util.function.Tuples; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +/** + * Demonstrates a custom implementation of {@code MemoryStore} that is read only. + * In this sample, the data is stored in a JSON String and deserialized into an + * {@code MemoryRecord[]}. For this specific sample, the implementation + * of {@code MemoryStore} has a single collection, and thus does not need to be named. + * It also assumes that the JSON formatted data can be deserialized into {@code MemoryRecord} objects. + * @see MemoryRecord + * @see MemoryStore + */ +public class Example25_ReadOnlyMemoryStore +{ + public static void main(String[] args) { + RunAsync().block(); + } + + public static Mono RunAsync() + { + var store = new ReadOnlyMemoryStore(JSON_VECTOR_ENTRIES); + + var embedding = new Embedding(Arrays.asList(22f, 4f, 6f)); + + System.out.println("Reading data from custom read-only memory store"); + Mono mono = store.getAsync("collection", "key3", true) + .mapNotNull(memoryRecord -> { + String memoryRecordId = memoryRecord.getMetadata().getId(); + Embedding memoryRecordEmbedding = memoryRecord.getEmbedding(); + System.out.printf("ID = %s, Embedding = %s%n", memoryRecordId, embeddingVectorToString(memoryRecordEmbedding)); + return memoryRecord; + }); + + mono = mono.then( + store.getNearestMatchAsync("collection", embedding, 0f, true) + .mapNotNull(result -> { + Float similarity = result.getT2().floatValue(); + MemoryRecord memoryRecord = result.getT1(); + Embedding memoryRecordEmbedding = memoryRecord.getEmbedding(); + System.out.printf("Embedding = %s, Similarity = %f%n", embeddingVectorToString(memoryRecordEmbedding), similarity); + return result; + } + ) + ); + + return mono.then(); + + } + + private static String embeddingVectorToString(Embedding embedding) { + StringJoiner stringJoiner = new StringJoiner(", ", "[", "]"); + embedding.getVector().stream().map(Number::toString).forEach(stringJoiner::add); + return stringJoiner.toString(); + } + + private static class ReadOnlyMemoryStore implements MemoryStore + { + private final MemoryRecord[] _memoryRecords; + private final int _vectorSize = 3; + + public ReadOnlyMemoryStore(String valueString) + { + try { + _memoryRecords = new ObjectMapper().readValue(valueString, MemoryRecord[].class); + } catch (JsonProcessingException e) { + throw new RuntimeException("Unable to deserialize memory records"); + } + } + + @Override + public Mono createCollectionAsync(String collectionName) + { + return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store")); + } + + @Override + public Mono deleteCollectionAsync(String collectionName) + { + return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store")); + } + + @Override + public Mono doesCollectionExistAsync(String collectionName) + { + return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store")); + } + + @Override + public Mono getAsync(String collectionName, String key, boolean withEmbedding) + { + // Note: with this simple implementation, the MemoryRecord will always contain the embedding. + return Mono.justOrEmpty( + Arrays.stream(this._memoryRecords) + .filter(it -> it.getKey().equals(key)) + .findFirst() + ); + } + + @Override + public Mono> getBatchAsync(String collectionName, Collection keys, boolean withEmbeddings) + { + // Note: with this simple implementation, the MemoryRecord will always contain the embedding. + return Mono.just( + Arrays.stream(this._memoryRecords) + .filter(it -> keys.contains(it.getKey())) + .collect(Collectors.toList()) + ); + } + + @Override + public Mono> getCollectionsAsync() + { + return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store")); + } + + @Override + public Mono> getNearestMatchAsync(String collectionName, Embedding embedding, float minRelevanceScore, + boolean withEmbedding) + { + // Note: with this simple implementation, the MemoryRecord will always contain the embedding. + return Mono.justOrEmpty( + Arrays.stream(this._memoryRecords) + .map(it -> { + Embedding memoryRecordEmbedding = + it.getEmbedding(); + float cosineSimilarity = -1f; + try { + cosineSimilarity = embedding.cosineSimilarity(memoryRecordEmbedding); + } catch (IllegalArgumentException e) { + // Vectors cannot have zero norm + } + return Tuples.of(it, cosineSimilarity); + }) + .filter(it -> it.getT2() >= minRelevanceScore) + .max(Comparator.comparing(Tuple2::getT2, Float::compare)) + ); + } + + @Override + public Mono>> getNearestMatchesAsync(String collectionName, Embedding embedding, int limit, + float minRelevanceScore, boolean withEmbeddings) + { + // Note: with this simple implementation, the MemoryRecord will always contain the embedding. + return Mono.justOrEmpty( + Arrays.stream(this._memoryRecords) + .map(it -> { + Embedding memoryRecordEmbedding = + it.getEmbedding(); + float cosineSimilarity = -1f; + try { + cosineSimilarity = embedding.cosineSimilarity(memoryRecordEmbedding); + } catch (IllegalArgumentException e) { + // Vectors cannot have zero norm + } + return Tuples.of(it, cosineSimilarity); + }) + .filter(it -> it.getT2() >= (float)minRelevanceScore) + // sort by similarity score, descending + .sorted(Comparator.comparing(Tuple2::getT2, (a,b) -> Float.compare(b, a))) + .limit(limit) + .collect(Collectors.toList()) + ); + + + } + + @Override + public Mono removeAsync(String collectionName, String key) + { + return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store")); + } + + @Override + public Mono removeBatchAsync(String collectionName, Collection keys) + { + return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store")); + } + + @Override + public Mono upsertAsync(String collectionName, MemoryRecord record) + { + return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store")); + } + + @Override + public Mono> upsertBatchAsync(String collectionName, Collection records) + { + return Mono.error(() -> new UnsupportedOperationException("This is a read-only memory store")); + } + } + + private static final String JSON_VECTOR_ENTRIES = """ + [ + { + "embedding": { + "vector": [0, 0, 0 ] + }, + "metadata": { + "is_reference": false, + "external_source_name": "externalSourceName", + "id": "Id1", + "description": "description", + "text": "text", + "additional_metadata" : "value:" + }, + "key": "key1", + "timestamp": null + }, + { + "embedding": { + "vector": [0, 0, 10 ] + }, + "metadata": { + "is_reference": false, + "external_source_name": "externalSourceName", + "id": "Id2", + "description": "description", + "text": "text", + "additional_metadata" : "value:" + }, + "key": "key2", + "timestamp": null + }, + { + "embedding": { + "vector": [1, 2, 3 ] + }, + "metadata": { + "is_reference": false, + "external_source_name": "externalSourceName", + "id": "Id3", + "description": "description", + "text": "text", + "additional_metadata" : "value:" + }, + "key": "key3", + "timestamp": null + }, + { + "embedding": { + "vector": [-1, -2, -3 ] + }, + "metadata": { + "is_reference": false, + "external_source_name": "externalSourceName", + "id": "Id4", + "description": "description", + "text": "text", + "additional_metadata" : "value:" + }, + "key": "key4", + "timestamp": null + }, + { + "embedding": { + "vector": [12, 8, 4 ] + }, + "metadata": { + "is_reference": false, + "external_source_name": "externalSourceName", + "id": "Id5", + "description": "description", + "text": "text", + "additional_metadata" : "value:" + }, + "key": "key5", + "timestamp": null + } + ] + """.replaceAll(" |\\n", ""); +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example28_ActionPlanner.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example28_ActionPlanner.java new file mode 100644 index 0000000000..4e95324e4c --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example28_ActionPlanner.java @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.coreskills.TextSkill; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.planner.actionplanner.ActionPlanner; + +/** + * Demonstrates the + * Action Planner + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example28_ActionPlanner { + public static void main(String[] args) throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + + System.out.println("======== Action Planner ========"); + + var kernel = SKBuilders.kernel() + .withDefaultAIService(SKBuilders.textCompletion() + .withModelId("text-davinci-002") + .withOpenAIClient(client) + .build()) + .build(); + + kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(), "SummarizeSkill"); + + kernel.importSkillFromDirectory("WriterSkill", SampleSkillsUtil.detectSkillDirLocation(), "WriterSkill"); + + kernel.importSkill(new TextSkill(), "TextSkill"); + + // Create an instance of ActionPlanner. + // The ActionPlanner takes one goal and returns a single function to execute. + var planner = new ActionPlanner(kernel, null); + + // We're going to ask the planner to find a function to achieve this goal. + var goal = "Write a poem about Cleopatra."; + + // The planner returns a plan, consisting of a single function + // to execute and achieve the goal requested. + var plan = planner.createPlanAsync(goal).block(); + + // Show the result, which should match the given goal + System.out.println(plan.getName()); + + System.out.println(plan.invokeAsync(goal).block().getResult()); + + /* Output: + * + * Cleopatra was a queen + * But she didn't act like one + * She was more like a teen + + * She was always on the scene + * And she loved to be seen + * But she didn't have a queenly bone in her body + */ + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example29_Tokenizer.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example29_Tokenizer.java new file mode 100644 index 0000000000..16590fe4db --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example29_Tokenizer.java @@ -0,0 +1,86 @@ +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.microsoft.semantickernel.GPT3Tokenizer; + +/** + * Demonstrates how to count tokens using GPT tokenizer. The number of tokens affects + * API calls cost and each model has a maximum amount of tokens it can process and generate. + * This example is specific to OpenAI models, which use the tokenization described here: + * OpenAI tokenizer + * If you use Semantic Kernel with other models, the tokenization logic is most probably different, + * and you should not use the GPT tokenizer. + */ +public class Example29_Tokenizer { + + public static void main(String[] args) { + // Example 1 + String sentence = "Some text on one line"; + int tokenCount = GPT3Tokenizer.encode(sentence).size(); + + System.out.println("---"); + System.out.println(sentence); + System.out.println("Tokens: " + tokenCount); + System.out.println("---\n\n"); + + // Example 2 + sentence = "⭐⭐"; + tokenCount = GPT3Tokenizer.encode(sentence).size(); + + System.out.println("The following example contains emojis which require several tokens."); + System.out.println("---"); + System.out.println(sentence); + System.out.println("Tokens: " + tokenCount); + System.out.println("---\n\n"); + + // Example 3 + sentence = "Some text on\ntwo lines"; + tokenCount = GPT3Tokenizer.encode(sentence).size(); + + System.out.println("The following example uses Unix '\\n' line separator."); + System.out.println("---"); + System.out.println(sentence); + System.out.println("Tokens: " + tokenCount); + System.out.println("---\n\n"); + + // Example 4 + sentence = "Some text on\r\ntwo lines"; + tokenCount = GPT3Tokenizer.encode(sentence).size(); + + System.out.println("The following example uses Windows '\\r\\n' line separator."); + System.out.println("---"); + System.out.println(sentence); + System.out.println("Tokens: " + tokenCount); + System.out.println("---\n\n"); + + /* + Output: + --- + Some text on one line + Tokens: 5 + --- + + + The following example contains emojis which require several tokens. + --- + ⭐⭐ + Tokens: 6 + --- + + + The following example uses Unix '\n' line separator. + --- + Some text on + two lines + Tokens: 6 + --- + + + The following example uses Windows '\r\n' line separator. + --- + Some text on + two lines + Tokens: 7 + --- + */ + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example33_StreamingChat.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example33_StreamingChat.java new file mode 100644 index 0000000000..e4cff30c8c --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example33_StreamingChat.java @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import reactor.core.publisher.Mono; + +import java.util.function.BiFunction; + +import static com.microsoft.semantickernel.chatcompletion.ChatHistory.AuthorRoles.Assistant; + +/** + * Demonstrates how to use Semantic Kernel with Text Completion as streaming + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example33_StreamingChat { + public static void main(String[] args) throws ConfigurationException { + StartStreamingChatAsync(); + } + + private static void StartStreamingChatAsync() throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + + ChatCompletion chatCompletion = SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("gpt-35-turbo") + .build(); + + System.out.println("Chat content:"); + System.out.println("------------------------"); + + var chatHistory = chatCompletion.createNewChat("You are a librarian, expert about books"); + messageOutput(chatHistory); + + // First user message + chatHistory.addMessage(ChatHistory.AuthorRoles.User, "Hi, I'm looking for book suggestions"); + messageOutput(chatHistory); + + // First bot assistant message + streamMessageOutputAsync(chatCompletion, chatHistory, Assistant); + + // Second user message + chatHistory.addMessage(ChatHistory.AuthorRoles.User, "I love history and philosophy, I'd like to learn something new about Greece, any suggestion?"); + messageOutput(chatHistory); + + // Second bot assistant message + streamMessageOutputAsync(chatCompletion, chatHistory, Assistant); + } + + private static void streamMessageOutputAsync(ChatCompletion chatGPT, ChatHistory chatHistory, ChatHistory.AuthorRoles authorRole) { + System.out.println(authorRole.name() + ": "); + + BiFunction agg = (o, o2) -> o + o2; + + Mono mono = chatGPT + .generateMessageStream(chatHistory, null) + .reduce("", agg); + + String fullMessage = mono.block(); + System.out.println(fullMessage); + System.out.println("\n------------------------"); + chatHistory.addMessage(authorRole, fullMessage); + } + + private static void messageOutput(ChatHistory chatHistory) { + var message = chatHistory.getMessages().get(chatHistory.getMessages().size() - 1); + + System.out.println(message.getAuthorRoles().name() + " " + message.getContent()); + System.out.println("------------------------"); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example51_StepwisePlanner.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example51_StepwisePlanner.java new file mode 100644 index 0000000000..54e8180a3a --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/Example51_StepwisePlanner.java @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.samples.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.coreskills.TimeSkill; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.stepwiseplanner.DefaultStepwisePlanner; +import com.microsoft.semantickernel.planner.stepwiseplanner.StepwisePlanner; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.util.Locale; +import reactor.core.publisher.Mono; + +/** + * Demonstrates the + * Stepwise Planner + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class Example51_StepwisePlanner { + + // Fake a search engine skill so that users do not need to have a search engine API key to run this example + public static class WebSearchEngineSkill { + + @DefineSKFunction(description = "Perform a web search.", name = "search") + public Mono search( + @SKFunctionParameters(description = "Text to search for", name = "query") + String input, + @SKFunctionParameters(description = "Number of results", name = "count", defaultValue = "1", type = Integer.class) + Integer count, + @SKFunctionParameters(description = "Number of results to skip", name = "offset", defaultValue = "0", type = Integer.class) + Integer offset) { + + String question = input.toLowerCase(Locale.ROOT); + + if (question.contains("year")) { + return Mono.just("1930"); + } + + throw new RuntimeException("Unable to find answer to question: " + input); + } + } + + // Fake a calculator + public static class AdvancedCalculator { + + @DefineSKFunction(description = "Useful for getting the result of a non-trivial math expression.", name = "Calculator") + public Mono Calculator( + @SKFunctionParameters(description = "A valid mathematical expression that could be executed by a calculator capable of more advanced math functions like sin/cosine/floor.", name = "input") + String input) { + if ("1930/2".equals(input)) { + return Mono.just("965"); + } else { + return Mono.error(new RuntimeException("Unknown calculation")); + } + } + } + + public static void main(String[] args) throws ConfigurationException { + + String[] questions = new String[]{ + "What year is the first world cup divided by 2", + }; + + for (String question : questions) { + System.out.println("Result: " + runChatCompletion(question).block().getResult()); + + // Currently due to token limits, not supporting text completion + //System.out.println("Result: " + runTextCompletion(question).block().getResult()); + } + + } + + private static Mono runTextCompletion(String question) throws ConfigurationException { + System.out.println("RunTextCompletion"); + var kernel = getKernel(false); + return runWithQuestion(kernel, question); + } + + private static Mono runChatCompletion(String question) throws ConfigurationException { + System.out.println("RunChatCompletion"); + var kernel = getKernel(true); + return runWithQuestion(kernel, question); + } + + private static Mono runWithQuestion(Kernel kernel, String question) { + var webSearchEngineSkill = new WebSearchEngineSkill(); + + kernel.importSkill(webSearchEngineSkill, "WebSearch"); + kernel.importSkill(new AdvancedCalculator(), "AdvancedCalculator"); + kernel.importSkill(new TimeSkill(), "time"); + + System.out.println("*****************************************************"); + System.out.println("Question: " + question); + + StepwisePlanner planner = new DefaultStepwisePlanner(kernel, null, null, null); + + var plan = planner.createPlan(question); + + return plan.invokeAsync(SKBuilders.context().withKernel(kernel).build()); + } + + private static Kernel getKernel(boolean useChat) throws ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + TextCompletion textCompletion; + + if (useChat) { + textCompletion = SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("gpt-35-turbo") + .build(); + + } else { + textCompletion = SKBuilders.textCompletion() + .withOpenAIClient(client) + .withModelId("text-davinci-003") + .build(); + } + + return SKBuilders.kernel() + .withDefaultAIService(textCompletion) + .build(); + } +} \ No newline at end of file diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java new file mode 100644 index 0000000000..0f0d1379c3 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/RunAll.java @@ -0,0 +1,48 @@ +package com.microsoft.semantickernel.samples.syntaxexamples; + +import java.util.Arrays; +import java.util.List; + +/** + * Run all the syntax examples. + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class RunAll { + public interface MainMethod { + void run(String[] args) throws Exception; + } + + public static void main(String[] args) { + List mains = Arrays.asList( + Example01_NativeFunctions::main, + Example02_Pipeline::main, + Example03_Variables::main, + Example04_CombineLLMPromptsAndNativeCode::main, + Example05_InlineFunctionDefinition::main, + Example06_TemplateLanguage::main, + Example08_RetryHandler::main, + Example09_FunctionTypes::main, + Example12_SequentialPlanner::main, + Example13_ConversationSummarySkill::main, + Example14_SemanticMemory::main, + Example15_MemorySkill::main, + Example17_ChatGPT::main, + Example25_ReadOnlyMemoryStore::main, + Example28_ActionPlanner::main, + Example29_Tokenizer::main, + Example33_StreamingChat::main, + Example51_StepwisePlanner::main + ); + + mains.forEach(mainMethod -> { + try { + mainMethod.run(args); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/SampleSkillsUtil.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/SampleSkillsUtil.java new file mode 100644 index 0000000000..daffd76d01 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/SampleSkillsUtil.java @@ -0,0 +1,30 @@ +package com.microsoft.semantickernel.samples.syntaxexamples; + +import java.nio.file.Files; +import java.nio.file.Path; + +public class SampleSkillsUtil { + + public static final String SAMPLES_SKILLS_DIR = "samples/skills"; + + /** + * Detects the location of the sample skill directory by searching up til the top of the repository. + */ + public static String detectSkillDirLocation() { + Path dir = Path.of(System.getProperty("user.dir")); + + do { + if (Files.isDirectory(dir.resolve(SAMPLES_SKILLS_DIR))) { + return dir.resolve(SAMPLES_SKILLS_DIR).toFile().getAbsolutePath(); + } + + if (Files.exists(dir.resolve(".gitignore"))) { + // We've reached the root of the repo + throw new RuntimeException("Could not find skill directory"); + } + + } while ((dir = dir.getParent()) != null); + + throw new RuntimeException("Could not find skill directory"); + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Java_Example01_ResourceLoading.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Java_Example01_ResourceLoading.java new file mode 100644 index 0000000000..af67a5b820 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Java_Example01_ResourceLoading.java @@ -0,0 +1,41 @@ +package com.microsoft.semantickernel.samples.syntaxexamples.javaspecific; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.orchestration.SKFunction; + +import java.io.IOException; + +/** + * Import a skill from resources. + */ +public class Java_Example01_ResourceLoading { + + public static void main(String[] args) throws IOException { + Kernel kernel = SKBuilders.kernel() + .build(); + + kernel.importSkillFromResources( + "Plugins", + "ExamplePlugins", + "ExampleFunction", + Java_Example01_ResourceLoading.class + ); + + SKFunction function = kernel.getSkills().getFunctions("ExamplePlugins").getFunction("ExampleFunction"); + + System.out.println("Loaded function: " + function.getDescription()); + + + kernel.importSkillFromResources( + "Plugins", + "ExamplePlugins", + "ExampleFunctionRoot" + ); + function = kernel.getSkills().getFunctions("ExamplePlugins").getFunction("ExampleFunctionRoot"); + + System.out.println("Loaded function from classpath root: " + function.getDescription()); + + + } +} diff --git a/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/SequentialPlanner_AnswerQuestion.java b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/SequentialPlanner_AnswerQuestion.java new file mode 100644 index 0000000000..d8b3a388b8 --- /dev/null +++ b/java/samples/sample-code/src/main/java/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/SequentialPlanner_AnswerQuestion.java @@ -0,0 +1,81 @@ +package com.microsoft.semantickernel.samples.syntaxexamples.javaspecific; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.SamplesConfig; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.exceptions.ConfigurationException; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +/** + * Using Sequential Planner to take the input as a question and answer it finding any information needed. + *

+ * See + * Semantic Kernel Planners: Sequential Planner + *

+ * Refer to the + * README for configuring your environment to run the examples. + */ +public class SequentialPlanner_AnswerQuestion { + + public static class InformationFinder { + @DefineSKFunction( + name = "Search", + description = "Returns information relevant to answering a given query." + ) + public String search( + @SKFunctionInputAttribute(description = "The query to answer.") + String query) { + return """ + - The Eiffel Tower is in Paris. + - The Eiffel Tower is made of metal. + - The Eiffel Tower is 324 meters tall. + """.stripIndent(); + } + } + + public static void main(String[] args) throws IOException, ConfigurationException { + OpenAIAsyncClient client = SamplesConfig.getClient(); + var kernel = SKBuilders.kernel() + .withDefaultAIService(SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build()) + .build(); + + + kernel.importSkillFromResources( + "Plugins", + "Answer", + "AnswerQuestion", + SequentialPlanner_AnswerQuestion.class + ); + + kernel.importSkill(new InformationFinder(), "InformationFinder"); + + String prompt; + try (InputStream altprompt = SequentialPlanner_AnswerQuestion.class.getResourceAsStream("require_context_variable_planner_prompt.txt")) { + prompt = new String(altprompt.readAllBytes(), StandardCharsets.UTF_8); + } + + var planner = new SequentialPlanner(kernel, null, prompt); + + var plan = planner.createPlanAsync("Take the input as a question and answer it finding any information needed.").block(); + + System.out.println(plan.toPlanString()); + + SKContext response = plan.invokeAsync("Where is the Eiffel Tower?").block(); + + System.out.println("========================================"); + System.out.println("Answer is: " + response.getResult()); + System.out.println("Sources used to answer this question: " + response.getVariables().get("sources")); + } +} diff --git a/java/samples/sample-code/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/config.json b/java/samples/sample-code/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/config.json new file mode 100644 index 0000000000..bcdcb51cfd --- /dev/null +++ b/java/samples/sample-code/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/config.json @@ -0,0 +1,12 @@ +{ + "schema": 1, + "description": "Sample plugin loaded from classpath root via resources", + "type": "completion", + "completion": { + "max_tokens": 150, + "temperature": 0.9, + "top_p": 0.0, + "presence_penalty": 0.6, + "frequency_penalty": 0.0 + } +} \ No newline at end of file diff --git a/java/samples/sample-code/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/skprompt.txt b/java/samples/sample-code/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/skprompt.txt new file mode 100644 index 0000000000..ddd3f836d3 --- /dev/null +++ b/java/samples/sample-code/src/main/resources/Plugins/ExamplePlugins/ExampleFunctionRoot/skprompt.txt @@ -0,0 +1 @@ +This is an example \ No newline at end of file diff --git a/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/config.json b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/config.json new file mode 100644 index 0000000000..47f85399fd --- /dev/null +++ b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/config.json @@ -0,0 +1,24 @@ +{ + "schema": 1, + "description": "Sample plugin loaded via resources", + "type": "completion", + "completion": { + "max_tokens": 150, + "temperature": 0.9, + "top_p": 0.0, + "presence_penalty": 0.6, + "frequency_penalty": 0.0 + }, + "input": { + "parameters": [ + { + "name": "input", + "description": "Question to answer" + }, + { + "name": "sources", + "description": "Information used to answer the question" + } + ] + } +} \ No newline at end of file diff --git a/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/skprompt.txt b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/skprompt.txt new file mode 100644 index 0000000000..fdc3dcfaf0 --- /dev/null +++ b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/Answer/AnswerQuestion/skprompt.txt @@ -0,0 +1,30 @@ +Using the information below and ONLY the information below, answer the question: + +[EXAMPLES] +[EXAMPLE 1] +[INFORMATION] +- My computer is hot +- My computers fan is on +[END INFORMATION] +Question: What temperature is my computer? +Answer: Your computer is hot +[END EXAMPLE 2] + + +[EXAMPLE 2] +[INFORMATION] +- The house is red +- The house has 5 bed rooms +[END INFORMATION] +Question: Where is the house? +Answer: I do not have enough information to answer that. +[END EXAMPLE 2] + +[END EXAMPLES] + +[INFORMATION] +{{$sources}} +[END INFORMATION] + +Question: {{$input}} +Answer: \ No newline at end of file diff --git a/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/config.json b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/config.json new file mode 100644 index 0000000000..99631f93ee --- /dev/null +++ b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/config.json @@ -0,0 +1,12 @@ +{ + "schema": 1, + "description": "Sample plugin loaded via resources", + "type": "completion", + "completion": { + "max_tokens": 150, + "temperature": 0.9, + "top_p": 0.0, + "presence_penalty": 0.6, + "frequency_penalty": 0.0 + } +} \ No newline at end of file diff --git a/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt new file mode 100644 index 0000000000..ddd3f836d3 --- /dev/null +++ b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/Plugins/ExamplePlugins/ExampleFunction/skprompt.txt @@ -0,0 +1 @@ +This is an example \ No newline at end of file diff --git a/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/require_context_variable_planner_prompt.txt b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/require_context_variable_planner_prompt.txt new file mode 100644 index 0000000000..c949a424f0 --- /dev/null +++ b/java/samples/sample-code/src/main/resources/com/microsoft/semantickernel/samples/syntaxexamples/javaspecific/require_context_variable_planner_prompt.txt @@ -0,0 +1,118 @@ +Create an XML plan step by step, to satisfy the goal given. +To create a plan, follow these steps: +0. The plan should be as short as possible. +1. From a create a as a series of . +2. Before using any function in a plan, check that it is present in the most recent [AVAILABLE FUNCTIONS] list. If it is not, do not use it. Do not assume that any function that was previously defined or used in another plan or in [EXAMPLES] is automatically available or compatible with the current plan. +3. Only use functions that are required for the given goal. +4. A function has a single 'input' and a single 'output' which are both strings and not objects. +5. The 'output' from each function is automatically passed as 'input' to the subsequent . +6. 'input' does not need to be specified if it consumes the 'output' of the previous function. +7. To save an 'output' from a , to pass into a future , use "/> +8. To save an 'output' from a , to return as part of a plan result, use "/> +9. Append an "END" XML comment at the end of the plan. + +[EXAMPLES] +[AVAILABLE FUNCTIONS] + + EmailConnector.LookupContactEmail: + description: looks up a contact and retrieves their email address + inputs: + - input: the name to look up + + EmailConnector.EmailTo: + description: email the input text to a recipient + inputs: + - input: the text to email + - recipient: the recipient's email address. Multiple addresses may be included if separated by ';'. + + LanguageHelpers.TranslateTo: + description: translate the input to another language + inputs: + - input: the text to translate + - translate_to_language: the language to translate to + + SummarizeSkill.Summarize: + description: summarize input text + inputs: + - input: the text to summarize + +[END AVAILABLE FUNCTIONS] + +Summarize the input, then translate to japanese and email it to Martin + + + + + + + +[AVAILABLE FUNCTIONS] + + _GLOBAL_FUNCTIONS_.GetEmailAddress: + description: Gets email address for given contact + inputs: + - input: the name to look up + + _GLOBAL_FUNCTIONS_.SendEmail: + description: email the input text to a recipient + inputs: + - input: the text to email + - recipient: the recipient's email address. Multiple addresses may be included if separated by ';'. + + AuthorAbility.Summarize: + description: summarizes the input text + inputs: + - input: the text to summarize + + Magician.TranslateTo: + description: translate the input to another language + inputs: + - input: the text to translate + - translate_to_language: the language to translate to + +[END AVAILABLE FUNCTIONS] + +Summarize an input, translate to french, and e-mail to John Doe + + + + + + + +[AVAILABLE FUNCTIONS] + + _GLOBAL_FUNCTIONS_.NovelOutline : + description: Outlines the input text as if it were a novel + inputs: + - input: the title of the novel to outline + - chapterCount: the number of chapters to outline + + Emailer.EmailTo: + description: email the input text to a recipient + inputs: + - input: the text to email + - recipient: the recipient's email address. Multiple addresses may be included if separated by ';'. + + Everything.Summarize: + description: summarize input text + inputs: + - input: the text to summarize + +[END AVAILABLE FUNCTIONS] + +Create an outline for a children's book with 3 chapters about a group of kids in a club and then summarize it. + + + + + +[END EXAMPLES] + +[AVAILABLE FUNCTIONS] + +{{$available_functions}} + +[END AVAILABLE FUNCTIONS] + +{{$input}} diff --git a/java/samples/sample-code/src/main/resources/log4j2.xml b/java/samples/sample-code/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..dfe2ccca7e --- /dev/null +++ b/java/samples/sample-code/src/main/resources/log4j2.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/samples/semantickernel-samples-guice/pom.xml b/java/samples/semantickernel-samples-guice/pom.xml new file mode 100644 index 0000000000..8722893315 --- /dev/null +++ b/java/samples/semantickernel-samples-guice/pom.xml @@ -0,0 +1,48 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + samples + 0.2.10-alpha-SNAPSHOT + ../pom.xml + + + semantickernel-samples-guice + jar + + + + com.microsoft.semantic-kernel + semantickernel-core + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + + + com.microsoft.semantic-kernel + semantickernel-plugin-core + + + + com.google.inject + guice + 7.0.0 + + + com.google.inject.extensions + guice-assistedinject + 7.0.0 + + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + + \ No newline at end of file diff --git a/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/CompletionFunctionFactory.java b/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/CompletionFunctionFactory.java new file mode 100644 index 0000000000..fadafa0468 --- /dev/null +++ b/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/CompletionFunctionFactory.java @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.guice; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import jakarta.inject.Inject; + +public interface CompletionFunctionFactory { + + CompletionSKFunction createFunction( + String prompt, String name, PromptTemplateConfig.CompletionConfig completionConfig); + + class CompletionFunctionFactoryImpl implements CompletionFunctionFactory { + @Inject + private Kernel kernel; + + @Override + public CompletionSKFunction createFunction( + String prompt, + String name, + PromptTemplateConfig.CompletionConfig completionConfig) { + return kernel.getSemanticFunctionBuilder() + .withPromptTemplate(prompt) + .withFunctionName(name) + .withCompletionConfig(completionConfig) + .build(); + } + } +} diff --git a/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/Config.java b/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/Config.java new file mode 100644 index 0000000000..d36c8a6705 --- /dev/null +++ b/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/Config.java @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.guice; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.KeyCredential; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// TODO Remove when the upstream configuration updates arrive +public class Config { + + private static final Logger LOGGER = LoggerFactory.getLogger(Config.class); + + public static final String OPEN_AI_CONF_PROPERTIES = "samples/java/semantickernel-samples/conf.openai.properties"; + public static final String AZURE_CONF_PROPERTIES = "samples/java/semantickernel-samples/conf.azure.properties"; + + public static String getOpenAIKey(String conf) { + return getConfigValue(conf, "token"); + } + + public static String getAzureOpenAIEndpoint(String conf) { + return getConfigValue(conf, "endpoint"); + } + + private static String getConfigValue(String configFile, String propertyName) { + File config = new File(configFile); + try (FileInputStream fis = new FileInputStream(config.getAbsolutePath())) { + Properties props = new Properties(); + props.load(fis); + return props.getProperty(propertyName); + } catch (IOException e) { + LOGGER.error( + "Unable to load config value " + propertyName + " from file" + configFile, e); + throw new RuntimeException(configFile + " not configured properly"); + } + } + + /** + * Returns the client that will handle AzureOpenAI or OpenAI requests. + * + * @param useAzureOpenAI whether to use AzureOpenAI or OpenAI. + * @return client to be used by the kernel. + */ + public static OpenAIAsyncClient getClient(boolean useAzureOpenAI) { + if (useAzureOpenAI) { + return new OpenAIClientBuilder() + .endpoint(Config.getAzureOpenAIEndpoint(AZURE_CONF_PROPERTIES)) + .credential(new AzureKeyCredential(Config.getOpenAIKey(AZURE_CONF_PROPERTIES))) + .buildAsyncClient(); + } + + return new OpenAIClientBuilder() + .credential(new KeyCredential(Config.getOpenAIKey(OPEN_AI_CONF_PROPERTIES))) + .buildAsyncClient(); + } +} diff --git a/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/SemanticKernelModule.java b/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/SemanticKernelModule.java new file mode 100644 index 0000000000..bb2e722274 --- /dev/null +++ b/java/samples/semantickernel-samples-guice/src/main/java/com/microsoft/semantickernel/guice/SemanticKernelModule.java @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.guice; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.google.inject.AbstractModule; +import com.google.inject.TypeLiteral; +import com.google.inject.util.Providers; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.KernelConfig; +import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion; +import com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration; +import com.microsoft.semantickernel.memory.NullMemory; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.templateengine.DefaultPromptTemplateEngine; +import com.microsoft.semantickernel.templateengine.PromptTemplateEngine; + +import javax.annotation.Nullable; + +public class SemanticKernelModule extends AbstractModule { + + private final SemanticTextMemory memory; + private final KernelConfig.Builder kernelConfig; + private final ReadOnlySkillCollection skillCollection; + private final PromptTemplateEngine promptTemplateEngine; + private String textCompletionModelId; + private boolean withMemory; + private String embeddingsGenerationServiceId; + private OpenAIAsyncClient client; + + public SemanticKernelModule( + KernelConfig.Builder kernelConfig, + @Nullable SemanticTextMemory memory, + @Nullable ReadOnlySkillCollection skillCollection, + @Nullable PromptTemplateEngine promptTemplateEngine) { + this.kernelConfig = kernelConfig; + + if (memory != null) { + this.memory = memory.copy(); + } else { + this.memory = null; + } + + if (skillCollection == null) { + skillCollection = new DefaultSkillCollection(); + } + this.skillCollection = skillCollection; + + if (promptTemplateEngine == null) { + promptTemplateEngine = new DefaultPromptTemplateEngine(); + } + this.promptTemplateEngine = promptTemplateEngine; + } + + public SemanticKernelModule( + KernelConfig.Builder kernelConfig, @Nullable SemanticTextMemory memory) { + this(kernelConfig, memory, null, null); + } + + public SemanticKernelModule(KernelConfig.Builder kernelConfig) { + this(kernelConfig, null); + } + + public SemanticKernelModule() { + this(SKBuilders.kernelConfig(), null); + } + + public SemanticKernelModule withTextCompletionService(String model) { + this.textCompletionModelId = model; + return this; + } + + public SemanticKernelModule withClient(OpenAIAsyncClient client) { + this.client = client; + return this; + } + + @Override + protected void configure() { + super.configure(); + + if (client == null) { + client = Config.getClient(true); + } + + bind(OpenAIAsyncClient.class).toInstance(client); + + if (embeddingsGenerationServiceId != null) { + OpenAITextEmbeddingGeneration embeddings = new OpenAITextEmbeddingGeneration(client, + embeddingsGenerationServiceId); + bind(new TypeLiteral>() { + }).toInstance(embeddings); + } + + + bind(KernelConfig.class).toInstance(kernelConfig.build()); + bind(PromptTemplateEngine.class).toInstance(promptTemplateEngine); + bind(ReadOnlySkillCollection.class).toProvider(Providers.of(skillCollection)); + + if (withMemory) { + bind(SemanticTextMemory.class).toProvider(Providers.of(memory)); + } else { + bind(SemanticTextMemory.class).toInstance(NullMemory.getInstance()); + } + + bind(Kernel.class).toProvider(() -> { + Kernel.Builder builder = SKBuilders.kernel(); + if (textCompletionModelId != null) { + builder.withDefaultAIService(new OpenAITextCompletion(client, textCompletionModelId)); + } + return builder.build(); + }); + + bind(CompletionFunctionFactory.class) + .to(CompletionFunctionFactory.CompletionFunctionFactoryImpl.class); + } + + public SemanticKernelModule withMemory() { + this.withMemory = true; + return this; + } + + public SemanticKernelModule withTextEmbeddingsGenerationService( + String embeddingsGenerationServiceId) { + this.embeddingsGenerationServiceId = embeddingsGenerationServiceId; + return this; + } +} diff --git a/java/samples/semantickernel-samples-guice/src/test/java/com/microsoft/semantickernel/guice/CompletionFunctionExample.java b/java/samples/semantickernel-samples-guice/src/test/java/com/microsoft/semantickernel/guice/CompletionFunctionExample.java new file mode 100644 index 0000000000..33a96b8d26 --- /dev/null +++ b/java/samples/semantickernel-samples-guice/src/test/java/com/microsoft/semantickernel/guice/CompletionFunctionExample.java @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.guice; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; + +import java.util.ArrayList; + +public class CompletionFunctionExample { + + private final CompletionFunctionFactory completionFunctionFactory; + + public static void main(String[] args) { + Injector injector = + Guice.createInjector( + new SemanticKernelModule().withTextCompletionService("text-davinci-003")); + + CompletionFunctionExample example = injector.getInstance(CompletionFunctionExample.class); + example.run(); + } + + @Inject + public CompletionFunctionExample(CompletionFunctionFactory completionFunctionFactory) { + this.completionFunctionFactory = completionFunctionFactory; + } + + public void run() { + String prompt = "{{$input}}\n" + "Summarize the content above."; + + String text = + "\n" + + "Demo (ancient Greek poet)\n" + + "From Wikipedia, the free encyclopedia\n" + + "Demo or Damo (Greek: ΔÎĩÎŧĪŽ, ΔαÎŧĪŽ; fl. c. AD 200) was a Greek woman of the\n" + + "Roman period, known for a single epigram, engraved upon the Colossus of\n" + + "Memnon, which bears her name. She speaks of herself therein as a lyric\n" + + "poetess dedicated to the Muses, but nothing is known of her life.[1]\n" + + "Identity\n" + + "Demo was evidently Greek, as her name, a traditional epithet of Demeter,\n" + + "signifies. The name was relatively common in the Hellenistic world, in\n" + + "Egypt and elsewhere, and she cannot be further identified. The date of her\n" + + "visit to the Colossus of Memnon cannot be established with certainty, but\n" + + "internal evidence on the left leg suggests her poem was inscribed there at\n" + + "some point in or after AD 196.[2]\n" + + "Epigram\n" + + "There are a number of graffiti inscriptions on the Colossus of Memnon.\n" + + "Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac\n" + + "couplets, entitled and presumably authored by \"Demo\" or \"Damo\" (the\n" + + "Greek inscription is difficult to read), is a dedication to the Muses.[2]\n" + + "The poem is traditionally published with the works of Balbilla, though the\n" + + "internal evidence suggests a different author.[1]\n" + + "In the poem, Demo explains that Memnon has shown her special respect. In\n" + + "return, Demo offers the gift for poetry, as a gift to the hero. At the end\n" + + "of this epigram, she addresses Memnon, highlighting his divine status by\n" + + "recalling his strength and holiness.[2]\n" + + "Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic\n" + + "dialect. The language indicates she was knowledgeable in Homeric\n" + + "poetry—'bearing a pleasant gift', for example, alludes to the use of that\n" + + "phrase throughout the Iliad and Odyssey.[a][2];"; + + SKContext summary = + completionFunctionFactory + .createFunction( + prompt, + "summarize", + new PromptTemplateConfig.CompletionConfig( + 0.2, 0.5, 0, 0, 2000)) + .invokeAsync(text) + .block(); + + if (summary != null) { + System.out.println("Result: " + summary.getResult()); + } else { + System.out.println("Null result"); + } + } +} diff --git a/java/samples/semantickernel-samples-guice/src/test/java/com/microsoft/semantickernel/guice/GuiceEmbeddingExample.java b/java/samples/semantickernel-samples-guice/src/test/java/com/microsoft/semantickernel/guice/GuiceEmbeddingExample.java new file mode 100644 index 0000000000..48323bc3f8 --- /dev/null +++ b/java/samples/semantickernel-samples-guice/src/test/java/com/microsoft/semantickernel/guice/GuiceEmbeddingExample.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.guice; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration; + +import jakarta.inject.Inject; + +import java.util.ArrayList; +import java.util.List; + +public class GuiceEmbeddingExample { + + private final EmbeddingGeneration embeddingGeneration; + + public static void main(String[] args) { + Injector injector = + Guice.createInjector( + new SemanticKernelModule() + .withMemory() + .withTextEmbeddingsGenerationService("text-embedding-ada-002")); + + GuiceEmbeddingExample example = injector.getInstance(GuiceEmbeddingExample.class); + example.run(); + } + + @Inject + public GuiceEmbeddingExample(EmbeddingGeneration embeddingGeneration) { + this.embeddingGeneration = embeddingGeneration; + } + + public void run() { + List data = new ArrayList<>(); + data.add("This is just a test"); + + embeddingGeneration + .generateEmbeddingsAsync(data) + .block() + .forEach( + doubleEmbedding -> { + doubleEmbedding.getVector().forEach(System.out::println); + }); + } +} diff --git a/java/semantickernel-api/pom.xml b/java/semantickernel-api/pom.xml new file mode 100644 index 0000000000..77d322cdca --- /dev/null +++ b/java/semantickernel-api/pom.xml @@ -0,0 +1,45 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../pom.xml + + + semantickernel-api + jar + Semantic Kernel API + Defines the public interface for the Semantic Kernel + + + com.azure + azure-ai-openai + + + org.slf4j + slf4j-api + + + com.fasterxml.jackson.core + jackson-databind + compile + + + com.fasterxml.jackson.core + jackson-core + compile + + + io.projectreactor + reactor-core + + + com.google.code.findbugs + jsr305 + + + \ No newline at end of file diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java new file mode 100644 index 0000000000..b92c50c92e --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Kernel.java @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.memory.MemoryStore; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig; +import com.microsoft.semantickernel.services.AIService; +import com.microsoft.semantickernel.templateengine.PromptTemplateEngine; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import java.util.function.Function; +import java.util.function.Supplier; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/** Interface for the semantic kernel. */ +public interface Kernel extends SkillExecutor, Buildable { + + /** + * Settings required to execute functions, including details about AI dependencies, e.g. + * endpoints and API keys. + */ + KernelConfig getConfig(); + + /** + * Reference to the engine rendering prompt templates + * + * @return Reference to the engine rendering prompt templates + */ + PromptTemplateEngine getPromptTemplateEngine(); + + /** + * Get the SemanticTextMemory in use. + * + * @return the SemanticTextMemory in use + */ + SemanticTextMemory getMemory(); + + /** + * Run a pipeline composed of synchronous and asynchronous functions. + * + * @param pipeline List of functions + * @return Result of the function composition + */ + Mono runAsync(SKFunction... pipeline); + + /** + * Run a pipeline composed of synchronous and asynchronous functions. + * + * @param input Input to process + * @param pipeline List of functions + * @return Result of the function composition + */ + Mono runAsync(String input, SKFunction... pipeline); + + /** + * Run a pipeline composed of synchronous and asynchronous functions. + * + * @param variables variables to initialise the context with + * @param pipeline List of functions + * @return Result of the function composition + */ + Mono runAsync(ContextVariables variables, SKFunction... pipeline); + + /** + * Register a semantic function on this kernel + * + * @param skillName The skill name + * @param functionName The function name + * @param functionConfig The function configuration + * @return The registered function + */ + CompletionSKFunction registerSemanticFunction( + String skillName, String functionName, SemanticFunctionConfig functionConfig); + + /** + * Get a completion function builder, functions created with this builder will be registered on + * the kernel + */ + CompletionSKFunction.Builder getSemanticFunctionBuilder(); + + /** Obtains the service with the given name and type */ + T getService(@Nullable String name, Class clazz) + throws KernelException; + + /** Registers a semantic function on this kernel */ + > + FunctionType registerSemanticFunction(FunctionType semanticFunctionDefinition); + + /** Obtains a semantic function with the given name */ + SKFunction getFunction(String skill, String function); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(Kernel.Builder.class); + } + + interface Builder extends SemanticKernelBuilder { + /** + * Set the kernel configuration + * + * @param kernelConfig Kernel configuration + * @return Builder + */ + Builder withConfiguration(KernelConfig kernelConfig); + + /** + * Add prompt template engine to the kernel to be built. + * + * @param promptTemplateEngine Prompt template engine to add. + * @return Updated kernel builder including the prompt template engine. + */ + Builder withPromptTemplateEngine(PromptTemplateEngine promptTemplateEngine); + + /** + * Add memory storage to the kernel to be built. + * + * @param storage Storage to add. + * @return Updated kernel builder including the memory storage. + */ + Builder withMemoryStorage(MemoryStore storage); + + /** + * Add memory storage factory to the kernel. + * + * @param factory The storage factory. + * @return Updated kernel builder including the memory storage. + */ + Builder withMemoryStorage(Supplier factory); + + /** + * Adds an instance to the services collection + * + * @param instance The instance. + * @return The builder. + */ + Builder withDefaultAIService(T instance); + + /** + * Adds an instance to the services collection + * + * @param instance The instance. + * @param clazz The class of the instance. + * @return The builder. + */ + Builder withDefaultAIService(T instance, Class clazz); + + /** + * Adds a factory method to the services collection + * + * @param factory The factory method that creates the AI service instances of type T. + * @param clazz The class of the instance. + */ + Builder withDefaultAIService(Supplier factory, Class clazz); + + /** + * Adds an instance to the services collection + * + * @param serviceId The service ID + * @param instance The instance. + * @param setAsDefault Optional: set as the default AI service for type T + * @param clazz The class of the instance. + */ + Builder withAIService( + @Nullable String serviceId, T instance, boolean setAsDefault, Class clazz); + + /** + * Adds a factory method to the services collection + * + * @param serviceId The service ID + * @param factory The factory method that creates the AI service instances of type T. + * @param setAsDefault Optional: set as the default AI service for type T + * @param clazz The class of the instance. + */ + Builder withAIServiceFactory( + @Nullable String serviceId, + Function factory, + boolean setAsDefault, + Class clazz); + + /** + * Add a semantic text memory entity to the kernel to be built. + * + * @param memory Semantic text memory entity to add. + * @return Updated kernel builder including the semantic text memory entity. + */ + Builder withMemory(SemanticTextMemory memory); + + /** + * Add memory storage and an embedding generator to the kernel to be built. + * + * @param storage Storage to add. + * @param embeddingGenerator Embedding generator to add. + * @return Updated kernel builder including the memory storage and embedding generator. + */ + Builder withMemoryStorageAndTextEmbeddingGeneration( + MemoryStore storage, TextEmbeddingGeneration embeddingGenerator); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelConfig.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelConfig.java new file mode 100644 index 0000000000..4fc0cbc99a --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelConfig.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; + +// Currently the kernel config does not have and function within Java +public final class KernelConfig implements Buildable { + + public static Builder builder() { + return BuildersSingleton.INST.getInstance(KernelConfig.Builder.class); + } + + public static class Builder implements SemanticKernelBuilder { + public KernelConfig build() { + return new KernelConfig(); + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelException.java new file mode 100644 index 0000000000..47d540a0e2 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/KernelException.java @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Kernel logic exception */ +public class KernelException extends SKException { + + @Nonnull private final ErrorCodes errorCode; + + public KernelException(@Nonnull ErrorCodes error) { + this(error, null, null); + } + + public KernelException(@Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + public KernelException( + @Nonnull ErrorCodes errorCode, + @Nullable String message, + @Nullable Throwable innerException) { + super(formatDefaultMessage(errorCode.getMessage(), message), innerException); + this.errorCode = errorCode; + } + + public ErrorCodes getErrorCode() { + return errorCode; + } + + ///

+ /// Semantic kernel error codes. + /// + public enum ErrorCodes { + /// + /// Unknown error. + /// + UNKNOWN_ERROR("Unknown error"), + + INVALID_FUNCTION_DESCRIPTION("Invalid function description"), + + FUNCTION_OVERLOAD_NOT_SUPPORTED("Function overload not supported"), + + FUNCTION_NOT_AVAILABLE("Function not available"), + + FUNCTION_TYPE_NOT_SUPPORTED("Function type not supported"), + + FUNCTION_CONFIGURATION_ERROR("Function configuration is not valid"), + + INVALID_FUNCTION_TYPE("Invalid function type"), + + INVALID_SERVICE_CONFIGURATION("Invalid service configuration"), + + SERVICE_NOT_FOUND("Service not found"), + + SKILL_COLLECTION_NOT_SET("Skill collection not set"), + + FUNCTION_INVOCATION_ERROR("Represents an error that occurs when invoking a function"); + + private final String message; + + ErrorCodes(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKBuilders.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKBuilders.java new file mode 100644 index 0000000000..114f7c6f42 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKBuilders.java @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.memory.MemoryStore; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.templateengine.PromptTemplateEngine; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; + +public class SKBuilders { + // Prevent creating object + private SKBuilders() {} + + public static TextCompletion.Builder textCompletion() { + return BuildersSingleton.INST.getInstance(TextCompletion.Builder.class); + } + + public static TextEmbeddingGeneration.Builder textEmbeddingGeneration() { + return BuildersSingleton.INST.getInstance(TextEmbeddingGeneration.Builder.class); + } + + public static Kernel.Builder kernel() { + return BuildersSingleton.INST.getInstance(Kernel.Builder.class); + } + + public static KernelConfig.Builder kernelConfig() { + return BuildersSingleton.INST.getInstance(KernelConfig.Builder.class); + } + + public static SemanticTextMemory.Builder semanticTextMemory() { + return BuildersSingleton.INST.getInstance(SemanticTextMemory.Builder.class); + } + + public static ReadOnlySkillCollection.Builder skillCollection() { + return BuildersSingleton.INST.getInstance(ReadOnlySkillCollection.Builder.class); + } + + public static PromptTemplate.Builder promptTemplate() { + return BuildersSingleton.INST.getInstance(PromptTemplate.Builder.class); + } + + public static PromptTemplateEngine.Builder promptTemplateEngine() { + return BuildersSingleton.INST.getInstance(PromptTemplateEngine.Builder.class); + } + + public static ContextVariables.Builder variables() { + return BuildersSingleton.INST.getInstance(ContextVariables.Builder.class); + } + + public static SKContext.Builder context() { + return BuildersSingleton.INST.getInstance(SKContext.Builder.class); + } + + public static PromptTemplateConfig.CompletionConfigBuilder completionConfig() { + return BuildersSingleton.INST.getInstance( + PromptTemplateConfig.CompletionConfigBuilder.class); + } + + @SuppressWarnings("unchecked") + public static + ChatCompletion.Builder chatCompletion() { + return (ChatCompletion.Builder) + BuildersSingleton.INST.getInstance(ChatCompletion.Builder.class); + } + + public static MemoryStore.Builder memoryStore() { + return BuildersSingleton.INST.getInstance(MemoryStore.Builder.class); + } + + public static CompletionSKFunction.Builder completionFunctions() { + return BuildersSingleton.INST.getInstance(CompletionSKFunction.Builder.class); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKCheckedException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKCheckedException.java new file mode 100644 index 0000000000..3c8fcaf58c --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKCheckedException.java @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Provides the base exception from which all CHECKED Semantic Kernel exceptions derive. */ +public class SKCheckedException extends Exception { + + /** + * Initializes a new instance of the {@code SKCheckedException} class with a default message. + */ + protected SKCheckedException() { + super(); + } + + /** + * Initializes a new instance of the {@code SKCheckedException} class with its message set to + * {@code message}. + * + * @param message A string that describes the error. + */ + protected SKCheckedException(@Nullable String message) { + super(message); + } + + /** + * Initializes a new instance of the {@code SKCheckedException} class with its message set to + * {@code message}. + * + * @param message A string that describes the error. + * @param cause The exception that is the cause of the current exception. + */ + protected SKCheckedException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + } + + /** + * Translate the error code into a default message format. + * + * @param errorMessage The error message from an error code + * @param message The message from the code which throws the exception + * @return A formatted message + */ + protected static String formatDefaultMessage( + @Nonnull String errorMessage, @Nullable String message) { + return SKException.formatDefaultMessage(errorMessage, message); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKException.java new file mode 100644 index 0000000000..28c89779ba --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SKException.java @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Provides the base exception from which all Semantic Kernel exceptions derive. */ +public class SKException extends RuntimeException { + + /** Initializes a new instance of the {@code SKException} class with a default message. */ + protected SKException() { + super(); + } + + /** + * Initializes a new instance of the {@code SKException} class with its message set to {@code + * message}. + * + * @param message A string that describes the error. + */ + protected SKException(@Nullable String message) { + super(message); + } + + /** + * Initializes a new instance of the {@code SKException} class with its message set to {@code + * message}. + * + * @param message A string that describes the error. + * @param cause The exception that is the cause of the current exception. + */ + protected SKException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + } + + /** + * Translate the error code into a default message format. + * + * @param errorMessage The error message from an error code + * @param message The message from the code which throws the exception + * @return A formatted message + */ + protected static String formatDefaultMessage( + @Nonnull String errorMessage, @Nullable String message) { + return String.format("%s: %s", errorMessage, message); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SkillExecutor.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SkillExecutor.java new file mode 100644 index 0000000000..a58d129550 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/SkillExecutor.java @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.microsoft.semantickernel.exceptions.SkillsNotFoundException; +import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import java.util.Map; +import javax.annotation.Nullable; + +public interface SkillExecutor { + + /** + * Import a set of skills + * + * @param skillName name of the skill + * @param skills map of skill names to skill configs + * @return the function collection + * @throws SkillsNotFoundException if the skill is not found + */ + ReadOnlyFunctionCollection importSkill( + String skillName, Map skills) + throws SkillsNotFoundException; + + /** + * Get function collection with the skill name + * + * @param skillName name of the skill + * @return the function collection + * @throws SkillsNotFoundException if the skill is not found + */ + ReadOnlyFunctionCollection getSkill(String skillName) throws SkillsNotFoundException; + + /** + * Imports the native functions annotated on the given object as a skill. + * + * @param skillName name of the skill + * @return the function collection + */ + ReadOnlyFunctionCollection importSkillFromDirectory( + String skillName, String parentDirectory, String skillDirectoryName); + + /** Imports the native functions annotated on the given object as a skill. */ + void importSkillsFromDirectory(String parentDirectory, String... skillNames); + + /** + * Imports the native functions annotated on the given object as a skill. Assumes that the + * directory that contains the skill is the same as skillName + * + * @param skillName name of the skill + * @param parentDirectory directory that contains the skill + * @return the function collection + */ + ReadOnlyFunctionCollection importSkillFromDirectory(String skillName, String parentDirectory); + + /** + * Imports a skill using ClassLoader.getResourceAsStream to load skills from the classpath. + * + * @param pluginDirectory directory within the classpath that contains the skill + * @param skillName name of the skill + * @param functionName name of the function + * @return the function collection + * @throws KernelException if it is not possible to correctly load the skill + */ + ReadOnlyFunctionCollection importSkillFromResources( + String pluginDirectory, String skillName, String functionName) throws KernelException; + + /** + * Imports a skill using clazz.getResourceAsStream to load skills from the classpath. + * + * @param skillName name of the skill + * @param functionName name of the function + * @param clazz class that contains the skill + * @return the function collection + * @throws KernelException if it is not possible to correctly load the skill + */ + ReadOnlyFunctionCollection importSkillFromResources( + String pluginDirectory, String skillName, String functionName, @Nullable Class clazz) throws KernelException; + + /** + * Imports the native functions annotated on the given object as a skill. + * + * @param nativeSkill object containing the native functions + * @param skillName name of the skill + * @return the function collection + */ + ReadOnlyFunctionCollection importSkill(Object nativeSkill, @Nullable String skillName); + + /** + * @return Reference to the read-only skill collection containing all the imported functions + */ + ReadOnlySkillCollection getSkills(); +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Verify.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Verify.java new file mode 100644 index 0000000000..7713801c1e --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/Verify.java @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import javax.annotation.Nullable; + +public class Verify { + + public static void notNull(Object object) { + assert object != null; + } + + public static boolean isNullOrEmpty(@Nullable String s) { + return s == null || s.isEmpty(); + } + + public static boolean isNullOrWhiteSpace(String s) { + return s == null || s.matches("^\\w+$"); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/AIException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/AIException.java new file mode 100644 index 0000000000..a5e321e78d --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/AIException.java @@ -0,0 +1,101 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.ai; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** AI logic exception */ +public class AIException extends SKException { + + @Nonnull private final ErrorCodes errorCode; + + /** + * Initializes a new instance of the {@link AIException} class. + * + * @param error The error code. + */ + public AIException(@Nonnull ErrorCodes error) { + this(error, null, null); + } + + /** + * Initializes a new instance of the {@link AIException} class. + * + * @param errorCode The error code. + * @param message The message. + */ + public AIException(@Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + /** + * Initializes a new instance of the {@link AIException} class. + * + * @param errorCode The error code. + * @param message The message. + * @param innerException The cause of the exception. + */ + public AIException( + @Nonnull ErrorCodes errorCode, + @Nullable String message, + @Nullable Throwable innerException) { + super(formatDefaultMessage(errorCode.getMessage(), message), innerException); + this.errorCode = errorCode; + } + + /** + * Gets the error code. + * + * @return The error code. + */ + public ErrorCodes getErrorCode() { + return errorCode; + } + + /** Error codes */ + public enum ErrorCodes { + /** Unknown error. */ + UNKNOWN_ERROR("Unknown error"), + + /** No response. */ + NO_RESPONSE("No response"), + /** Access denied. */ + ACCESS_DENIED("Access is denied"), + + /** Invalid request. */ + INVALID_REQUEST("The request was invalid"), + /** Invalid response. */ + INVALID_RESPONSE_CONTENT("The content of the response was invalid"), + + /** Throttling. */ + THROTTLING("The request was throttled"), + /** Request timeout. */ + REQUEST_TIMEOUT("The request timed out"), + + /** Service error. */ + SERVICE_ERROR("There was an error in the service"), + + /** Model not available. */ + MODEL_NOT_AVAILABLE("The requested model is not available"), + + /** Invalid configuration. */ + INVALID_CONFIGURATION("The supplied configuration was invalid"), + /** Function type not supported. */ + FUNCTION_TYPE_NOT_SUPPORTED("The function is not supported"); + private final String message; + + ErrorCodes(String message) { + this.message = message; + } + + /** + * Gets the error message. + * + * @return The error message. + */ + public String getMessage() { + return message; + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/Embedding.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/Embedding.java new file mode 100644 index 0000000000..b28790662e --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/Embedding.java @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.ai.embeddings; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nonnull; + +/** Represents a strongly typed vector of numeric data. */ +public class Embedding { + + // vector is immutable! + private final List vector; + + private static final Embedding EMPTY = new Embedding(); + + public static Embedding empty() { + return EMPTY; + } + + /** Initializes a new instance of the Embedding class. */ + public Embedding() { + this.vector = Collections.emptyList(); + } + + /** + * Initializes a new instance of the Embedding class that contains numeric elements copied from + * the specified collection + * + * @param vector The collection whose elements are copied to the new Embedding + */ + public Embedding(@Nonnull List vector) { + Objects.requireNonNull(vector); + this.vector = Collections.unmodifiableList(vector); + } + + /** + * Return the embedding vector as a read-only list. + * + * @return The embedding vector as a read-only list. + */ + public List getVector() { + return vector; + } + + /** + * Calculates the dot product of this {@code Embedding} with another. + * + * @param other The other {@code Embedding} to compute the dot product with + * @return The dot product between the {@code Embedding} vectors + */ + public float dot(@Nonnull Embedding other) { + Objects.requireNonNull(other); + return VectorOperations.dot(this.vector, other.getVector()); + } + + /** + * Calculates the Euclidean length of this vector. + * + * @return Euclidean length + */ + public float euclideanLength() { + return VectorOperations.euclideanLength(this.vector); + } + + /** + * Calculates the cosine similarity of this vector with another. + * + * @param other The other vector to compute cosine similarity with. + * @return Cosine similarity between vectors + */ + public float cosineSimilarity(@Nonnull Embedding other) { + Objects.requireNonNull(other); + return VectorOperations.cosineSimilarity(this.vector, other.getVector()); + } + + /** + * Multiply the {@code Embedding} vector by a multiplier. + * + * @param multiplier The multiplier to multiply the {@code Embedding} vector by + * @return A new {@code Embedding} with the vector multiplied by the multiplier + */ + public Embedding multiply(float multiplier) { + return new Embedding(VectorOperations.multiply(this.vector, multiplier)); + } + + /** + * Divide the {@code Embedding} vector by a divisor. + * + * @param divisor The divisor to divide the {@code Embedding} vector by + * @return A new {@code Embedding} with the vector divided by the divisor + */ + public Embedding divide(float divisor) { + return new Embedding(VectorOperations.divide(this.vector, divisor)); + } + + /** + * Normalizes the underlying vector, such that the Euclidean length is 1. + * + * @return A new {@code Embedding} with the normalized vector + */ + public Embedding normalize() { + return new Embedding(VectorOperations.normalize(this.vector)); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/EmbeddingGeneration.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/EmbeddingGeneration.java new file mode 100644 index 0000000000..d85656a9ba --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/EmbeddingGeneration.java @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.ai.embeddings; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.services.AIService; +import java.util.List; +import reactor.core.publisher.Mono; + +/** Interface for text embedding generation services */ +public interface EmbeddingGeneration extends AIService, Buildable { + /** + * Generates a list of embeddings associated to the data + * + * @param data List of texts to generate embeddings for + * @return List of embeddings of each data point + */ + Mono> generateEmbeddingsAsync(List data); + + interface Builder> extends SemanticKernelBuilder { + + Builder withOpenAIClient(OpenAIAsyncClient client); + + Builder withModelId(String modelId); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/TextEmbeddingGeneration.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/TextEmbeddingGeneration.java new file mode 100644 index 0000000000..d956c99455 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/TextEmbeddingGeneration.java @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.ai.embeddings; + +import com.microsoft.semantickernel.services.AIService; + +/** Interface for text embedding generation services */ +public interface TextEmbeddingGeneration extends EmbeddingGeneration, AIService { + interface Builder extends EmbeddingGeneration.Builder {} +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/VectorOperations.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/VectorOperations.java new file mode 100644 index 0000000000..7883cc9584 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/ai/embeddings/VectorOperations.java @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.ai.embeddings; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; + +final class VectorOperations { + + /** + * Calculates the cosine similarity of two vectors. The vectors must be equal in length and have + * non-zero norm. + * + * @param x First vector, which is not modified + * @param y Second vector, which is not modified + * @return The cosine similarity of the two vectors + */ + static float cosineSimilarity(@Nonnull List x, @Nonnull List y) { + Objects.requireNonNull(x); + Objects.requireNonNull(y); + + if (x.size() != y.size()) { + throw new IllegalArgumentException("Vectors lengths must be equal"); + } + + float dotProduct = dot(x, y); + float normX = dot(x, x); + float normY = dot(y, y); + + if (normX == 0 || normY == 0) { + throw new IllegalArgumentException("Vectors cannot have zero norm"); + } + + return dotProduct / (float) (Math.sqrt(normX) * Math.sqrt(normY)); + } + + /** + * Divides the elements of the vector by the divisor. + * + * @param vector Vector to divide, which is not modified + * @param divisor Divisor to apply to each element of the vector + * @return A new vector with the elements divided by the divisor + */ + static List divide(@Nonnull List vector, float divisor) { + Objects.requireNonNull(vector); + if (Float.isNaN(divisor)) { + throw new IllegalArgumentException("Divisor cannot be NaN"); + } + if (divisor == 0f) { + throw new IllegalArgumentException("Divisor cannot be zero"); + } + + return vector.stream().map(x -> x / divisor).collect(Collectors.toList()); + } + + static float dot(@Nonnull List x, @Nonnull List y) { + Objects.requireNonNull(x); + Objects.requireNonNull(y); + + if (x.size() != y.size()) { + throw new IllegalArgumentException("Vectors lengths must be equal"); + } + + float result = 0; + for (int i = 0; i < x.size(); ++i) { + result += x.get(i) * y.get(i); + } + + return result; + } + + /** + * Calculates the Euclidean length of a vector. + * + * @param vector Vector to calculate the length of, which is not modified + * @return The Euclidean length of the vector + */ + static float euclideanLength(@Nonnull List vector) { + Objects.requireNonNull(vector); + return (float) Math.sqrt(dot(vector, vector)); + } + + /** + * Multiplies the elements of the vector by the multiplier. + * + * @param vector Vector to multiply, which is not modified + * @param multiplier Multiplier to apply to each element of the vector + * @return A new vector with the elements multiplied by the multiplier + */ + static List multiply(@Nonnull List vector, float multiplier) { + Objects.requireNonNull(vector); + if (Float.isNaN(multiplier)) { + throw new IllegalArgumentException("Multiplier cannot be NaN"); + } + if (Float.isInfinite(multiplier)) { + throw new IllegalArgumentException("Multiplier cannot be infinite"); + } + + return vector.stream().map(x -> x * multiplier).collect(Collectors.toList()); + } + + /** + * Normalizes the vector such that the Euclidean length is 1. + * + * @param vector Vector to normalize, which is not modified + * @return A new, normalized vector + */ + static List normalize(@Nonnull List vector) { + Objects.requireNonNull(vector); + return divide(vector, euclideanLength(vector)); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/Buildable.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/Buildable.java new file mode 100644 index 0000000000..b04296b6c2 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/Buildable.java @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.builders; + +/** + * A marker interface for all classes that are buildable, typically via obtaining a builder from + * {@link com.microsoft.semantickernel.SKBuilders}. + */ +public interface Buildable {} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/BuildersSingleton.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/BuildersSingleton.java new file mode 100644 index 0000000000..3ba14ec468 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/BuildersSingleton.java @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.builders; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.KernelConfig; +import com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.memory.MemoryStore; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.templateengine.PromptTemplateEngine; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Enum singleton that service loads builder implementations */ +@SuppressWarnings("ImmutableEnumChecker") +public enum BuildersSingleton { + INST; + + // Fallback classes in case the META-INF/services directory is missing + // Keep this list in alphabetical order by fallback variable name + + private static final String FALLBACK_CHAT_COMPLETION_BUILDER_CLASS = + "com.microsoft.semantickernel.connectors.ai.openai.chatcompletion.OpenAIChatCompletion$Builder"; + private static final String FALLBACK_COMPLETION_CONFIG_BUILDER_CLASS = + "com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig$CompletionConfigBuilder"; + private static final String FALLBACK_COMPLETION_FUNCTION_BUILDER_CLASS = + "com.microsoft.semantickernel.orchestration.DefaultCompletionSKFunction$Builder"; + private static final String FALLBACK_CONTEXT_BUILDER_CLASS = + "com.microsoft.semantickernel.orchestration.DefaultSKContext$Builder"; + private static final String FALLBACK_TEXT_EMBEDDING_GENERATION_BUILDER_CLASS = + "com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration$Builder"; + private static final String FALLBACK_KERNEL_BUILDER_CLASS = + "com.microsoft.semantickernel.DefaultKernel$Builder"; + private static final String FALLBACK_KERNEL_CONFIG_BUILDER_CLASS = + "com.microsoft.semantickernel.KernelConfig$Builder"; + private static final String FALLBACK_PROMPT_TEMPLATE_BUILDER_CLASS = + "com.microsoft.semantickernel.semanticfunctions.DefaultPromptTemplate$Builder"; + private static final String FALLBACK_PROMPT_TEMPLATE_ENGINE_BUILDER_CLASS = + "com.microsoft.semantickernel.templateengine.DefaultPromptTemplateEngine$Builder"; + private static final String FALLBACK_MEMORY_STORE_BUILDER_CLASS = + "com.microsoft.semantickernel.memory.VolatileMemoryStore$Builder"; + private static final String FALLBACK_SEMANTIC_TEXT_MEMORY_CLASS = + "com.microsoft.semantickernel.memory.DefaultSemanticTextMemory$Builder"; + private static final String FALLBACK_SKILL_COLLECTION_BUILDER_CLASS = + "com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection$Builder"; + private static final String FALLBACK_TEXT_COMPLETION_BUILDER_CLASS = + "com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion$Builder"; + private static final String FALLBACK_VARIABLE_BUILDER_CLASS = + "com.microsoft.semantickernel.orchestration.DefaultContextVariables$Builder"; + + private final Map>, Supplier> + builders = new HashMap<>(); + + BuildersSingleton() { + try { + // Keep this list in alphabetical order by fallback variable name + registerBuilder(ChatCompletion.Builder.class, FALLBACK_CHAT_COMPLETION_BUILDER_CLASS); + registerBuilder( + PromptTemplateConfig.CompletionConfigBuilder.class, + FALLBACK_COMPLETION_CONFIG_BUILDER_CLASS); + registerBuilder( + CompletionSKFunction.Builder.class, FALLBACK_COMPLETION_FUNCTION_BUILDER_CLASS); + registerBuilder(SKContext.Builder.class, FALLBACK_CONTEXT_BUILDER_CLASS); + registerBuilder( + TextEmbeddingGeneration.Builder.class, + FALLBACK_TEXT_EMBEDDING_GENERATION_BUILDER_CLASS); + registerBuilder(Kernel.Builder.class, FALLBACK_KERNEL_BUILDER_CLASS); + registerBuilder(KernelConfig.Builder.class, FALLBACK_KERNEL_CONFIG_BUILDER_CLASS); + registerBuilder(MemoryStore.Builder.class, FALLBACK_MEMORY_STORE_BUILDER_CLASS); + registerBuilder(PromptTemplate.Builder.class, FALLBACK_PROMPT_TEMPLATE_BUILDER_CLASS); + registerBuilder( + PromptTemplateEngine.Builder.class, + FALLBACK_PROMPT_TEMPLATE_ENGINE_BUILDER_CLASS); + registerBuilder(SemanticTextMemory.Builder.class, FALLBACK_SEMANTIC_TEXT_MEMORY_CLASS); + registerBuilder( + ReadOnlySkillCollection.Builder.class, FALLBACK_SKILL_COLLECTION_BUILDER_CLASS); + registerBuilder(TextCompletion.Builder.class, FALLBACK_TEXT_COMPLETION_BUILDER_CLASS); + registerBuilder(ContextVariables.Builder.class, FALLBACK_VARIABLE_BUILDER_CLASS); + } catch (Throwable e) { + Logger LOGGER = LoggerFactory.getLogger(BuildersSingleton.class); + LOGGER.error("Failed to discover Semantic Kernel Builders", e); + LOGGER.error( + "This is likely due to:\n\n" + + "- The Semantic Kernel implementation (typically provided by" + + " semantickernel-core) is not present on the classpath at runtime, ensure" + + " that this dependency is available at runtime. In maven this would be" + + " achieved by adding:\n" + + "\n" + + " \n" + + " com.microsoft.semantickernel\n" + + " semantickernel-core\n" + + " ${skversion}\n" + + " runtime\n" + + " \n\n" + + "- The META-INF/services files that define the service loading have been" + + " filtered out and are not present within the running application\n\n" + + "- The class names have been changed (for instance shaded) preventing" + + " discovering the classes"); + + throw e; + } + } + + @SuppressWarnings("unchecked") + private > void registerBuilder( + Class clazz, String fallbackClassName) { + builders.put( + clazz, + (Supplier) + ServiceLoadUtil.findServiceLoader(clazz, fallbackClassName)); + } + + @SuppressWarnings("unchecked") + public > T getInstance(Class clazz) { + return (T) builders.get(clazz).get(); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SemanticKernelBuilder.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SemanticKernelBuilder.java new file mode 100644 index 0000000000..784e460b5a --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/SemanticKernelBuilder.java @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.builders; + +/** + * Interface for all builders that create Buildable objects. Typically, these builders can be + * obtained via {@link com.microsoft.semantickernel.SKBuilders}. + * + * @param + */ +public interface SemanticKernelBuilder { + + /** + * Build the object. + * + * @return a constructed object. + */ + T build(); +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/ServiceLoadUtil.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/ServiceLoadUtil.java new file mode 100644 index 0000000000..fd1b2a1b1e --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/builders/ServiceLoadUtil.java @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.builders; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ServiceLoader; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ServiceLoadUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceLoadUtil.class); + + private ServiceLoadUtil() {} + + public static > + Supplier findServiceLoader(Class clazz, String alternativeClassName) { + List services = findAllServiceLoaders(clazz); + + T impl = null; + + if (services.size() > 0) { + impl = services.get(0); + } + + if (impl == null) { + try { + // Service loader not found, attempt to load the alternative class + Object instance = + Class.forName(alternativeClassName).getDeclaredConstructor().newInstance(); + if (clazz.isInstance(instance)) { + impl = (T) instance; + } + } catch (ClassNotFoundException + | InvocationTargetException + | InstantiationException + | IllegalAccessException + | NoSuchMethodException + | RuntimeException e) { + LOGGER.error("Unable to load service " + clazz.getName() + " ", e); + } + + if (impl == null) { + throw new RuntimeException("Service not found: " + clazz.getName()); + } + } + + try { + Constructor constructor = impl.getClass().getConstructor(); + + // Test that we can construct the builder + if (!clazz.isInstance(constructor.newInstance())) { + throw new RuntimeException( + "Builder creates instance of the wrong type: " + clazz.getName()); + } + + return () -> { + try { + return (T) constructor.newInstance(); + } catch (InstantiationException + | IllegalAccessException + | InvocationTargetException e) { + throw new RuntimeException(e); + } + }; + } catch (NoSuchMethodException e) { + throw new RuntimeException( + "Builder requires a no args constructor: " + clazz.getName()); + } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Builder is of wrong type: " + clazz.getName()); + } + } + + static List findAllServiceLoaders(Class clazz) { + List serviceLoaders = new ArrayList(); + + ServiceLoader factory = ServiceLoader.load(clazz); + Iterator iterator = factory.iterator(); + iterator.forEachRemaining(serviceLoaders::add); + + return serviceLoaders; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatCompletion.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatCompletion.java new file mode 100644 index 0000000000..5d4ea52648 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatCompletion.java @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.chatcompletion; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.ChatCompletions; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.services.AIService; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import javax.annotation.Nullable; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ChatCompletion + extends AIService, TextCompletion, Buildable { + + /** + * Generate a new chat message + * + * @param chat Chat history + * @param requestSettings AI request settings + * @return Generated chat message in string format + */ + Mono generateMessageAsync( + ChatHistoryType chat, @Nullable ChatRequestSettings requestSettings); + + /** + * Create a new empty chat instance + * + * @param instructions Optional chat instructions for the AI service + * @return Chat object + */ + ChatHistoryType createNewChat(@Nullable String instructions); + + Flux generateMessageStream( + ChatHistoryType chatHistory, @Nullable ChatRequestSettings requestSettings); + + Flux getStreamingChatCompletionsAsync( + ChatHistoryType chat, ChatRequestSettings requestSettings); + + @SuppressWarnings("unchecked") + static > + Builder builder() { + return (Builder) BuildersSingleton.INST.getInstance(Builder.class); + } + + interface Builder + extends SemanticKernelBuilder> { + + Builder withOpenAIClient(OpenAIAsyncClient client); + + Builder withModelId(String modelId); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatHistory.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatHistory.java new file mode 100644 index 0000000000..e14b9f61ed --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatHistory.java @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.chatcompletion; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** Provides a history of messages between the User, Assistant and System */ +public class ChatHistory { + + private final List messages; + + public ChatHistory() { + this.messages = new ArrayList<>(); + } + + /** + * Get the chat history + * + * @return List of messages in the chat + */ + public List getMessages() { + return Collections.unmodifiableList(messages); + } + + /** + * Get last message + * + * @return The most recent message in chat + */ + public Optional getLastMessage() { + if (messages.isEmpty()) { + return Optional.empty(); + } + return Optional.of(messages.get(messages.size() - 1)); + } + + /** Role of the author of a chat message */ + public enum AuthorRoles { + Unknown, + System, + User, + Assistant + } + + /** Chat message representation */ + public static class Message { + private final AuthorRoles authorRoles; + + private final String content; + + /** + * Create a new instance + * + * @param authorRoles Role of message author + * @param content Message content + */ + public Message(AuthorRoles authorRoles, String content) { + this.authorRoles = authorRoles; + this.content = content; + } + + /** + * Get the role of the message author + * + * @return Role of the message author, e.g. user/assistant/system + */ + public AuthorRoles getAuthorRoles() { + return authorRoles; + } + + /** + * Get the message content + * + * @return Message content + */ + public String getContent() { + return content; + } + } + + /** + * Add a message to the chat history + * + * @param authorRole Role of the message author + * @param content Message content + */ + public void addMessage(AuthorRoles authorRole, String content) { + this.messages.add(new Message(authorRole, content)); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatRequestSettings.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatRequestSettings.java new file mode 100644 index 0000000000..a427c4ab02 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/chatcompletion/ChatRequestSettings.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.chatcompletion; + +import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings; +import javax.annotation.Nonnull; + +/** Settings for a chat completion request */ +public class ChatRequestSettings extends CompletionRequestSettings { + public ChatRequestSettings() { + super(); + } + + public ChatRequestSettings(@Nonnull CompletionRequestSettings requestSettings) { + super(requestSettings); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/ConfigurationException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/ConfigurationException.java new file mode 100644 index 0000000000..abc3def774 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/ConfigurationException.java @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.exceptions; + +import com.microsoft.semantickernel.SKCheckedException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Kernel logic exception */ +public class ConfigurationException extends SKCheckedException { + + @Nonnull private final ErrorCodes errorCode; + + public ConfigurationException(@Nonnull ErrorCodes error) { + this(error, null, null); + } + + public ConfigurationException(@Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + public ConfigurationException( + @Nonnull ErrorCodes errorCode, + @Nullable String message, + @Nullable Throwable innerException) { + super(formatDefaultMessage(errorCode.getMessage(), message), innerException); + this.errorCode = errorCode; + } + + public ErrorCodes getErrorCode() { + return errorCode; + } + + public enum ErrorCodes { + UNKNOWN_ERROR("Unknown error"), + + CONFIGURATION_NOT_FOUND("Could not find configuration file"), + + COULD_NOT_READ_CONFIGURATION("Could not parse or load configuration file"), + NO_VALID_CONFIGURATIONS_FOUND("Could not find any valid configuration settings"), + VALUE_NOT_FOUND("Could not find value for configuration key"); + + private final String message; + + ErrorCodes(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public String getMessage(String param) { + return String.format(message, param); + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/NotSupportedException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/NotSupportedException.java new file mode 100644 index 0000000000..54da7df6d8 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/NotSupportedException.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.exceptions; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class NotSupportedException extends SKException { + + private final ErrorCodes errorCode; + + public NotSupportedException(@Nonnull ErrorCodes errorCode) { + this(errorCode, null, null); + } + + public NotSupportedException(@Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + public NotSupportedException( + @Nonnull ErrorCodes errorCode, @Nullable String message, @Nullable Throwable cause) { + super(formatDefaultMessage(errorCode.getMessage(), message), cause); + this.errorCode = errorCode; + } + + public ErrorCodes getErrorCode() { + return errorCode; + } + + public enum ErrorCodes { + NOT_SUPPORTED("Not Supported"); + + final String message; + + ErrorCodes(String message) { + this.message = message; + } + + String getMessage() { + return message; + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SkillsNotFoundException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SkillsNotFoundException.java new file mode 100644 index 0000000000..8199f28506 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/exceptions/SkillsNotFoundException.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.exceptions; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class SkillsNotFoundException extends SKException { + + private final ErrorCodes errorCode; + + public SkillsNotFoundException(@Nonnull ErrorCodes errorCodes) { + this(errorCodes, null, null); + } + + public SkillsNotFoundException(@Nonnull ErrorCodes errorCodes, @Nullable String message) { + this(errorCodes, message, null); + } + + public SkillsNotFoundException( + @Nonnull ErrorCodes errorCodes, @Nullable String message, @Nullable Throwable cause) { + super(formatDefaultMessage(errorCodes.getMessage(), message), cause); + this.errorCode = errorCodes; + } + + public ErrorCodes getErrorCode() { + return errorCode; + } + + public enum ErrorCodes { + SKILLS_NOT_FOUND("Skills not found"); + + final String message; + + ErrorCodes(String message) { + this.message = message; + } + + String getMessage() { + return message; + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/extensions/KernelExtensions.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/extensions/KernelExtensions.java new file mode 100644 index 0000000000..f5cfaf4d6c --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/extensions/KernelExtensions.java @@ -0,0 +1,186 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.extensions; + +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.semantickernel.KernelException; +import com.microsoft.semantickernel.KernelException.ErrorCodes; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig; +import com.microsoft.semantickernel.templateengine.PromptTemplateEngine; +import com.microsoft.semantickernel.util.EmbeddedResourceLoader; +import com.microsoft.semantickernel.util.EmbeddedResourceLoader.ResourceLocation; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KernelExtensions { + + private static final Logger LOGGER = LoggerFactory.getLogger(KernelExtensions.class); + private static final String CONFIG_FILE = "config.json"; + private static final String PROMPT_FILE = "skprompt.txt"; + + private KernelExtensions() {} + + public static Map importSemanticSkillFromDirectory( + String parentDirectory, + String skillDirectoryName, + PromptTemplateEngine promptTemplateEngine) { + + // Verify.ValidSkillName(skillDirectoryName); + File skillDir = new File(parentDirectory, skillDirectoryName); + // Verify.DirectoryExists(skillDir); + + File[] files = skillDir.listFiles(); + if (files == null) { + throw new KernelException( + ErrorCodes.FUNCTION_NOT_AVAILABLE, + "No Skills found in directory " + skillDir.getAbsolutePath()); + } + + HashMap skills = new HashMap<>(); + + for (File dir : files) { + try { + // Continue only if prompt template exists + File promptPath = new File(dir, PROMPT_FILE); + if (!promptPath.exists()) { + continue; + } + + // Load prompt configuration. Note: the configuration is + // optional. + PromptTemplateConfig config = new PromptTemplateConfig("", "", null); + + File configPath = new File(dir, CONFIG_FILE); + if (configPath.exists()) { + config = new ObjectMapper().readValue(configPath, PromptTemplateConfig.class); + + // Verify.NotNull(config, $"Invalid prompt template + // configuration, unable to parse {configPath}"); + } + + // kernel.Log.LogTrace("Config {0}: {1}", functionName, + // config.ToJson()); + + // Load prompt template + String template = + new String( + Files.readAllBytes(promptPath.toPath()), Charset.defaultCharset()); + + PromptTemplate promptTemplate = + SKBuilders.promptTemplate() + .withPromptTemplate(template) + .withPromptTemplateConfig(config) + .withPromptTemplateEngine(promptTemplateEngine) + .build(); + + skills.put(dir.getName(), new SemanticFunctionConfig(config, promptTemplate)); + } catch (IOException e) { + LOGGER.error("Failed to read file", e); + } + } + + return skills; + } + + public static Map importSemanticSkillFromResourcesDirectory( + String pluginDirectory, + String pluginName, + String functionName, + @Nullable Class clazz, + PromptTemplateEngine promptTemplateEngine) throws KernelException { + + PromptTemplateConfig config = + getPromptTemplateConfig(pluginDirectory, pluginName, functionName, clazz); + + if (config == null) { + config = new PromptTemplateConfig("", "", null); + } + + String template = getTemplatePrompt(pluginDirectory, pluginName, functionName, clazz); + + HashMap skills = new HashMap<>(); + + PromptTemplate promptTemplate = + SKBuilders.promptTemplate() + .withPromptTemplate(template) + .withPromptTemplateConfig(config) + .withPromptTemplateEngine(promptTemplateEngine) + .build(); + + skills.put(functionName, new SemanticFunctionConfig(config, promptTemplate)); + + return skills; + } + + private static String getTemplatePrompt( + String pluginDirectory, String pluginName, String functionName, @Nullable Class clazz) { + String promptFileName = + pluginDirectory + + File.separator + + pluginName + + File.separator + + functionName + + File.separator + + PROMPT_FILE; + + try { + return EmbeddedResourceLoader.readFile( + promptFileName, + clazz, + ResourceLocation.CLASSPATH_ROOT, + ResourceLocation.CLASSPATH, + ResourceLocation.FILESYSTEM); + } catch (IOException e) { + LOGGER.error("Failed to read file " + promptFileName, e); + + throw new KernelException( + ErrorCodes.FUNCTION_NOT_AVAILABLE, + "No Skills found in directory " + promptFileName); + } + } + + private static PromptTemplateConfig getPromptTemplateConfig( + String pluginDirectory, String pluginName, String functionName, @Nullable Class clazz) throws KernelException { + String configFileName = + pluginDirectory + + File.separator + + pluginName + + File.separator + + functionName + + File.separator + + CONFIG_FILE; + + try { + String config = + EmbeddedResourceLoader.readFile( + configFileName, + clazz, + ResourceLocation.CLASSPATH_ROOT, + ResourceLocation.CLASSPATH, + ResourceLocation.FILESYSTEM); + + return new ObjectMapper().readValue(config, PromptTemplateConfig.class); + } catch (IOException e) { + if (e instanceof JsonMappingException) { + LOGGER.error("Failed to parse config file " + configFileName, e); + + throw new KernelException( + ErrorCodes.FUNCTION_CONFIGURATION_ERROR, + "Failed to parse config file " + configFileName, e); + } else { + LOGGER.debug("No config for " + functionName + " in " + pluginName); + } + return null; + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/DataEntryBase.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/DataEntryBase.java new file mode 100644 index 0000000000..fdb63f7b97 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/DataEntryBase.java @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import java.time.ZonedDateTime; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** A base class for data entries. */ +public class DataEntryBase { + @Nonnull private final String key; + @Nullable private final ZonedDateTime timestamp; + + /** + * Creates an instance of a {@code DataEntryBase}. + * + * @param key The key of the data. + * @param timestamp The timestamp of the data. + */ + public DataEntryBase(@Nullable String key, @Nullable ZonedDateTime timestamp) { + this.key = key != null ? key : ""; + this.timestamp = timestamp; + } + + /** + * Gets the key of the data. + * + * @return The key of the data + */ + public String getKey() { + return key; + } + + /** + * Gets the timestamp of the data. + * + * @return The timestamp of the data. + */ + @Nullable + public ZonedDateTime getTimestamp() { + return timestamp; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryException.java new file mode 100644 index 0000000000..415df3e638 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryException.java @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Exception thrown for errors related to memory logic. */ +public class MemoryException extends SKException { + @Nonnull private final ErrorCodes errorCode; + + /** + * Initializes a new instance of the {@code MemoryException} class with a provided error code. + * + * @param error The error code. + */ + public MemoryException(@Nonnull ErrorCodes error) { + this(error, null, null); + } + + /** + * Initializes a new instance of the {@code MemoryException} class with a provided error code + * and message. + * + * @param errorCode The error code. + * @param message A string that describes the error. + */ + public MemoryException(@Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + /** + * Initializes a new instance of the {@code MemoryException} class with a provided error code, + * message, and inner exception. + * + * @param errorCode The error code. + * @param message A string that describes the error. + * @param innerException The exception that is the cause of the current exception. + */ + public MemoryException( + @Nonnull ErrorCodes errorCode, + @Nullable String message, + @Nullable Throwable innerException) { + super(formatDefaultMessage(errorCode.getMessage(), message), innerException); + this.errorCode = errorCode; + } + + /** + * Gets the error code for this exception. + * + * @return The error code for this exception. + */ + public ErrorCodes getErrorCode() { + return errorCode; + } + + /** Semantic kernel memory error codes. */ + public enum ErrorCodes { + /** Unknown error. */ + UNKNOWN("Unknown error"), + + /** Failed to create collection. */ + FAILED_TO_CREATE_COLLECTION("Failed to create collection"), + + /** Failed to delete collection. */ + FAILED_TO_DELETE_COLLECTION("Failed to delete collection"), + + /** Unable to construct memory from serialized metadata. */ + UNABLE_TO_DESERIALIZE_MEMORY("Unable to deserialize memory"), + + /** Unable to serialize a memory . */ + UNABLE_TO_SERIALIZE_MEMORY("Unable to serialize memory"), + + /** Unable to build memory. */ + UNABLE_TO_BUILD_MEMORY("Unable to build memory"), + + /** Attempted to access a memory collection that does not exist. */ + ATTEMPTED_TO_ACCESS_NONEXISTENT_COLLECTION("Attempted to access non-existent collection"), + + /** Attempted to access a memory that does not exist. */ + MEMORY_NOT_FOUND("Memory not found"); + + /** + * Gets the error message. + * + * @return The error message. + */ + public String getMessage() { + return message; + } + + private ErrorCodes(String message) { + this.message = message; + } + + private final String message; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryQueryResult.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryQueryResult.java new file mode 100644 index 0000000000..819c9e4d46 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryQueryResult.java @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import javax.annotation.Nonnull; + +/** Copy of metadata associated with a memory entry. */ +public class MemoryQueryResult { + /** + * Whether the source data used to calculate embeddings are stored in the local storage provider + * or is available through an external service, such as website, MS Graph, etc. + */ + @Nonnull private final MemoryRecordMetadata metadata; + + /** Search relevance, from 0 to 1, where 1 means perfect match. */ + private final double relevance; + + /** + * Create a new instance of MemoryQueryResult + * + * @param metadata Whether the source data used to calculate embeddings are stored in the local + * storage provider or is available through an external service, such as website, MS Graph, + * etc. + * @param relevance Search relevance, from 0 to 1, where 1 means perfect match. + */ + public MemoryQueryResult(@Nonnull MemoryRecordMetadata metadata, double relevance) { + this.metadata = metadata; + this.relevance = clampRelevance(relevance); + } + + public MemoryRecordMetadata getMetadata() { + return metadata; + } + + public double getRelevance() { + return relevance; + } + + // function to clamp relevance to [0, 1] + private static double clampRelevance(double relevance) { + return !Double.isNaN(relevance) ? Math.max(0, Math.min(1, relevance)) : 0d; + } + + /* + /// + /// Create a new instance of MemoryQueryResult from a json string representing MemoryRecord metadata. + /// + /// The json string to deserialize. + /// The similarity score associated with the result. + /// A new instance of MemoryQueryResult. + /// + public static MemoryQueryResult FromJsonMetadata( + string json, + double relevance) + { + var metadata = JsonSerializer.Deserialize(json); + if (metadata != null) + { + return new MemoryQueryResult(metadata, relevance); + } + else + { + throw new MemoryException( + MemoryException.ErrorCodes.UnableToDeserializeMetadata, + "Unable to create memory query result from serialized metadata"); + } + } + + internal static MemoryQueryResult FromMemoryRecord( + MemoryRecord rec, + double relevance) + { + return new MemoryQueryResult( + (MemoryRecordMetadata)rec.Metadata.Clone(), + relevance); + } + + */ +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecord.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecord.java new file mode 100644 index 0000000000..4845cc1297 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecord.java @@ -0,0 +1,196 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.memory.MemoryException.ErrorCodes; +import java.time.ZonedDateTime; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * A record in a Semantic Kernel memory. IMPORTANT: this is a storage schema. Changing the fields + * will invalidate existing metadata stored in persistent vector DBs. + */ +public class MemoryRecord extends DataEntryBase { + @Nonnull private final Embedding embedding; + + @Nonnull private final MemoryRecordMetadata metadata; + + /** + * Creates an instance of a {@code MemoryRecord}. + * + * @param metadata The metadata associated with a Semantic Kernel memory. + * @param embedding The source content embeddings. + * @param key The key of the data. + * @param timestamp The timestamp of the data. + */ + @JsonCreator + public MemoryRecord( + @JsonProperty("additional_metadata") @Nonnull MemoryRecordMetadata metadata, + @JsonProperty("embedding") @Nonnull Embedding embedding, + @JsonProperty("key") @Nullable String key, + @JsonProperty("timestamp") @Nullable ZonedDateTime timestamp) { + super(key, timestamp); + this.metadata = metadata; + this.embedding = embedding; + } + + /** + * Gets the source content embeddings. + * + * @return The source content embeddings. + */ + public Embedding getEmbedding() { + return embedding; + } + + /** + * Gets the metadata associated with a Semantic Kernel memory. + * + * @return The metadata associated with a Semantic Kernel memory. + */ + public MemoryRecordMetadata getMetadata() { + return metadata; + } + + /** + * Prepare an instance about a memory which source is stored externally. The universal resource + * identifies points to the URL (or equivalent) to find the original source. + * + * @param externalId URL (or equivalent) to find the original source. + * @param sourceName Name of the external service, e.g. "MSTeams", "GitHub", "WebSite", "Outlook + * IMAP", etc. + * @param description Optional description of the record. Note: the description is not indexed. + * @param embedding Source content embedding. + * @param additionalMetadata Optional string for saving custom metadata. + * @param key Optional existing database key. + * @param timestamp optional timestamp. + * @return Memory record + */ + public static MemoryRecord referenceRecord( + @Nonnull String externalId, + @Nonnull String sourceName, + @Nullable String description, + @Nonnull Embedding embedding, + @Nullable String additionalMetadata, + @Nullable String key, + @Nullable ZonedDateTime timestamp) { + + MemoryRecordMetadata metadata = + new MemoryRecordMetadata( + true, + externalId, + "", + description != null ? description : "", + sourceName, + additionalMetadata != null ? additionalMetadata : ""); + return new MemoryRecord(metadata, embedding, key, timestamp); + } + + /** + * Prepare an instance for a memory stored in the internal storage provider. + * + * @param id Resource identifier within the storage provider, e.g. record ID/GUID/incremental + * counter etc. + * @param text Full text used to generate the embeddings. + * @param description Optional description of the record. Note: the description is not indexed. + * @param embedding Source content embedding. + * @param additionalMetadata Optional string for saving custom metadata. + * @param key Optional existing database key. + * @param timestamp optional timestamp. + * @return Memory record + */ + public static MemoryRecord localRecord( + @Nonnull String id, + @Nonnull String text, + @Nullable String description, + @Nonnull Embedding embedding, + @Nullable String additionalMetadata, + @Nullable String key, + @Nullable ZonedDateTime timestamp) { + + boolean isReference = false; + String emptyString = ""; + MemoryRecordMetadata metadata = + new MemoryRecordMetadata( + isReference, + id, + text, + description != null ? description : emptyString, + emptyString, + additionalMetadata != null ? additionalMetadata : emptyString); + return new MemoryRecord(metadata, embedding, key, timestamp); + } + + /** + * Create a memory record from a memory record's metadata. + * + * @param metadata Metadata associated with a memory. + * @param embedding Optional embedding associated with a memory record. + * @param key Optional existing database key. + * @param timestamp optional timestamp. + * @return Memory record + */ + public static MemoryRecord fromMetadata( + @Nonnull MemoryRecordMetadata metadata, + @Nullable Embedding embedding, + @Nullable String key, + @Nullable ZonedDateTime timestamp) { + return new MemoryRecord( + metadata, embedding != null ? embedding : Embedding.empty(), key, timestamp); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MemoryRecord)) return false; + + MemoryRecord that = (MemoryRecord) o; + + if (!embedding.equals(that.embedding)) return false; + return metadata.equals(that.metadata); + } + + @Override + public int hashCode() { + int result = embedding.hashCode(); + result = 31 * result + metadata.hashCode(); + return result; + } + + @Override + public String toString() { + return "MemoryRecord{" + "embedding=" + embedding + ", metadata=" + metadata + '}'; + } + + public String getSerializedMetadata() throws JsonProcessingException { + return new ObjectMapper().writeValueAsString(this.metadata); + } + + public String getSerializedEmbedding() throws JsonProcessingException { + return new ObjectMapper().writeValueAsString(this.embedding); + } + + public static MemoryRecord fromJsonMetadata( + String json, + @Nullable Embedding embedding, + @Nullable String key, + @Nullable ZonedDateTime timestamp) + throws JsonProcessingException { + MemoryRecordMetadata metadata = + new ObjectMapper().readValue(json, MemoryRecordMetadata.class); + + if (metadata != null) { + return new MemoryRecord( + metadata, embedding != null ? embedding : Embedding.empty(), key, timestamp); + } + + throw new MemoryException( + ErrorCodes.UNABLE_TO_DESERIALIZE_MEMORY, + "Unable to create memory record from serialized metadata"); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecordMetadata.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecordMetadata.java new file mode 100644 index 0000000000..9814264b84 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryRecordMetadata.java @@ -0,0 +1,159 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import javax.annotation.Nonnull; + +/** Class representing the metadata associated with a Semantic Kernel memory. */ +public class MemoryRecordMetadata { + + private final boolean isReference; + + @Nonnull private final String externalSourceName; + + @Nonnull private final String id; + + @Nonnull private final String description; + + @Nonnull private final String text; + + @Nonnull private final String additionalMetadata; + + /** + * Whether the source data used to calculate embeddings are stored in the local storage provider + * or is available through and external service, such as web site, MS Graph, etc. + */ + @JsonProperty("is_reference") + public boolean isReference() { + return isReference; + } + + /** + * A value used to understand which external service owns the data, to avoid storing the + * information inside the URI. E.g. this could be "MSTeams", "WebSite", "GitHub", etc. + * + * @return Name of the external service if isReference is true. + */ + @JsonProperty("external_source_name") + public String getExternalSourceName() { + return externalSourceName; + } + + /** + * Unique identifier. The format of the value is domain specific, so it can be a URL, a GUID, + * etc. + * + * @return Unique string used to identify the {@code MemoryRecord}. + */ + @JsonProperty("id") + public String getId() { + return id; + } + + /** + * Optional title describing the content. Note: the title is not indexed. + * + * @return the optional title describing the content. + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * Source text, available only when the memory is not an external source. + * + * @return Source text when the memory is not an external source. + */ + @JsonProperty("text") + public String getText() { + return text; + } + + /** + * Custom metadata associated with a memory. + * + * @return Custom metadata associated with a memory. + */ + @JsonProperty("additional_metadata") + public String getAdditionalMetadata() { + return additionalMetadata; + } + + /** + * Constructor. + * + * @param isReference True if source data is local, false if source data comes from an external + * service. + * @param id Unique string used to identify the {@code MemoryRecord}. + * @param text Local source data associated with a {@code MemoryRecord} embedding. + * @param description {@code MemoryRecord} description. + * @param externalSourceName Name of the external source if isReference is true. + * @param additionalMetadata Field for saving custom metadata with a memory. + */ + @JsonCreator + public MemoryRecordMetadata( + @JsonProperty("is_reference") boolean isReference, + @JsonProperty("id") @Nonnull String id, + @JsonProperty("text") @Nonnull String text, + @JsonProperty("description") @Nonnull String description, + @JsonProperty("external_source_name") @Nonnull String externalSourceName, + @JsonProperty("additional_metadata") @Nonnull String additionalMetadata) { + this.isReference = isReference; + this.id = id; + this.text = text; + this.description = description; + this.externalSourceName = externalSourceName; + this.additionalMetadata = additionalMetadata; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MemoryRecordMetadata)) return false; + + MemoryRecordMetadata that = (MemoryRecordMetadata) o; + + if (isReference != that.isReference) return false; + if (!externalSourceName.equals(that.externalSourceName)) return false; + if (!id.equals(that.id)) return false; + if (!description.equals(that.description)) return false; + if (!text.equals(that.text)) return false; + return additionalMetadata.equals(that.additionalMetadata); + } + + @Override + public int hashCode() { + int result = (isReference ? 1 : 0); + result = 31 * result + externalSourceName.hashCode(); + result = 31 * result + id.hashCode(); + result = 31 * result + description.hashCode(); + result = 31 * result + text.hashCode(); + result = 31 * result + additionalMetadata.hashCode(); + return result; + } + + @Override + public String toString() { + return "MemoryRecordMetadata{" + + "isReference=" + + isReference + + ", externalSourceName='" + + externalSourceName + + '\'' + + ", id='" + + id + + '\'' + + ", description='" + + description + + '\'' + + ", text='" + + text + + '\'' + + ", additionalMetadata='" + + additionalMetadata + + '\'' + + '}'; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryStore.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryStore.java new file mode 100644 index 0000000000..f88ee29772 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/MemoryStore.java @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import java.util.Collection; +import java.util.List; +import javax.annotation.Nonnull; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; + +/** An interface for storing and retrieving indexed {@link MemoryRecord} objects in a data store. */ +public interface MemoryStore extends Buildable { + + /** + * Creates a new collection in the data store. + * + * @param collectionName The name associated with a collection of embeddings + * @return A future that completes when the collection is created. + */ + Mono createCollectionAsync(@Nonnull String collectionName); + + /** + * Gets all collection names in the data store. + * + * @return An unmodifiable group of collection names. + */ + Mono> getCollectionsAsync(); + + /** + * Determines if a collection exists in the data store. + * + * @param collectionName The name associated with a collection of embeddings. + * @return A future that completes with a boolean indicating whether the collection exists. + */ + Mono doesCollectionExistAsync(@Nonnull String collectionName); + + /** + * Deletes a collection from the data store. + * + * @param collectionName The name associated with a collection of embeddings. + * @return A future that completes when the collection is deleted. + */ + Mono deleteCollectionAsync(@Nonnull String collectionName); + + /** + * 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. + * + * @param collectionName The name associated with a collection of embeddings. + * @param record The memory record to upsert. + * @return The unique identifier for the memory record. + */ + Mono upsertAsync(@Nonnull String collectionName, @Nonnull MemoryRecord record); + + /** + * 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. + * + * @param collectionName The name associated with a collection of vectors. + * @param records The memory records to upsert. + * @return The unique identifiers for the memory records. + */ + Mono> upsertBatchAsync( + @Nonnull String collectionName, @Nonnull Collection records); + + /** + * Gets a memory record from the data store. Does not guarantee that the collection exists. + * + * @param collectionName The name associated with a collection of embeddings. + * @param key The unique id associated with the memory record to get. + * @param withEmbedding If true, the embedding will be returned in the memory record. + * @return The memory record if found, otherwise null. + */ + Mono getAsync( + @Nonnull String collectionName, @Nonnull String key, boolean withEmbedding); + + /** + * Gets a batch of memory records from the data store. Does not guarantee that the collection + * exists. + * + * @param collectionName The name associated with a collection of embedding. + * @param keys The unique ids associated with the memory record to get. + * @param withEmbeddings If true, the embeddings will be returned in the memory records. + * @return The memory records associated with the unique keys provided. + */ + Mono> getBatchAsync( + @Nonnull String collectionName, + @Nonnull Collection keys, + boolean withEmbeddings); + + /** + * Removes a memory record from the data store. Does not guarantee that the collection exists. + * + * @param collectionName The name associated with a collection of embeddings. + * @param key The unique id associated with the memory record to remove. + * @return A {@link Mono} that completes when the operation is done. + */ + Mono removeAsync(@Nonnull String collectionName, @Nonnull String key); + + /** + * Removes a batch of memory records from the data store. Does not guarantee that the collection + * exists. + * + * @param collectionName The name associated with a collection of embeddings. + * @param keys The unique ids associated with the memory record to remove. + * @return A {@link Mono} that completes when the operation is done. + */ + Mono removeBatchAsync(@Nonnull String collectionName, @Nonnull Collection keys); + + /** + * Gets the nearest matches to the {@link Embedding} of type {@code Float}. Does not guarantee + * that the collection exists. + * + * @param collectionName The name associated with a collection of embeddings. + * @param embedding The {@link Embedding} to compare the collection's embeddings with. + * @param limit The maximum number of similarity results to return. + * @param minRelevanceScore The minimum relevance threshold for returned results. + * @param withEmbeddings If true, the embeddings will be returned in the memory records. + * @return A collection of tuples where item1 is a {@link MemoryRecord} and item2 is its + * similarity score as a {@code Float}. + */ + Mono>> getNearestMatchesAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + int limit, + float minRelevanceScore, + boolean withEmbeddings); + + /** + * Gets the nearest match to the {@link Embedding} of type {@code Float}. Does not guarantee + * that the collection exists. + * + * @param collectionName The name associated with a collection of embeddings. + * @param embedding The {@link Embedding} to compare the collection's embeddings with. + * @param minRelevanceScore The minimum relevance threshold for returned results. + * @param withEmbedding If true, the embedding will be returned in the memory record. + * @return A tuple consisting of the {@link MemoryRecord} and item2 is its similarity score as a + * {@code float}. Null if no nearest match found. + */ + Mono> getNearestMatchAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + float minRelevanceScore, + boolean withEmbedding); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(Builder.class); + } + + interface Builder extends SemanticKernelBuilder {} +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/NullMemory.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/NullMemory.java new file mode 100644 index 0000000000..5dd4cd2f9c --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/NullMemory.java @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import java.util.Collections; +import java.util.List; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/** Implementation of {@link SemanticTextMemory} that stores nothing. */ +public final class NullMemory implements SemanticTextMemory { + + private static final NullMemory DEFAULT = new NullMemory(); + + /** + * Gets the singleton instance of {@code }NullMemory}. + * + * @return The singleton instance of {@code NullMemory}. + */ + public static NullMemory getInstance() { + return DEFAULT; + } + + private static final String EMPTY_STRING = ""; + + @Override + @CheckReturnValue + public SemanticTextMemory copy() { + return new NullMemory(); + } + + @Override + public Mono saveInformationAsync( + @Nonnull String collection, + @Nonnull String text, + @Nonnull String externalId, + @Nullable String description, + @Nullable String additionalMetadata) { + return Mono.just(EMPTY_STRING); + } + + @Override + public Mono saveReferenceAsync( + @Nonnull String collection, + @Nonnull String text, + @Nonnull String externalId, + @Nonnull String externalSourceName, + @Nullable String description, + @Nullable String additionalMetadata) { + return Mono.just(EMPTY_STRING); + } + + @Override + public Mono getAsync(String collection, String key, boolean withEmbedding) { + return Mono.empty(); + } + + @Override + public Mono removeAsync(@Nonnull String collection, @Nonnull String key) { + return Mono.empty(); + } + + @Override + public Mono> searchAsync( + @Nonnull String collection, + @Nonnull String query, + int limit, + float minRelevanceScore, + boolean withEmbeddings) { + return Mono.just(Collections.emptyList()); + } + + @Override + public Mono> getCollectionsAsync() { + return Mono.just(Collections.emptyList()); + } + + /* + + /// + public Task SaveInformationAsync( + string collection, + string text, + string id, + string? description = null, + string? additionalMetadata = null, + CancellationToken cancel = default) + { + return Task.FromResult(string.Empty); + } + + /// + public Task SaveReferenceAsync( + string collection, + string text, + string externalId, + string externalSourceName, + string? description = null, + string? additionalMetadata = null, + CancellationToken cancel = default) + { + return Task.FromResult(string.Empty); + } + + /// + public Task GetAsync( + string collection, + string key, + bool withEmbedding = false, + CancellationToken cancel = default) + { + return Task.FromResult(null as MemoryQueryResult); + } + + /// + public Task RemoveAsync( + string collection, + string key, + CancellationToken cancel = default) + { + return Task.CompletedTask; + } + + /// + public IAsyncEnumerable SearchAsync( + string collection, + string query, + int limit = 1, + double minRelevanceScore = 0.7, + bool withEmbeddings = false, + CancellationToken cancel = default) + { + return AsyncEnumerable.Empty(); + } + + /// + public Task> GetCollectionsAsync( + CancellationToken cancel = default) + { + return Task.FromResult(new List() as IList); + } + + private NullMemory() + { + } + + */ +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/SemanticTextMemory.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/SemanticTextMemory.java new file mode 100644 index 0000000000..634039a719 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/memory/SemanticTextMemory.java @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import java.util.List; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/** An interface for semantic memory that creates and recalls memories associated with text. */ +public interface SemanticTextMemory extends Buildable { + + @CheckReturnValue + SemanticTextMemory copy(); + + /** + * Save some information into the semantic memory, keeping a copy of the source information. + * + * @param collection Collection where to save the information. + * @param text Information to save. + * @param externalId Unique identifier, e.g. URL or GUID to the original source. + * @param description Optional description. + * @param additionalMetadata Optional string for saving custom metadata. + * @return Unique identifier of the saved memory record. + */ + public Mono saveInformationAsync( + String collection, + String text, + String externalId, + @Nullable String description, + @Nullable String additionalMetadata); + + /** + * Save some information into the semantic memory, keeping only a reference to the source + * information. + * + * @param collection Collection where to save the information. + * @param text Information to save. + * @param externalId Unique identifier, e.g. URL or GUID to the original source. + * @param externalSourceName Name of the external service, e.g. "MSTeams", "GitHub", "WebSite", + * "Outlook IMAP", etc. + * @param description Optional description. + * @param additionalMetadata Optional string for saving custom metadata. + * @return Unique identifier of the saved memory record. + */ + public Mono saveReferenceAsync( + String collection, + String text, + String externalId, + String externalSourceName, + @Nullable String description, + @Nullable String additionalMetadata); + + /** + * Fetch a memory by key. For local memories the key is the "id" used when saving the record. + * For external reference, the key is the "URI" used when saving the record. + * + * @param collection Collection to search. + * @param key Unique memory record identifier. + * @param withEmbedding Whether to return the embedding of the memory found. + * @return Memory record, or null when nothing is found + */ + public Mono getAsync(String collection, String key, boolean withEmbedding); + + /** + * Remove a memory by key. For local memories the key is the "id" used when saving the record. + * For external reference, the key is the "URI" used when saving the record. + * + * @param collection Collection to search. + * @param key Unique memory record identifier. + * @return Mono completion. + */ + public Mono removeAsync(String collection, String key); + + /** + * Find some information in memory + * + * @param collection Collection to search + * @param query What to search for + * @param limit How many results to return + * @param minRelevanceScore Minimum relevance score, from 0 to 1, where 1 means exact match. + * @param withEmbeddings Whether to return the embeddings of the memories found. + * @return Memories found + */ + public Mono> searchAsync( + String collection, + String query, + int limit, + float minRelevanceScore, + boolean withEmbeddings); + + /** + * Gets a group of all available collection names. + * + * @return A group of collection names. + */ + public Mono> getCollectionsAsync(); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(Builder.class); + } + + interface Builder extends SemanticKernelBuilder { + Builder withStorage(MemoryStore storage); + + Builder withEmbeddingGenerator(EmbeddingGeneration embeddingGenerator); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSKContext.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSKContext.java new file mode 100644 index 0000000000..1a17601545 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSKContext.java @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Semantic Kernel context */ +public abstract class AbstractSKContext implements SKContext { + + private final ReadOnlySkillCollection skills; + private final WritableContextVariables variables; + @Nullable private final SemanticTextMemory memory; + + /** Whether an error occurred while executing functions in the pipeline. */ + private boolean errorOccurred; + + /** When an error occurs, this is the description of the error. */ + private String lastErrorDescription = ""; + + /** When an error occurs, this is the most recent exception. */ + @Nullable private Exception lastException; + + @Nullable + @Override + public String getResult() { + return getVariables().asMap().get(ContextVariables.MAIN_KEY); + } + + /// + /// User variables + /// + @Override + public ContextVariables getVariables() { + return SKBuilders.variables().withVariables(variables.asMap()).build(); + } + + AbstractSKContext(ContextVariables variables) { + this(variables, null, null); + } + + /** + * Constructor for the context. + * + * @param variables Context variables to include in context. + * @param memory Semantic text memory unit to include in context. + * @param skills Skills to include in context. + */ + protected AbstractSKContext( + ContextVariables variables, + @Nullable SemanticTextMemory memory, + @Nullable ReadOnlySkillCollection skills) { + this.variables = + SKBuilders.variables().withVariables(variables.asMap()).build().writableClone(); + + if (memory != null) { + this.memory = memory.copy(); + } else { + this.memory = null; + } + + if (skills == null) { + this.skills = SKBuilders.skillCollection().build(); + } else { + this.skills = skills; + } + } + + protected AbstractSKContext(SKContext toClone, String errorDescription, Exception exception) { + this(toClone.getVariables(), toClone.getSemanticMemory(), toClone.getSkills()); + this.errorOccurred = true; + this.lastErrorDescription = errorDescription; + this.lastException = exception; + } + + @CheckReturnValue + @Override + public SKContext copy() { + ReadOnlySkillCollection clonedSkill; + if (skills == null) { + clonedSkill = null; + } else { + clonedSkill = skills.copy(); + } + return build(variables.writableClone(), memory, clonedSkill); + } + + @Nullable + @Override + public SemanticTextMemory getSemanticMemory() { + return memory != null ? memory.copy() : null; + } + + @Override + public ReadOnlySkillCollection getSkills() { + return skills; + } + + @Override + public SKContext setVariable(@Nonnull String key, @Nonnull String content) { + variables.setVariable(key, content); + return getThis(); + } + + @Override + public SKContext appendToVariable(@Nonnull String key, @Nonnull String content) { + variables.appendToVariable(key, content); + return getThis(); + } + + @Override + public SKContext update(@Nonnull String content) { + variables.update(content); + return getThis(); + } + + @Override + public SKContext update(@Nonnull ContextVariables newData) { + variables.update(newData, true); + return getThis(); + } + + protected abstract SKContext getThis(); + + public boolean isErrorOccurred() { + return errorOccurred; + } + + public String getLastErrorDescription() { + return lastErrorDescription; + } + + @Nullable + public Exception getLastException() { + return new Exception(lastException); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSkFunction.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSkFunction.java new file mode 100644 index 0000000000..6a21b98560 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/AbstractSkFunction.java @@ -0,0 +1,274 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.memory.NullMemory; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.orchestration.FunctionNotRegisteredException.ErrorCodes; +import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier; +import com.microsoft.semantickernel.skilldefinition.ParameterView; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/** Abstract implementation of the SKFunction interface. */ +public abstract class AbstractSkFunction + implements SKFunction, RegistrableSkFunction { + + private final List parameters; + private final String skillName; + private final String functionName; + private final String description; + + private final List returnParameters; + @Nullable private KernelSkillsSupplier skillsSupplier; + + /** + * Constructor. + * + * @param parameters The parameters of the function. + * @param skillName The name of the skill. + * @param functionName The name of the function. + * @param description The description of the function. + * @param skillsSupplier The skill supplier. + */ + public AbstractSkFunction( + List parameters, + String skillName, + String functionName, + String description, + List returnParameters, + @Nullable KernelSkillsSupplier skillsSupplier) { + + this.parameters = new ArrayList<>(parameters); + this.skillName = skillName; + this.functionName = functionName; + this.description = description; + this.returnParameters = Collections.unmodifiableList(returnParameters); + this.skillsSupplier = skillsSupplier; + } + + /** + * Asserts that the skill supplier is registered. + * + * @throws FunctionNotRegisteredException if the skill supplier is not registered. + */ + protected void assertSkillSupplierRegistered() { + if (skillsSupplier == null) { + throw new FunctionNotRegisteredException(ErrorCodes.FUNCTION_NOT_REGISTERED, getName()); + } + } + + /** + * Sets the skill supplier. + * + * @param skillsSupplier The skill supplier. + */ + protected void setSkillsSupplier(@Nullable KernelSkillsSupplier skillsSupplier) { + this.skillsSupplier = skillsSupplier; + } + + /** + * Gets the skill supplier. + * + * @return The skill supplier. + */ + @Nullable + public KernelSkillsSupplier getSkillsSupplier() { + return skillsSupplier; + } + + @Override + public Mono invokeAsync( + @Nullable String input, + @Nullable SKContext context, + @Nullable RequestConfiguration settings) { + if (context == null) { + assertSkillSupplierRegistered(); + + context = + SKBuilders.context() + .withMemory(NullMemory.getInstance()) + .withSkills(skillsSupplier == null ? null : skillsSupplier.get()) + .build(); + } else { + context = context.copy(); + } + + if (input != null) { + context = context.update(input); + } + + return this.invokeAsync(context, settings); + } + + @Override + public Mono invokeAsync(String input) { + return invokeAsync(input, null, null); + } + + @Override + public Mono invokeAsync( + @Nullable SKContext context, @Nullable RequestConfiguration settings) { + if (context == null) { + context = + SKBuilders.context() + .withVariables(SKBuilders.variables().build()) + .withMemory(NullMemory.getInstance()) + .build(); + } else { + context = context.copy(); + } + + return this.invokeAsyncInternal(context, settings); + } + + /** + * The function to invoke asynchronously. + * + * @param context The context. + * @param settings The settings. + * @return A mono of the context with the result. + */ + protected abstract Mono invokeAsyncInternal( + SKContext context, @Nullable RequestConfiguration settings); + + @Override + public String getSkillName() { + return skillName; + } + + @Override + public String getName() { + return functionName; + } + + /** + * The parameters of the function. + * + * @return The parameters of the function. + */ + public List getParametersView() { + return Collections.unmodifiableList(parameters); + } + + /** + * The function to create a fully qualified name for + * + * @return A fully qualified name for a function + */ + @Override + public String toFullyQualifiedName() { + return skillName + "." + functionName; + } + + @Override + @Nullable + public String getDescription() { + return description; + } + + @Override + public String toEmbeddingString() { + String inputs = + parameters.stream() + .map(p -> " - " + p.getName() + ": " + p.getDescription()) + .collect(Collectors.joining("\n")); + + return getName() + ":\n description: " + getDescription() + "\n inputs:\n" + inputs; + } + + @Override + public String toManualString(boolean includeOutputs) { + String inputs = + parameters.stream() + .map( + parameter -> { + String defaultValueString; + if (parameter.getDefaultValue() == null + || parameter.getDefaultValue().isEmpty() + || parameter + .getDefaultValue() + .equals( + SKFunctionParameters + .NO_DEFAULT_VALUE)) { + defaultValueString = ""; + } else { + defaultValueString = + " (default value: " + + parameter.getDefaultValue() + + ")"; + } + + return " - " + + parameter.getName() + + ": " + + parameter.getDescription() + + defaultValueString; + }) + .map(s -> s.toLowerCase(Locale.ROOT)) + .sorted() + .distinct() + .collect(Collectors.joining("\n")); + + String outputsList = ""; + + if (returnParameters.size() > 0) { + + outputsList = + returnParameters.stream() + .filter(it -> !it.getDescription().isEmpty()) + .map(it -> " - " + it.getName() + ": " + it.getDescription()) + .collect(Collectors.joining("\n")); + } + + String outputs = ""; + if (includeOutputs) { + outputs = "\n outputs:\n"; + if (outputsList.length() > 0) { + outputs += outputsList; + } else { + outputs += " - return: void"; + } + } + + return toFullyQualifiedName() + + ":\n" + + " description: " + + getDescription() + + "\n" + + " inputs:\n" + + inputs + + outputs; + } + + @Override + public Mono invokeWithCustomInputAsync( + ContextVariables variables, + @Nullable SemanticTextMemory semanticMemory, + @Nullable ReadOnlySkillCollection skills) { + SKContext tmpContext = + SKBuilders.context() + .withVariables(variables) + .withMemory(semanticMemory) + .withSkills(skills) + .build(); + return invokeAsync(tmpContext, null); + } + + @Override + public Mono invokeAsync() { + return invokeAsync(null, null, null); + } + + @Override + public Mono invokeAsync(SKContext context) { + return invokeAsync(context, null); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ContextVariables.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ContextVariables.java new file mode 100644 index 0000000000..9379f93cfa --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/ContextVariables.java @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +// Copyright (c) Microsoft. All rights reserved. + +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * Context Variables is a data structure that holds temporary data while a task is being performed. + * It is accessed by functions in the pipeline. + */ +public interface ContextVariables extends Buildable { + + /** Default key for the main input */ + String MAIN_KEY = "input"; + + /** + * Get variables as a map + * + * @return Map of variables + */ + Map asMap(); + + /** + * Get a clone of the variables that can be modified + * + * @return Writable clone of the variables + */ + WritableContextVariables writableClone(); + + /** + * Get the input (entry in the MAIN_KEY slot) + * + * @return input + */ + @Nullable + String getInput(); + + /** + * Create formatted string of the variables + * + * @return formatted string + */ + String prettyPrint(); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(ContextVariables.Builder.class); + } + + /** Builder for ContextVariables */ + interface Builder extends SemanticKernelBuilder { + + /** + * Builds an instance with the given content in the default main key + * + * @param content Entry to place in the "input" slot + * @return an instantiation of ContextVariables + */ + Builder withInput(String content); + + /** + * Builds an instance with the given variables + * + * @param map Existing variables + * @return an instantiation of ContextVariables + */ + Builder withVariables(Map map); + + /** + * Set variable + * + * @param key variable name + * @param value variable value + * @return builder for fluent chaining + */ + Builder withVariable(String key, String value); + } + + /** + * Return the variable with the given name + * + * @param key variable name + * @return content of the variable + */ + @Nullable + String get(String key); +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionNotRegisteredException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionNotRegisteredException.java new file mode 100644 index 0000000000..72d1714349 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/FunctionNotRegisteredException.java @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class FunctionNotRegisteredException extends SKException { + + @Nonnull private final ErrorCodes errorCode; + + public FunctionNotRegisteredException(@Nonnull ErrorCodes errorCode) { + this(errorCode, null); + } + + public FunctionNotRegisteredException(@Nonnull ErrorCodes errorCode, @Nullable String name) { + this(errorCode, name, null); + } + + public FunctionNotRegisteredException( + @Nonnull ErrorCodes errorCode, @Nullable String name, @Nullable Throwable cause) { + super(formatDefaultMessage(errorCode, name), cause); + this.errorCode = errorCode; + } + + public ErrorCodes getErrorCode() { + return errorCode; + } + + private static String formatDefaultMessage(@Nonnull ErrorCodes errorCode, String name) { + if (name != null) { + String detailedMessage = + String.format( + "It does not appear this function(%s) has been registered on a" + + " kernel.%nRegister it on a kernel either by passing it to" + + " KernelConfig.Builder().addSkill() when building the kernel," + + " or%npassing it to Kernel.registerSemanticFunction", + name); + return SKException.formatDefaultMessage(errorCode.getErrorMessage(), detailedMessage); + } + return errorCode.getErrorMessage(); + } + + public enum ErrorCodes { + FUNCTION_NOT_REGISTERED("Function not registered"); + + private final String errorMessage; + + ErrorCodes(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getErrorMessage() { + return errorMessage; + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/RegistrableSkFunction.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/RegistrableSkFunction.java new file mode 100644 index 0000000000..004317f92c --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/RegistrableSkFunction.java @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.Kernel; + +public interface RegistrableSkFunction { + + void registerOnKernel(Kernel kernel); +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKContext.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKContext.java new file mode 100644 index 0000000000..fee04b4364 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKContext.java @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import javax.annotation.CheckReturnValue; +import reactor.util.annotation.Nullable; + +/** Semantic Kernel context. */ +public interface SKContext extends Buildable { + + SKContext build( + ContextVariables variables, + @Nullable SemanticTextMemory memory, + @Nullable ReadOnlySkillCollection skills); + + /** + * Obtain the result of the execution that produced this context. This will be the "input" entry + * in the variables. + * + * @return the "input" entry in the variables + */ + @Nullable + String getResult(); + + /** + * Return a copy of all variables within the context + * + * @return a clone of the variables + */ + ContextVariables getVariables(); + + /** + * Provides access to the context's semantic memory + * + * @return the semantic memory + */ + @Nullable + SemanticTextMemory getSemanticMemory(); + + /** + * Provides access to the skills within this context + * + * @return the skills + */ + ReadOnlySkillCollection getSkills(); + + /** + * Sets the given variable + * + * @param key if null defaults to the "input" key + * @param content value to set + * @return Context for fluent calls + */ + SKContext setVariable(String key, String content); + + /** + * Appends data to the given key + * + * @param key key to set + * @param content value to set + * @return Context for fluent calls + */ + SKContext appendToVariable(String key, String content); + + /** + * Updates the input entry with the given data + * + * @param content value to set + * @return Context for fluent calls + */ + @CheckReturnValue + SKContext update(String content); + + /** + * Merges in the given variables. Duplicate keys provided by newData will overwrite existing + * entries. + * + * @param newData variables to merge in + * @return Context for fluent calls + */ + @CheckReturnValue + SKContext update(ContextVariables newData); + + /** + * Clones the context + * + * @return a copy of this context + */ + SKContext copy(); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(SKContext.Builder.class); + } + + interface Builder extends SemanticKernelBuilder { + + Builder withVariables(ContextVariables variables); + + /** + * Clones the given context and sets its result to the given error + * + * @param toClone context to clone + * @param errorDescription description of the error + * @param exception exception to set + * @return Failed context + */ + SKContext failed(SKContext toClone, String errorDescription, Exception exception); + + /** + * Sets the skills + * + * @param skills null argument will be ignored + * @return Context for fluent calls + */ + Builder withSkills(@Nullable ReadOnlySkillCollection skills); + + /** + * Sets the memory + * + * @param memory null argument will be ignored + * @return Context for fluent calls + */ + Builder withMemory(@Nullable SemanticTextMemory memory); + + Builder clone(SKContext context); + + /** + * Builds a context from the given kernel. If not explicitly set, the skills and memory will + * be used from the kernel. + * + * @param kernel Kernel to use + * @return Context + */ + Builder withKernel(Kernel kernel); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKFunction.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKFunction.java new file mode 100644 index 0000000000..d1b932f994 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/SKFunction.java @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.skilldefinition.FunctionView; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/** + * Semantic Kernel callable function interface + * + * @param The type of the configuration argument that will be provided when + * the function is invoked + */ +public interface SKFunction { + /** + * Returns a description of the function, including parameters. + * + * @return An instance of {@link FunctionView} describing the function + */ + @Nullable + FunctionView describe(); + + /** + * Invokes the function with the given input, context and settings + * + * @param input input provided to the function + * @param context Request context + * @param settings Configuration of the request + * @return an updated context with the result of the request + */ + @CheckReturnValue + Mono invokeAsync(String input, SKContext context, RequestConfiguration settings); + + /** + * Invokes the function + * + * @return an updated context with the result of the request + */ + Mono invokeAsync(); + + /** + * Invokes the function with the given input + * + * @param input input provided to the function + * @return an updated context with the result of the request + */ + @CheckReturnValue + Mono invokeAsync(String input); + + /** + * The type of the configuration argument that will be provided when the function is invoked + * + * @return The type + */ + @Nullable + Class getType(); + + /** + * Invokes the function with the given context and settings + * + * @param context Request context + * @return an updated context with the result of the request + */ + @CheckReturnValue + Mono invokeAsync(SKContext context); + + /** + * Invokes the function with the given context and settings + * + * @param context Request context + * @param settings Configuration of the request + * @return an updated context with the result of the request + */ + @CheckReturnValue + Mono invokeAsync(SKContext context, @Nullable RequestConfiguration settings); + + /** + * @return The name of the skill that this function is within + */ + String getSkillName(); + + /** + * @return The name of this function + */ + String getName(); + + /** + * The function to create a fully qualified name for + * + * @return A fully qualified name for a function + */ + String toFullyQualifiedName(); + + /** + * @return A description of the function + */ + String getDescription(); + + /** + * Create a string for generating an embedding for a function. + * + * @return A string for generating an embedding for a function. + */ + String toEmbeddingString(); + + /** + * Create a manual-friendly string for a function. + * + * @param includeOutputs Whether to include function outputs in the string. + * @return A manual-friendly string for a function. + */ + String toManualString(boolean includeOutputs); + + /** + * Invokes the function with the given input, context and settings + * + * @param variables variables to be used in the function + * @param semanticMemory semantic memory to be used in the function + * @param skills skills to be used in the function + * @return an updated context with the result of the request + */ + Mono invokeWithCustomInputAsync( + ContextVariables variables, + @Nullable SemanticTextMemory semanticMemory, + @Nullable ReadOnlySkillCollection skills); +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/WritableContextVariables.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/WritableContextVariables.java new file mode 100644 index 0000000000..239fe27f9a --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/orchestration/WritableContextVariables.java @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import java.util.Map; + +/** + * Context Variables is a data structure that holds temporary data while a task is being performed. + * It is accessed by functions in the pipeline. + */ +public interface WritableContextVariables extends ContextVariables { + + /** + * Set the value + * + * @param key variable name + * @param content value to set + * @return Context for fluent calls + */ + ContextVariables setVariable(String key, String content); + + ContextVariables appendToVariable(String key, String content); + + /** + * Updates the main input text with the new value after a function is complete. + * + * @param content The new input value, for the next function in the pipeline, or as a result for + * the user if the pipeline reached the end. + * @return The current instance + */ + ContextVariables update(String content); + + /** + * Updates the variables merging or overwriting in the new values. + * + * @param newData Data to merge or overwrite. + * @param merge Whether to merge the new data with the existing data or to replace it + * @return The current instance + */ + ContextVariables update(ContextVariables newData, boolean merge); + + ContextVariables remove(String key); + + interface Builder { + /** + * Builds an instance with the given variables + * + * @param map Existing variables + * @return an instantiation of ContextVariables + */ + WritableContextVariables build(Map map); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/planner/PlanningException.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/planner/PlanningException.java new file mode 100644 index 0000000000..9638ab7eda --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/planner/PlanningException.java @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Exception thrown for errors related to planning. */ +public class PlanningException extends SKException { + @Nonnull private final ErrorCodes errorCode; + + public PlanningException(@Nonnull ErrorCodes error) { + this(error, null, null); + } + + /** + * Initializes a new instance of the PlanningException class with a provided error code and + * message + * + * @param errorCode Error code + * @param message The exception message + */ + public PlanningException(@Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + /** + * Initializes a new instance of the PlanningException class with a provided error code, + * message, and inner exception. + * + * @param errorCode The error code + * @param message A string that describes the error + * @param innerException The exception that is the cause of the current exception + */ + public PlanningException( + @Nonnull ErrorCodes errorCode, + @Nullable String message, + @Nullable Throwable innerException) { + super(formatDefaultMessage(errorCode.getMessage(), message), innerException); + this.errorCode = errorCode; + } + + /** + * Gets the error code + * + * @return The error code + */ + public ErrorCodes getErrorCode() { + return errorCode; + } + + /** Error codes for PlanningException */ + public enum ErrorCodes { + UNKNOWN_ERROR("Unknown error"), + + INVALID_GOAL("Invalid goal"), + + INVALID_PLAN("Invalid plan"), + + INVALID_CONFIGURATION("Invalid configuration"), + PLAN_EXECUTION_PRODUCED_NO_RESULTS("Plan execution produced no result values"); + + private final String message; + + ErrorCodes(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java new file mode 100644 index 0000000000..5e4cf5181e --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplate.java @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.semanticfunctions; + +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.ParameterView; +import com.microsoft.semantickernel.templateengine.PromptTemplateEngine; +import java.util.List; +import reactor.core.publisher.Mono; + +/** Interface for prompt template */ +public interface PromptTemplate extends Buildable { + /** + * Get the list of parameters required by the template, using configuration and template info + * + * @return List of parameters + */ + List getParameters(); + + /** + * Render the template using the information in the context + * + * @param executionContext Kernel execution context helpers + * @return Prompt rendered to string + */ + Mono renderAsync(SKContext executionContext); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(Builder.class); + } + + interface Builder extends SemanticKernelBuilder { + + Builder withPromptTemplate(String promptTemplate); + + Builder withPromptTemplateConfig(PromptTemplateConfig config); + + Builder withPromptTemplateEngine(PromptTemplateEngine promptTemplateEngine); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateConfig.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateConfig.java new file mode 100644 index 0000000000..bc48ed0aef --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/PromptTemplateConfig.java @@ -0,0 +1,411 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.semanticfunctions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import reactor.util.annotation.Nullable; + +/** Prompt template configuration */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class PromptTemplateConfig { + private final CompletionConfig completionConfig; + private final InputConfig input; + + /** + * A returns the configuration for the text completion + * + * @return CompletionConfig + */ + public CompletionConfig getCompletionConfig() { + return completionConfig; + } + + public int getSchema() { + return schema; + } + + public String getType() { + return type; + } + + /** Builder for CompletionConfig */ + public static class CompletionConfigBuilder implements SemanticKernelBuilder { + + private CompletionConfig completionConfig; + + public CompletionConfigBuilder() { + completionConfig = new CompletionConfig(); + } + + public CompletionConfigBuilder(CompletionConfig completionConfig) { + this.completionConfig = completionConfig; + } + + public CompletionConfigBuilder temperature(double temperature) { + return new CompletionConfigBuilder( + new CompletionConfig( + temperature, + completionConfig.topP, + completionConfig.presencePenalty, + completionConfig.frequencyPenalty, + completionConfig.maxTokens, + completionConfig.bestOf, + completionConfig.user, + completionConfig.stopSequences)); + } + + public CompletionConfigBuilder topP(double topP) { + return new CompletionConfigBuilder( + new CompletionConfig( + completionConfig.temperature, + topP, + completionConfig.presencePenalty, + completionConfig.frequencyPenalty, + completionConfig.maxTokens, + completionConfig.bestOf, + completionConfig.user, + completionConfig.stopSequences)); + } + + public CompletionConfigBuilder presencePenalty(double presencePenalty) { + return new CompletionConfigBuilder( + new CompletionConfig( + completionConfig.temperature, + completionConfig.topP, + presencePenalty, + completionConfig.frequencyPenalty, + completionConfig.maxTokens, + completionConfig.bestOf, + completionConfig.user, + completionConfig.stopSequences)); + } + + public CompletionConfigBuilder frequencyPenalty(double frequencyPenalty) { + return new CompletionConfigBuilder( + new CompletionConfig( + completionConfig.temperature, + completionConfig.topP, + completionConfig.presencePenalty, + frequencyPenalty, + completionConfig.maxTokens, + completionConfig.bestOf, + completionConfig.user, + completionConfig.stopSequences)); + } + + public CompletionConfigBuilder maxTokens(int maxTokens) { + return new CompletionConfigBuilder( + new CompletionConfig( + completionConfig.temperature, + completionConfig.topP, + completionConfig.presencePenalty, + completionConfig.frequencyPenalty, + maxTokens, + completionConfig.bestOf, + completionConfig.user, + completionConfig.stopSequences)); + } + + public CompletionConfigBuilder stopSequences(List stopSequences) { + return new CompletionConfigBuilder( + new CompletionConfig( + completionConfig.temperature, + completionConfig.topP, + completionConfig.presencePenalty, + completionConfig.frequencyPenalty, + completionConfig.maxTokens, + completionConfig.bestOf, + completionConfig.user, + stopSequences)); + } + + public CompletionConfig build() { + return completionConfig; + } + } + + public InputConfig getInput() { + return input; + } + + /** Completion configuration parameters */ + public static class CompletionConfig implements Buildable { + /* + /// + /// Sampling temperature to use, between 0 and 2. Higher values will make the output more random. + /// Lower values will make it more focused and deterministic. + /// + [JsonPropertyName("temperature")] + [JsonPropertyOrder(1)] + */ + private final double temperature; + /* + /// + /// Cut-off of top_p probability mass of tokens to consider. + /// For example, 0.1 means only the tokens comprising the top 10% probability mass are considered. + /// + [JsonPropertyName("top_p")] + [JsonPropertyOrder(2)] + */ + private final double topP; + + /* + /// + /// Lowers the probability of a word appearing if it already appeared in the predicted text. + /// Unlike the frequency penalty, the presence penalty does not depend on the frequency at which words + /// appear in past predictions. + /// + [JsonPropertyName("presence_penalty")] + [JsonPropertyOrder(3)] + */ + private final double presencePenalty; + + /* + /// + /// Controls the model’s tendency to repeat predictions. The frequency penalty reduces the probability + /// of words that have already been generated. The penalty depends on how many times a word has already + /// occurred in the prediction. + /// + [JsonPropertyName("frequency_penalty")] + [JsonPropertyOrder(4)] + */ + private final double frequencyPenalty; + /* + /// + /// Maximum number of tokens that can be generated. + /// + [JsonPropertyName("max_tokens")] + [JsonPropertyOrder(5)]*/ + private final int maxTokens; // { get; set; } = 256; + /* + /// + /// Stop sequences are optional sequences that tells the AI model when to stop generating tokens. + /// + [JsonPropertyName("stop_sequences")] + [JsonPropertyOrder(6)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + */ + public final List stopSequences; // { get; set; } = new(); + + /** + * The maximum number of completions to generate for each prompt. This is used by the + * CompletionService to generate multiple completions for a single prompt. + */ + private final Integer bestOf; + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and + * detect abuse + */ + private final String user; + + public CompletionConfig() { + this(0.0, 0.0, 0.0, 0.0, 256, 1, "", new ArrayList<>()); + } + + public CompletionConfig( + double temperature, + double topP, + double presencePenalty, + double frequencyPenalty, + int maxTokens) { + this( + temperature, + topP, + presencePenalty, + frequencyPenalty, + maxTokens, + 1, + "", + new ArrayList<>()); + } + + @JsonCreator + public CompletionConfig( + @JsonProperty("temperature") double temperature, + @JsonProperty("top_p") double topP, + @JsonProperty("presence_penalty") double presencePenalty, + @JsonProperty("frequency_penalty") double frequencyPenalty, + @JsonProperty("max_tokens") int maxTokens, + @JsonProperty("best_of") int bestOf, + @JsonProperty("user") String user, + @JsonProperty(value = "stop_sequences") List stopSequences) { + this.temperature = temperature; + this.topP = topP; + this.presencePenalty = presencePenalty; + this.frequencyPenalty = frequencyPenalty; + this.maxTokens = maxTokens; + + // bestOf must be at least 1 + this.bestOf = Math.max(1, bestOf); + + if (user == null) { + user = ""; + } + this.user = user; + if (stopSequences == null) { + stopSequences = new ArrayList<>(); + } + this.stopSequences = stopSequences; + } + + public double getTemperature() { + return temperature; + } + + public double getTopP() { + return topP; + } + + public double getPresencePenalty() { + return presencePenalty; + } + + public double getFrequencyPenalty() { + return frequencyPenalty; + } + + public int getMaxTokens() { + return maxTokens; + } + + /** + * The maximum number of completions to generate for each prompt. This is used by the + * CompletionService to generate multiple completions for a single prompt. + */ + public int getBestOf() { + return bestOf; + } + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and + * detect abuse + */ + public String getUser() { + return user; + } + + public SemanticKernelBuilder builder() { + return BuildersSingleton.INST.getInstance(CompletionConfigBuilder.class); + } + + public List getStopSequences() { + return Collections.unmodifiableList(stopSequences); + } + } + + /** Input parameter for semantic functions */ + public static class InputParameter { + private final String name; + private final String description; + + private final String defaultValue; + + @JsonCreator + public InputParameter( + @JsonProperty("name") String name, + @JsonProperty("description") String description, + @JsonProperty("defaultValue") String defaultValue) { + this.name = name; + this.description = description; + this.defaultValue = defaultValue; + } + + /** + * Name of the parameter to pass to the function. e.g. when using "{{$input}}" the name is + * "input", when using "{{$style}}" the name is "style", etc. + * + * @return name + */ + public String getName() { + return name; + } + + /** + * Parameter description for UI apps and planner. Localization is not supported here. + * + * @return description + */ + public String getDescription() { + return description; + } + + /** + * Default value when nothing is provided + * + * @return the default value + */ + public String getDefaultValue() { + return defaultValue; + } + } + + /** Input configuration (list of all input parameters for a semantic function). */ + public static class InputConfig { + + public final List parameters; + + @JsonCreator + public InputConfig(@JsonProperty("parameters") List parameters) { + this.parameters = Collections.unmodifiableList(parameters); + } + + public List getParameters() { + return parameters; + } + } + + private final int schema; + + private final String type; // { get; set; } = "completion"; + private final String description; + + public PromptTemplateConfig() { + this("", "", null); + } + + public PromptTemplateConfig(CompletionConfig completionConfig) { + this(1, "", "", completionConfig, new InputConfig(new ArrayList<>())); + } + + public PromptTemplateConfig( + String description, String type, @Nullable CompletionConfig completionConfig) { + this(1, description, type, completionConfig, new InputConfig(new ArrayList<>())); + } + + @JsonCreator + public PromptTemplateConfig( + @JsonProperty("schema") int schema, + @JsonProperty("description") String description, + @JsonProperty("type") String type, + @Nullable @JsonProperty("completion") CompletionConfig completionConfig, + @Nullable @JsonProperty("input") InputConfig input) { + if (completionConfig == null) { + completionConfig = new CompletionConfig(); + } + this.schema = schema; + this.description = description; + this.type = type; + this.completionConfig = completionConfig; + if (input == null) { + input = new InputConfig(new ArrayList<>()); + } + this.input = input; + } + + /** + * Description + * + * @return Description + */ + public String getDescription() { + return description; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/SemanticFunctionConfig.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/SemanticFunctionConfig.java new file mode 100644 index 0000000000..70ec601acf --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/semanticfunctions/SemanticFunctionConfig.java @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.semanticfunctions; + +/** Semantic function configuration */ +public class SemanticFunctionConfig { + private final PromptTemplateConfig config; + + /** Prompt template */ + private final PromptTemplate template; + + /** + * Constructor for SemanticFunctionConfig. + * + * @param config Prompt template configuration. + * @param template Prompt template. + */ + public SemanticFunctionConfig(PromptTemplateConfig config, PromptTemplate template) { + this.config = config; + this.template = template; + } + + public PromptTemplateConfig getConfig() { + return config; + } + + public PromptTemplate getTemplate() { + return template; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIService.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIService.java new file mode 100644 index 0000000000..8d8b24559d --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIService.java @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.services; + +/** Marker interface for AI services */ +public interface AIService {} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceCollection.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceCollection.java new file mode 100644 index 0000000000..8c497de45e --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceCollection.java @@ -0,0 +1,166 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.services; + +import com.microsoft.semantickernel.Verify; +import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration; +import com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import javax.annotation.Nullable; + +/** A collection that can hold AI services */ +public class AIServiceCollection { + // A constant key for the default service + private static final String DefaultKey = "__DEFAULT__"; + + private static final List> KNOWN_SERVICES = + Arrays.asList( + EmbeddingGeneration.class, + TextEmbeddingGeneration.class, + TextCompletion.class, + ChatCompletion.class); + + // A dictionary that maps a service type to a nested dictionary of names and service instances + // or factories + // private readonly Dictionary> _services = new(); + private final Map, Map>> + services = new HashMap<>(); + + // A dictionary that maps a service type to the name of the default service + private final Map, String> defaultIds = new HashMap<>(); + + /** + * Registers a singleton service instance with the default name. + * + * @param service The service instance. + * @param serviceType The type of the service. + */ + public void setService(T service, Class serviceType) { + setService(DefaultKey, (Supplier) () -> service, true, serviceType); + } + + /** + * Registers a singleton service instance with an optional name and default flag. + * + * @param name The name of the service, or null for the default service. + * @param service The service instance. + * @param setAsDefault Whether the service should be the default for its type. + * @param serviceType The type of the service. + */ + public void setService( + String name, T service, boolean setAsDefault, Class serviceType) { + setService(name, (Supplier) () -> service, setAsDefault, serviceType); + } + + /** + * Registers a transient service factory with the default name. + * + * @param factory The factory function to create the service instance. + * @param serviceType The type of the service. + */ + public void setService(Supplier factory, Class serviceType) { + setService(DefaultKey, factory, true, serviceType); + } + + /** + * Registers a transient service factory with an optional name and default flag. + * + * @param name The name of the service, or null for the default service. + * @param factory The factory function to create the service instance. + * @param setAsDefault Whether the service should be the default for its type. + * @param specificServiceType The type of the service. + */ + public void setService( + @Nullable String name, + Supplier factory, + boolean setAsDefault, + Class specificServiceType) { + + // Validate the factory function + if (factory == null) { + throw new IllegalArgumentException(); + } + + // if this is an implementation of a known service type, register it as such + getKnownServiceTypes(specificServiceType) + .forEach( + serviceType -> { + // Get or create the nested dictionary for the service type + Map> namedServices = + this.services.computeIfAbsent( + serviceType, (ignore) -> new HashMap<>()); + + // Set as the default if the name is empty, or the default flag is true, + // or there is no default name for the service type. + if (name == null || setAsDefault || !this.hasDefault(serviceType)) { + // Update the default name for the service type + this.defaultIds.put(serviceType, name == null ? DefaultKey : name); + } + + // Register the factory with the given name + namedServices.put(name == null ? DefaultKey : name, factory); + }); + } + + private List> getKnownServiceTypes( + Class serviceType) { + ArrayList> knownServices = + KNOWN_SERVICES.stream() + .filter(knownServiceType -> knownServiceType.isAssignableFrom(serviceType)) + .collect(Collectors.toCollection(ArrayList::new)); + + knownServices.add(serviceType); + return knownServices; + } + + /** + * Builds an AIServiceProvider from the registered services and default names. + * + * @return The AIServiceProvider. + */ + public AIServiceProvider build() { + // Create a clone of the services and defaults Dictionaries to prevent further changes + // by the services provider. + Map, Map>> servicesClone = + cloneServices(services); + + Map defaultsClone = new HashMap<>(defaultIds); + + return new DefaultAIServiceProvider(servicesClone, defaultsClone); + } + + /** + * Creates a clone of the services as a Map. + * + * @param services The services Map. + * @return The clone. + */ + static Map, Map>> cloneServices( + Map, Map>> services) { + return Collections.unmodifiableMap( + services.entrySet().stream() + .reduce( + new HashMap<>(), + (a, b) -> { + a.put(b.getKey(), Collections.unmodifiableMap(b.getValue())); + return a; + }, + (a, b) -> { + a.putAll(b); + return a; + })); + } + + private boolean hasDefault(Class type) { + String defaultName = defaultIds.get(type); + return !Verify.isNullOrEmpty(defaultName); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceProvider.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceProvider.java new file mode 100644 index 0000000000..0c7727e90c --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/AIServiceProvider.java @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.services; + +public interface AIServiceProvider extends NamedServiceProvider {} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/DefaultAIServiceProvider.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/DefaultAIServiceProvider.java new file mode 100644 index 0000000000..4302f0dd09 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/DefaultAIServiceProvider.java @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.services; + +import java.util.Map; +import java.util.function.Supplier; + +/** Default implementation of {@link AIServiceProvider} */ +public class DefaultAIServiceProvider extends DefaultNamedServiceProvider + implements AIServiceProvider { + public DefaultAIServiceProvider( + Map, Map>> services, + Map, String> defaultIds) { + super(services, defaultIds); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/DefaultNamedServiceProvider.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/DefaultNamedServiceProvider.java new file mode 100644 index 0000000000..945752038f --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/DefaultNamedServiceProvider.java @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.services; + +import com.microsoft.semantickernel.Verify; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; +import javax.annotation.Nullable; + +/** Default implementation of {@link NamedServiceProvider} */ +public class DefaultNamedServiceProvider implements NamedServiceProvider { + + // A dictionary that maps a service type to a nested dictionary of names and service instances + // or factories + // private readonly Dictionary> _services = new(); + private final Map, Map>> services; + + // A dictionary that maps a service type to the name of the default service + private final Map, String> defaultIds; + + public DefaultNamedServiceProvider( + Map, Map>> services, + Map, String> defaultIds) { + this.services = AIServiceCollection.cloneServices(services); + this.defaultIds = new HashMap<>(defaultIds); + } + + /** + * Gets the service of the specified type and name, or null if not found. + * + * @param name The name of the service, or null for the default service. + * @param clazz The type of the service. + * @return The service instance, or null if not found. + */ + @Nullable + @Override + public U getService(@Nullable String name, Class clazz) { + // Return the service, casting or invoking the factory if needed + Supplier factory = this.getServiceFactory(name, clazz); + if (factory != null) { + return factory.get(); + } + + return null; + } + + /** + * Get the default service instance. + * + * @param clazz The type of the service. + * @return The service instance, or null if none. + */ + @Nullable + private String getDefaultServiceName(Class clazz) { + // Returns the name of the default service for the given type, or null if none + String name = this.defaultIds.get(clazz); + if (!Verify.isNullOrEmpty(name)) { + return name; + } + + return null; + } + + @Nullable + private Supplier getServiceFactory(@Nullable String name, Class clazz) { + // Get the nested dictionary for the service type + Map> namedServices = services.get(clazz); + + if (namedServices != null) { + Supplier serviceFactory = null; + + // If the name is not specified, try to load the default factory + name = name == null ? this.getDefaultServiceName(clazz) : name; + if (name != null) { + // Check if there is a service registered with the given name + serviceFactory = (Supplier) namedServices.get(name); + } + + return serviceFactory; + } + + return null; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/NamedServiceProvider.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/NamedServiceProvider.java new file mode 100644 index 0000000000..a7ec5b064f --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/services/NamedServiceProvider.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.services; + +import javax.annotation.Nullable; + +public interface NamedServiceProvider { + /** + * Gets the service of the specified type and name, or null if not found. + * + * @param name The name of the service, or null for the default service. + * @param clazz The type of the service. + * @return The service instance, or null if not found. + */ + @Nullable + public U getService(@Nullable String name, Class clazz); +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionNotFound.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionNotFound.java new file mode 100644 index 0000000000..cffc141718 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionNotFound.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class FunctionNotFound extends SKException { + + private final ErrorCodes errorCode; + + public FunctionNotFound(@Nonnull ErrorCodes errorCodes) { + this(errorCodes, null, null); + } + + public FunctionNotFound(@Nonnull ErrorCodes errorCodes, @Nullable String functionName) { + this(errorCodes, functionName, null); + } + + public FunctionNotFound( + @Nonnull ErrorCodes errorCodes, + @Nullable String functionName, + @Nullable Throwable cause) { + super(formatDefaultMessage(errorCodes.getMessage(), functionName), cause); + this.errorCode = errorCodes; + } + + public ErrorCodes getErrorCode() { + return errorCode; + } + + public enum ErrorCodes { + FUNCTION_NOT_FOUND("Function not found"); + + final String message; + + ErrorCodes(String message) { + this.message = message; + } + + String getMessage() { + return message; + } + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionView.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionView.java new file mode 100644 index 0000000000..f24bdecee3 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionView.java @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +import java.util.Collections; +import java.util.List; + +/** + * Class used to copy and export data from the skill collection. The data is mutable, but changes do + * not affect the skill collection. + */ +public class FunctionView { + + // Name of the function. The name is used by the skill collection and in prompt templates e.g. + // {{skillName.functionName}} + private final String name; + + /// Name of the skill containing the function. The name is used by the skill collection and in + // prompt templates e.g. {{skillName.functionName}} + private final String skillName; + + // Function description. The description is used in combination with embeddings when searching + // relevant functions. + private final String description; + + // Whether the delegate points to a semantic function + private final boolean isSemantic; + + // Whether the delegate is an asynchronous function + private final boolean isAsynchronous; + + // List of function parameters + private final List parameters; + + /** + * Create a function view. + * + * @param name Function name + * @param skillName Skill name, e.g. the function namespace + * @param description Function description + * @param parameters List of function parameters provided by the skill developer + * @param isSemantic Whether the function is a semantic one (or native is False) + * @param isAsynchronous Whether the function is async. Note: all semantic functions are async + */ + public FunctionView( + String name, + String skillName, + String description, + List parameters, + boolean isSemantic, + boolean isAsynchronous) { + this.name = name; + this.skillName = skillName; + this.description = description; + this.parameters = Collections.unmodifiableList(parameters); + this.isSemantic = isSemantic; + this.isAsynchronous = isAsynchronous; + } + + /** + * List of function parameters + * + * @return the list of function parameters + */ + public List getParameters() { + return parameters; + } + + public String getDescription() { + return description; + } + + public String getSkillName() { + return skillName; + } + + public String getName() { + return name; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/KernelSkillsSupplier.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/KernelSkillsSupplier.java new file mode 100644 index 0000000000..fa4805961d --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/KernelSkillsSupplier.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +import com.microsoft.semantickernel.Kernel; +import java.util.function.Supplier; + +public interface KernelSkillsSupplier extends Supplier { + + static KernelSkillsSupplier getInstance(Kernel kernel) { + return kernel::getSkills; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ParameterView.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ParameterView.java new file mode 100644 index 0000000000..5c7651692a --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ParameterView.java @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +/// +/// Class used to copy and export data from +/// +/// and +/// for planner and related scenarios. +/// +public class ParameterView { + private final String name; + private final String description; + private final String defaultValue; + + /// + /// Create a function parameter view, using information provided by the skill developer. + /// + /// Parameter name. The name must be alphanumeric (underscore is the only + // special char allowed). + /// Parameter description + /// Default parameter value, if not provided + public ParameterView(String name, String description, String defaultValue) { + // TODO + // Verify.ValidFunctionParamName(name); + + this.name = name; + this.description = description; + this.defaultValue = defaultValue; + } + + public ParameterView(String name) { + this(name, "", ""); + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getDefaultValue() { + return defaultValue; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlyFunctionCollection.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlyFunctionCollection.java new file mode 100644 index 0000000000..3574dc57b3 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlyFunctionCollection.java @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +import com.microsoft.semantickernel.orchestration.SKFunction; +import java.util.List; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +public interface ReadOnlyFunctionCollection { + + String getSkillName(); + + SKFunction getFunction(String functionName); + + /** + * Get function with the given SKFunction type argument. + * + * @param functionName the name of the function to retrieve + * @param clazz The class of the SKFunction parameter type + * @param SKFunction parameter type + * @return The given function + * @throws RuntimeException if the given entry is not of the expected type + */ + T getFunction(String functionName, @Nullable Class clazz); + + /** + * @return A clone of this collection + */ + @CheckReturnValue + ReadOnlyFunctionCollection copy(); + + /** + * @return An unmodifiable list of all functions + */ + List> getAll(); +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlySkillCollection.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlySkillCollection.java new file mode 100644 index 0000000000..b3318eb76c --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/ReadOnlySkillCollection.java @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.orchestration.SKFunction; +import java.util.Map; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +/** + * Skill collection interface. + * + *

This is read only + */ +public interface ReadOnlySkillCollection extends Buildable { + + String GlobalSkill = "_GLOBAL_FUNCTIONS_"; + + @CheckReturnValue + ReadOnlySkillCollection copy(); + + /* + ///

+ /// Add a native function to the collection + /// + /// Wrapped function delegate + /// Self instance + */ + + /** Get this collection as an unmodifiable map */ + Map asMap(); + + ReadOnlyFunctionCollection getAllFunctions(); + + /** Get function with name from the global scope */ + @Nullable + > T getFunction(String functionName, @Nullable Class functionType); + + @Nullable + > T getFunction( + String skillName, String funName, @Nullable Class functionClazz); + + @Nullable + ReadOnlyFunctionCollection getFunctions(String skillName); + + boolean hasFunction(String functionName); + + boolean hasFunction(String skillName, String functionName); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(Builder.class); + } + + interface Builder extends SemanticKernelBuilder {} +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/DefineSKFunction.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/DefineSKFunction.java new file mode 100644 index 0000000000..b6f9366623 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/DefineSKFunction.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Annotation that defines a method that can be invoked as a native function */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface DefineSKFunction { + String description() default ""; + + String name() default ""; + + String returnType() default "void"; + + String returnDescription() default ""; +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/SKFunctionInputAttribute.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/SKFunctionInputAttribute.java new file mode 100644 index 0000000000..47b238bbae --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/SKFunctionInputAttribute.java @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Annotates a parameter binding it to the "input" context variable */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface SKFunctionInputAttribute { + String description(); +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/SKFunctionParameters.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/SKFunctionParameters.java new file mode 100644 index 0000000000..95e5bcb961 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/skilldefinition/annotations/SKFunctionParameters.java @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Annotates a parameter to a native function */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface SKFunctionParameters { + + String NO_DEFAULT_VALUE = "SKFunctionParameters__NO_INPUT_PROVIDED"; + + String description() default ""; + + String name(); + + String defaultValue() default NO_DEFAULT_VALUE; + + /** + * If required is false, no value is set, and no default value is provided, null will be passed + * as this argument. + */ + boolean required() default true; + + Class type() default String.class; +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/PromptTemplateEngine.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/PromptTemplateEngine.java new file mode 100644 index 0000000000..77c8054ddd --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/PromptTemplateEngine.java @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine; + +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.templateengine.blocks.Block; +import java.util.List; +import reactor.core.publisher.Mono; + +/** Prompt template engine interface */ +public interface PromptTemplateEngine extends Buildable { + + /* + /// + /// Given a prompt template string, extract all the blocks (text, variables, function calls) + /// + /// Prompt template (see skprompt.txt files) + /// Whether to validate the blocks syntax, or just return the blocks found, which could contain invalid code + /// A list of all the blocks, ie the template tokenized in text, variables and function calls + IList ExtractBlocks( + string?templateText, + bool validate =true); + */ + + /** + * Given a prompt template, replace the variables with their values and execute the functions + * replacing their reference with the function result + * + * @param templateText Prompt template (see skprompt.txt files) + * @param context Access into the current kernel execution context + * @return The prompt template ready to be used for an AI request + */ + Mono renderAsync(String templateText, SKContext context); + + /** + * Given a prompt template string, extract all the blocks (text, variables, function calls) + * + * @param promptTemplate Prompt template (see skprompt.txt files) + * @return A list of all the blocks, ie the template tokenized in text, variables and function + * calls + */ + List extractBlocks(String promptTemplate); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(Builder.class); + } + + interface Builder extends SemanticKernelBuilder {} +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/blocks/Block.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/blocks/Block.java new file mode 100644 index 0000000000..b48410343e --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/blocks/Block.java @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +/** Base class for blocks parsed from a prompt template */ +public abstract class Block { + private final String content; + private final BlockTypes type; + + /** + * Base constructor + * + * @param content Block content + * @param type Block type + */ + public Block(String content, BlockTypes type) { + if (content == null) { + content = ""; + } + + this.content = content; + this.type = type; + } + + /** + * Get the block content + * + * @return Block content + */ + public String getContent() { + return content; + } + + /** + * Check if the block content is valid. + * + * @return True if the block content is valid + */ + public abstract boolean isValid(); + + /** + * Get the block type + * + * @return Block type + */ + public BlockTypes getType() { + return type; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/blocks/BlockTypes.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/blocks/BlockTypes.java new file mode 100644 index 0000000000..bb66bca30e --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/templateengine/blocks/BlockTypes.java @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +public enum BlockTypes { + /** Undefined block type */ + Undefined(0), + /** Text block type */ + Text(1), + /** Code block type */ + Code(2), + /** Variable block type */ + Variable(3), + /** Value block type */ + Value(4), + /** Function block type */ + FunctionId(5); + + BlockTypes(int i) {} +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionRequestSettings.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionRequestSettings.java new file mode 100644 index 0000000000..f243778cfa --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionRequestSettings.java @@ -0,0 +1,215 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.textcompletion; + +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nonnull; + +/** Settings for a text completion request */ +public class CompletionRequestSettings { + /** + * Temperature controls the randomness of the completion. The higher the temperature, the more + * random the completion + */ + private final double temperature; // { get; set; } = 0; + + /** + * TopP controls the diversity of the completion. The higher the TopP, the more diverse the + * completion. + */ + private final double topP; // { get; set; } = 0; + + /** + * Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + * in the text so far, increasing the model's likelihood to talk about new topics. + */ + private final double presencePenalty; // { get; set; } = 0; + + /** + * Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + * frequency in the text so far, decreasing the model's likelihood to repeat the same line + * verbatim. + */ + private final double frequencyPenalty; // { get; set; } = 0; + + /** The maximum number of tokens to generate in the completion. */ + private final int maxTokens; // { get; set; } = 256; + + /** Sequences where the completion will stop generating further tokens. */ + private final List stopSequences; // { get; set; } = Array.Empty(); + + /** + * The maximum number of completions to generate for each prompt. This is used by the + * CompletionService to generate multiple completions for a single prompt. + */ + private final int bestOf; + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and detect + * abuse + */ + private final String user; + + /** + * Create a new settings object with the given values. + * + * @param temperature Temperature controls the randomness of the completion. + * @param topP TopP controls the diversity of the completion. + * @param presencePenalty Number between -2.0 and 2.0. Positive values penalize new tokens based + * on whether they appear in the text so far, increasing the model's likelihood to talk + * about new topics. + * @param frequencyPenalty Number between -2.0 and 2.0. Positive values penalize new tokens + * based on their existing frequency in the text so far, decreasing the model's likelihood + * to repeat the same line verbatim. + * @param maxTokens The maximum number of tokens to generate in the completion. + */ + public CompletionRequestSettings( + double temperature, + double topP, + double presencePenalty, + double frequencyPenalty, + int maxTokens) { + this( + temperature, + topP, + presencePenalty, + frequencyPenalty, + maxTokens, + 1, + "", + Collections.emptyList()); + } + + /** + * Create a new settings object with the given values. + * + * @param temperature Temperature controls the randomness of the completion. + * @param topP TopP controls the diversity of the completion. + * @param presencePenalty Number between -2.0 and 2.0. Positive values penalize new tokens based + * on whether they appear in the text so far, increasing the model's likelihood to talk + * about new topics. + * @param frequencyPenalty Number between -2.0 and 2.0. Positive values penalize new tokens + * based on their existing frequency in the text so far, decreasing the model's likelihood + * to repeat the same line verbatim. + * @param maxTokens The maximum number of tokens to generate in the completion. + * @param bestOf The maximum number of completions to generate for each prompt. This is used by + * the CompletionService to generate multiple completions for a single prompt. + * @param user A unique identifier representing your end-user, which can help OpenAI to monitor + * and detect abuse + * @param stopSequences Sequences where the completion will stop generating further tokens. + */ + public CompletionRequestSettings( + double temperature, + double topP, + double presencePenalty, + double frequencyPenalty, + int maxTokens, + int bestOf, + String user, + List stopSequences) { + this.temperature = temperature; + this.topP = topP; + this.presencePenalty = presencePenalty; + this.frequencyPenalty = frequencyPenalty; + this.maxTokens = maxTokens; + this.bestOf = bestOf; + this.user = user; + this.stopSequences = new ArrayList<>(stopSequences); + } + + /** Create a new settings object with default values. */ + public CompletionRequestSettings() { + this(0, 0, 0, 0, 256, 1, "", new ArrayList<>()); + } + + public CompletionRequestSettings(@Nonnull CompletionRequestSettings requestSettings) { + this( + requestSettings.getTemperature(), + requestSettings.getTopP(), + requestSettings.getPresencePenalty(), + requestSettings.getFrequencyPenalty(), + requestSettings.getMaxTokens(), + requestSettings.getBestOf(), + requestSettings.getUser(), + requestSettings.getStopSequences()); + } + + /** + * Create a new settings object with the values from another settings object. + * + * @param config The config to copy values from + */ + public static CompletionRequestSettings fromCompletionConfig( + PromptTemplateConfig.CompletionConfig config) { + return new CompletionRequestSettings( + config.getTemperature(), + config.getTopP(), + config.getPresencePenalty(), + config.getFrequencyPenalty(), + config.getMaxTokens(), + config.getBestOf(), + config.getUser(), + config.getStopSequences()); + } + + /** + * Temperature controls the randomness of the completion. The higher the temperature, the more + * random the completion + */ + public double getTemperature() { + return temperature; + } + + /** + * TopP controls the diversity of the completion. The higher the TopP, the more diverse the + * completion. + */ + public double getTopP() { + return topP; + } + + /** + * Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + * in the text so far, increasing the model's likelihood to talk about new topics. + */ + public double getPresencePenalty() { + return presencePenalty; + } + + /** + * Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + * frequency in the text so far, decreasing the model's likelihood to repeat the same line + * verbatim. + */ + public double getFrequencyPenalty() { + return frequencyPenalty; + } + + /** The maximum number of tokens to generate in the completion. */ + public int getMaxTokens() { + return maxTokens; + } + + /** Sequences where the completion will stop generating further tokens. */ + public List getStopSequences() { + return Collections.unmodifiableList(stopSequences); + } + + /** + * The maximum number of completions to generate for each prompt. This is used by the + * CompletionService to generate multiple completions for a single prompt. + */ + public Integer getBestOf() { + return bestOf; + } + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and detect + * abuse + */ + public String getUser() { + return user; + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKFunction.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKFunction.java new file mode 100644 index 0000000000..08be7ae143 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionSKFunction.java @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.textcompletion; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig; +import java.util.List; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/** Semantic function for text completion */ +public interface CompletionSKFunction extends SKFunction, Buildable { + + /** + * Method to aggregate partitioned results of a semantic function. + * + * @param partitionedInput Input to aggregate + * @param context Semantic Kernel context + * @return Aggregated results + */ + Mono aggregatePartitionedResultsAsync( + List partitionedInput, @Nullable SKContext context); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(CompletionSKFunction.Builder.class); + } + + /** Builder for completion functions */ + interface Builder extends SemanticKernelBuilder { + + Builder withKernel(Kernel kernel); + + Builder withPromptTemplate(String promptTemplate); + + Builder withPromptTemplateConfig(PromptTemplateConfig config); + + Builder withCompletionConfig(PromptTemplateConfig.CompletionConfig completionConfig); + + Builder withSemanticFunctionConfig(SemanticFunctionConfig functionConfig); + + Builder withSkillName(@Nullable String skillName); + + Builder withFunctionName(@Nullable String functionName); + + Builder withDescription(String description); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionType.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionType.java new file mode 100644 index 0000000000..0eb2645a85 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/CompletionType.java @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.textcompletion; + +/** Defines if an AI service supports streaming or non-streaming completion requests. */ +public enum CompletionType { + STREAMING, + NON_STREAMING +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/TextCompletion.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/TextCompletion.java new file mode 100644 index 0000000000..b02666d449 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/textcompletion/TextCompletion.java @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.textcompletion; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.builders.Buildable; +import com.microsoft.semantickernel.builders.BuildersSingleton; +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.services.AIService; +import java.util.List; +import javax.annotation.Nonnull; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** Interface for text completion services */ +public interface TextCompletion extends AIService, Buildable { + + /** + * Creates a completion for the prompt and settings. + * + * @param text The prompt to complete. + * @param requestSettings Request settings for the completion API + * @return Text generated by the remote model + */ + Mono> completeAsync( + @Nonnull String text, @Nonnull CompletionRequestSettings requestSettings); + + /** + * Creates a completion for the prompt and settings. + * + * @param text The prompt to complete. + * @param requestSettings Request settings for the completion API + * @return Text generated by the remote model + */ + Flux completeStreamAsync( + @Nonnull String text, @Nonnull CompletionRequestSettings requestSettings); + + static Builder builder() { + return BuildersSingleton.INST.getInstance(Builder.class); + } + + /** + * Returns the default completion type for this service. This will be the type of request used + * (streaming or non-streaming) when calls to this service are made. Defaults to {@link + * CompletionType#STREAMING}. + * + * @return The default completion type for this service. + */ + CompletionType defaultCompletionType(); + + interface Builder extends SemanticKernelBuilder { + + Builder withOpenAIClient(OpenAIAsyncClient client); + + Builder withModelId(String modelId); + + /** + * Sets the default completion type for this service. This will be the type of request used + * (streaming or non-streaming) when calls to this service are made. Defaults to {@link + * CompletionType#STREAMING}. + */ + Builder withDefaultCompletionType(CompletionType completionType); + } +} diff --git a/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/EmbeddedResourceLoader.java b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/EmbeddedResourceLoader.java new file mode 100644 index 0000000000..b54b80df29 --- /dev/null +++ b/java/semantickernel-api/src/main/java/com/microsoft/semantickernel/util/EmbeddedResourceLoader.java @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +public class EmbeddedResourceLoader { + + public enum ResourceLocation { + CLASSPATH, + FILESYSTEM, + CLASSPATH_ROOT + } + + /** + * Loads a file to a string from the classpath using getResourceAsStream + * + * @param fileName Filename to read + * @return File content + * @throws FileNotFoundException Error in case the file doesn't exist + */ + public static String readFile(String fileName, Class clazz) throws FileNotFoundException { + return readFile(fileName, clazz, ResourceLocation.CLASSPATH); + } + + /** + * Loads a file to a string from the classpath, classpath root or filesystem + * + * @param fileName Filename to read + * @return File content + * @throws FileNotFoundException Error in case the file doesn't exist + */ + public static String readFile(String fileName, Class clazz, ResourceLocation... locations) + throws FileNotFoundException { + + List locationsList = + Arrays.stream(locations).collect(Collectors.toList()); + + Optional fileContents = + locationsList.stream() + .map( + type -> { + switch (type) { + case CLASSPATH: + try (InputStream inputStream = + clazz.getResourceAsStream(fileName)) { + return readInputStream(fileName, inputStream); + } catch (Exception e) { + // IGNORE + } + break; + case CLASSPATH_ROOT: + try (InputStream inputStream = + Thread.currentThread() + .getContextClassLoader() + .getResourceAsStream(fileName)) { + return readInputStream(fileName, inputStream); + } catch (IOException e) { + // IGNORE + } + break; + case FILESYSTEM: + File file = new File(fileName); + if (file.exists()) { + try (InputStream inputStream = + Files.newInputStream(file.toPath())) { + return readInputStream(fileName, inputStream); + } catch (IOException e) { + // IGNORE + } + } + break; + default: + } + return null; + }) + .filter(Objects::nonNull) + .findFirst(); + + if (fileContents.isPresent()) { + return fileContents.get(); + } + + throw new FileNotFoundException("Could not find file " + fileName); + } + + private static String readInputStream(String fileName, InputStream inputStream) + throws FileNotFoundException { + if (inputStream == null) { + throw new FileNotFoundException("File not found: " + fileName); + } + + return new BufferedReader( + new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8)) + .lines() + .collect(Collectors.joining("\n")); + } +} diff --git a/java/semantickernel-bom/pom.xml b/java/semantickernel-bom/pom.xml new file mode 100644 index 0000000000..4803fc433f --- /dev/null +++ b/java/semantickernel-bom/pom.xml @@ -0,0 +1,208 @@ + + + + 4.0.0 + + com.microsoft.semantic-kernel + semantickernel-bom + 0.2.10-alpha-SNAPSHOT + pom + + Semantic Kernel Java BOM + Bill of Materials for all Semantic Kernel (Java) modules + https://www.github.com/microsoft/semantic-kernel + + + 2.15.2 + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.3.0 + + + enforce-maven + + enforce + + + + + 3.9.3 + + + + + + + + + + + + + com.microsoft.semantic-kernel + semantickernel-api + ${project.version} + + + com.microsoft.semantic-kernel + semantickernel-core + ${project.version} + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + ${project.version} + + + + com.microsoft.semantic-kernel + semantickernel-planners + ${project.version} + + + + com.microsoft.semantic-kernel + semantickernel-plugin-core + ${project.version} + + + com.microsoft.semantic-kernel + semantickernel-gpt3-tokenizer + ${project.version} + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-jdbc + ${project.version} + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-sqlite + ${project.version} + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-postgresql + ${project.version} + + + com.microsoft.semantic-kernel + semantickernel-connectors-memory-azurecognitivesearch + ${project.version} + + + com.microsoft.semantic-kernel + semantickernel-settings-loader + ${project.version} + + + + com.azure + azure-ai-openai + 1.0.0-beta.5 + + + org.slf4j + slf4j-api + 2.0.7 + + + com.fasterxml.jackson.core + jackson-annotations + ${com.fasterxml.jackson.core.version} + + + com.fasterxml.jackson.core + jackson-databind + ${com.fasterxml.jackson.core.version} + runtime + + + com.fasterxml.jackson.core + jackson-core + ${com.fasterxml.jackson.core.version} + runtime + + + io.projectreactor + reactor-core + 3.5.8 + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.azure + azure-core-http-netty + 1.13.8 + runtime + + + com.azure + azure-search-documents + 11.6.0-beta.9 + + + jakarta.inject + jakarta.inject-api + 2.0.1.MR + + + + org.xerial + sqlite-jdbc + 3.42.0.0 + + + + org.postgresql + postgresql + 42.6.0 + + + + + + + release + + + + ${releaseRepoId} + + ${releaseRepoUrl} + ${releaseRepoName} + + + + + + + + microsoft + Microsoft + + + + + + MIT License + https://opensource.org/licenses/MIT + repo + + + + + https://github.com/microsoft/semantic-kernel + scm:git:https://github.com/microsoft/semantic-kernel.git + scm:git:https://github.com/microsoft/semantic-kernel.git + java-0.2.9-alpha + + diff --git a/java/semantickernel-core/pom.xml b/java/semantickernel-core/pom.xml new file mode 100644 index 0000000000..dd32da1ec1 --- /dev/null +++ b/java/semantickernel-core/pom.xml @@ -0,0 +1,95 @@ + + + + 4.0.0 + + + com.microsoft.semantic-kernel + semantickernel-parent + 0.2.10-alpha-SNAPSHOT + ../pom.xml + + + semantickernel-core + jar + Semantic Kernel Core + Implementation of the Semantic Kernel + + + org.slf4j + slf4j-api + + + com.azure + azure-core-http-netty + + + io.projectreactor + reactor-core + + + com.azure + azure-ai-openai + compile + + + com.fasterxml.jackson.core + jackson-databind + compile + + + org.apache.logging.log4j + log4j-api + test + + + org.apache.logging.log4j + log4j-core + test + + + org.apache.logging.log4j + log4j-slf4j2-impl + test + + + org.mockito + mockito-core + test + + + org.junit.jupiter + junit-jupiter + test + + + org.junit.jupiter + junit-jupiter-api + test + + + com.microsoft.semantic-kernel + semantickernel-api + + + com.microsoft.semantic-kernel + semantickernel-connectors-ai-openai + test + + + com.microsoft.semantic-kernel + semantickernel-plugin-core + test + + + com.microsoft.semantic-kernel + semantickernel-planners + test + + + + jakarta.inject + jakarta.inject-api + + + \ No newline at end of file diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/DefaultKernel.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/DefaultKernel.java new file mode 100644 index 0000000000..7f19344c31 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/DefaultKernel.java @@ -0,0 +1,511 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.microsoft.semantickernel.ai.AIException; +import com.microsoft.semantickernel.ai.embeddings.TextEmbeddingGeneration; +import com.microsoft.semantickernel.coreskills.SkillImporter; +import com.microsoft.semantickernel.exceptions.SkillsNotFoundException; +import com.microsoft.semantickernel.exceptions.SkillsNotFoundException.ErrorCodes; +import com.microsoft.semantickernel.extensions.KernelExtensions; +import com.microsoft.semantickernel.memory.MemoryConfiguration; +import com.microsoft.semantickernel.memory.MemoryStore; +import com.microsoft.semantickernel.memory.NullMemory; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.orchestration.RegistrableSkFunction; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig; +import com.microsoft.semantickernel.services.AIService; +import com.microsoft.semantickernel.services.AIServiceCollection; +import com.microsoft.semantickernel.services.AIServiceProvider; +import com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection; +import com.microsoft.semantickernel.skilldefinition.FunctionNotFound; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.templateengine.DefaultPromptTemplateEngine; +import com.microsoft.semantickernel.templateengine.PromptTemplateEngine; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import jakarta.inject.Inject; +import java.util.Arrays; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +public class DefaultKernel implements Kernel { + + private final KernelConfig kernelConfig; + private final DefaultSkillCollection defaultSkillCollection; + private final PromptTemplateEngine promptTemplateEngine; + private final AIServiceProvider aiServiceProvider; + private SemanticTextMemory memory; + + @Inject + public DefaultKernel( + KernelConfig kernelConfig, + PromptTemplateEngine promptTemplateEngine, + @Nullable SemanticTextMemory memoryStore, + AIServiceProvider aiServiceProvider) { + if (kernelConfig == null) { + throw new IllegalArgumentException(); + } + + this.kernelConfig = kernelConfig; + this.aiServiceProvider = aiServiceProvider; + this.promptTemplateEngine = promptTemplateEngine; + this.defaultSkillCollection = new DefaultSkillCollection(); + + if (memoryStore != null) { + this.memory = memoryStore.copy(); + } else { + this.memory = new NullMemory(); + } + } + + @Override + public T getService(String serviceId, Class clazz) { + + T service = aiServiceProvider.getService(serviceId, clazz); + + if (service == null) { + throw new KernelException( + KernelException.ErrorCodes.SERVICE_NOT_FOUND, + "Service of type " + + clazz.getName() + + " and name " + + serviceId + + " not registered"); + } else { + return service; + } + } + + @Override + public KernelConfig getConfig() { + return kernelConfig; + } + + @Override + public > + FunctionType registerSemanticFunction(FunctionType func) { + if (!(func instanceof RegistrableSkFunction)) { + throw new RuntimeException("This function does not implement RegistrableSkFunction"); + } + ((RegistrableSkFunction) func).registerOnKernel(this); + defaultSkillCollection.addSemanticFunction(func); + return func; + } + + @Override + public SKFunction getFunction(String skill, String function) { + return defaultSkillCollection.getFunction(skill, function, null); + } + + @Override + public CompletionSKFunction registerSemanticFunction( + String skillName, String functionName, SemanticFunctionConfig functionConfig) { + // Future-proofing the name not to contain special chars + // Verify.ValidSkillName(skillName); + // Verify.ValidFunctionName(functionName); + + return SKBuilders.completionFunctions() + .withSemanticFunctionConfig(functionConfig) + .withFunctionName(functionName) + .withSkillName(skillName) + .withKernel(this) + .build(); + } + + /// + /// Import a set of functions from the given skill. The functions must have the `SKFunction` + // attribute. + /// Once these functions are imported, the prompt templates can use functions to import content + // at runtime. + /// + /// Instance of a class containing functions + /// Name of the skill for skill collection and prompt templates. If the + // value is empty functions are registered in the global namespace. + /// A list of all the semantic functions found in the directory, indexed by function + // name. + @Override + public ReadOnlyFunctionCollection importSkill( + String skillName, Map skills) + throws SkillsNotFoundException { + skills.entrySet().stream() + .map( + (entry) -> { + return SKBuilders.completionFunctions() + .withKernel(this) + .withSkillName(skillName) + .withFunctionName(entry.getKey()) + .withSemanticFunctionConfig(entry.getValue()) + .build(); + }) + .forEach(this::registerSemanticFunction); + + ReadOnlyFunctionCollection collection = getSkill(skillName); + if (collection == null) { + throw new SkillsNotFoundException(ErrorCodes.SKILLS_NOT_FOUND); + } + return collection; + } + + @Override + public ReadOnlyFunctionCollection importSkill( + Object skillInstance, @Nullable String skillName) { + if (skillInstance instanceof String) { + throw new KernelException( + KernelException.ErrorCodes.FUNCTION_NOT_AVAILABLE, + "Called importSkill with a string argument, it is likely the intention was to" + + " call importSkillFromDirectory"); + } + + if (skillName == null || skillName.isEmpty()) { + skillName = ReadOnlySkillCollection.GlobalSkill; + } + + // skill = new Dictionary(StringComparer.OrdinalIgnoreCase); + ReadOnlyFunctionCollection functions = + SkillImporter.importSkill(skillInstance, skillName, () -> defaultSkillCollection); + + DefaultSkillCollection newSkills = + functions.getAll().stream() + .reduce( + new DefaultSkillCollection(), + DefaultSkillCollection::addNativeFunction, + DefaultSkillCollection::merge); + + this.defaultSkillCollection.merge(newSkills); + + return functions; + } + + @Override + public ReadOnlySkillCollection getSkills() { + return defaultSkillCollection; + } + + @Override + public CompletionSKFunction.Builder getSemanticFunctionBuilder() { + return SKBuilders.completionFunctions().withKernel(this); + } + + @Override + public ReadOnlyFunctionCollection getSkill(String skillName) throws FunctionNotFound { + ReadOnlyFunctionCollection functions = this.defaultSkillCollection.getFunctions(skillName); + if (functions == null) { + throw new FunctionNotFound(FunctionNotFound.ErrorCodes.FUNCTION_NOT_FOUND, skillName); + } + + return functions; + } + + @Override + public ReadOnlyFunctionCollection importSkillFromDirectory( + String skillName, String parentDirectory, String skillDirectoryName) { + Map skills = + KernelExtensions.importSemanticSkillFromDirectory( + parentDirectory, skillDirectoryName, promptTemplateEngine); + return importSkill(skillName, skills); + } + + @Override + public void importSkillsFromDirectory(String parentDirectory, String... skillNames) { + Arrays.stream(skillNames) + .forEach( + skill -> { + importSkillFromDirectory(skill, parentDirectory, skill); + }); + } + + @Override + public ReadOnlyFunctionCollection importSkillFromDirectory( + String skillName, String parentDirectory) { + return importSkillFromDirectory(skillName, parentDirectory, skillName); + } + + @Override + public ReadOnlyFunctionCollection importSkillFromResources( + String pluginDirectory, String skillName, String functionName) { + return importSkillFromResources(pluginDirectory, skillName, functionName, null); + } + + @Override + public ReadOnlyFunctionCollection importSkillFromResources( + String pluginDirectory, String skillName, String functionName, @Nullable Class clazz) throws KernelException { + Map skills = + KernelExtensions.importSemanticSkillFromResourcesDirectory( + pluginDirectory, skillName, functionName, clazz, promptTemplateEngine); + return importSkill(skillName, skills); + } + + @Override + public PromptTemplateEngine getPromptTemplateEngine() { + return promptTemplateEngine; + } + + @Override + public SemanticTextMemory getMemory() { + return memory; + } + + public void registerMemory(@Nonnull SemanticTextMemory memory) { + this.memory = memory; + } + + @Override + public Mono runAsync(SKFunction... pipeline) { + return runAsync(SKBuilders.variables().build(), pipeline); + } + + @Override + public Mono runAsync(String input, SKFunction... pipeline) { + return runAsync(SKBuilders.variables().withInput(input).build(), pipeline); + } + + @Override + public Mono runAsync(ContextVariables variables, SKFunction... pipeline) { + if (pipeline == null || pipeline.length == 0) { + throw new SKException("No parameters provided to pipeline"); + } + // TODO: The SemanticTextMemory can be null, but there should be a way to provide it. + // Not sure registerMemory is the right way. + Mono pipelineBuilder = + Mono.just( + SKBuilders.context() + .withVariables(variables) + .withSkills(getSkills()) + .build()); + + for (SKFunction f : Arrays.asList(pipeline)) { + pipelineBuilder = + pipelineBuilder + .switchIfEmpty( + Mono.fromCallable( + () -> { + // Previous pipeline did not produce a result + return SKBuilders.context() + .withVariables(variables) + .withSkills(getSkills()) + .build(); + })) + .flatMap( + newContext -> { + SKContext context = + SKBuilders.context() + .withVariables(newContext.getVariables()) + .withMemory(newContext.getSemanticMemory()) + .withSkills(newContext.getSkills()) + .build(); + return f.invokeAsync(context, null); + }); + } + + return pipelineBuilder; + } + + public static class Builder implements Kernel.Builder { + @Nullable private KernelConfig config = null; + @Nullable private PromptTemplateEngine promptTemplateEngine = null; + @Nullable private final AIServiceCollection aiServices = new AIServiceCollection(); + private Supplier memoryFactory = NullMemory::new; + private Supplier memoryStorageFactory = null; + + /** + * Set the kernel configuration + * + * @param kernelConfig Kernel configuration + * @return Builder + */ + public Kernel.Builder withConfiguration(KernelConfig kernelConfig) { + this.config = kernelConfig; + return this; + } + + /** + * Add prompt template engine to the kernel to be built. + * + * @param promptTemplateEngine Prompt template engine to add. + * @return Updated kernel builder including the prompt template engine. + */ + public Kernel.Builder withPromptTemplateEngine(PromptTemplateEngine promptTemplateEngine) { + Verify.notNull(promptTemplateEngine); + this.promptTemplateEngine = promptTemplateEngine; + return this; + } + + /** + * Add memory storage to the kernel to be built. + * + * @param storage Storage to add. + * @return Updated kernel builder including the memory storage. + */ + public Kernel.Builder withMemoryStorage(MemoryStore storage) { + Verify.notNull(storage); + this.memoryStorageFactory = () -> storage; + return this; + } + + /** + * Add memory storage factory to the kernel. + * + * @param factory The storage factory. + * @return Updated kernel builder including the memory storage. + */ + public Kernel.Builder withMemoryStorage(Supplier factory) { + Verify.notNull(factory); + this.memoryStorageFactory = factory::get; + return this; + } + + /** + * Adds an instance to the services collection + * + * @param instance The instance. + * @return The builder. + */ + public Kernel.Builder withDefaultAIService(T instance) { + Class clazz = (Class) instance.getClass(); + this.aiServices.setService(instance, clazz); + return this; + } + + /** + * Adds an instance to the services collection + * + * @param instance The instance. + * @param clazz The class of the instance. + * @return The builder. + */ + public Kernel.Builder withDefaultAIService( + T instance, Class clazz) { + this.aiServices.setService(instance, clazz); + return this; + } + + /** + * Adds a factory method to the services collection + * + * @param factory The factory method that creates the AI service instances of type T. + * @param clazz The class of the instance. + */ + public Kernel.Builder withDefaultAIService( + Supplier factory, Class clazz) { + this.aiServices.setService(factory, clazz); + return this; + } + + /** + * Adds an instance to the services collection + * + * @param serviceId The service ID + * @param instance The instance. + * @param setAsDefault Optional: set as the default AI service for type T + * @param clazz The class of the instance. + */ + public Kernel.Builder withAIService( + @Nullable String serviceId, T instance, boolean setAsDefault, Class clazz) { + this.aiServices.setService(serviceId, instance, setAsDefault, clazz); + + return this; + } + + /** + * Adds a factory method to the services collection + * + * @param serviceId The service ID + * @param factory The factory method that creates the AI service instances of type T. + * @param setAsDefault Optional: set as the default AI service for type T + * @param clazz The class of the instance. + */ + public Kernel.Builder withAIServiceFactory( + @Nullable String serviceId, + Function factory, + boolean setAsDefault, + Class clazz) { + this.aiServices.setService( + serviceId, (Supplier) () -> factory.apply(this.config), setAsDefault, clazz); + return this; + } + + /** + * Add a semantic text memory entity to the kernel to be built. + * + * @param memory Semantic text memory entity to add. + * @return Updated kernel builder including the semantic text memory entity. + */ + public Kernel.Builder withMemory(SemanticTextMemory memory) { + Verify.notNull(memory); + this.memoryFactory = () -> memory; + return this; + } + + /** + * Add memory storage and an embedding generator to the kernel to be built. + * + * @param storage Storage to add. + * @param embeddingGenerator Embedding generator to add. + * @return Updated kernel builder including the memory storage and embedding generator. + */ + public Kernel.Builder withMemoryStorageAndTextEmbeddingGeneration( + MemoryStore storage, TextEmbeddingGeneration embeddingGenerator) { + Verify.notNull(storage); + Verify.notNull(embeddingGenerator); + this.memoryFactory = + () -> + SKBuilders.semanticTextMemory() + .withEmbeddingGenerator(embeddingGenerator) + .withStorage(storage) + .build(); + return this; + } + + /** + * Build the kernel + * + * @return Kernel + */ + public Kernel build() { + if (config == null) { + config = SKBuilders.kernelConfig().build(); + } + + return build( + config, + promptTemplateEngine, + memoryFactory.get(), + memoryStorageFactory == null ? null : memoryStorageFactory.get(), + aiServices.build()); + } + + private Kernel build( + KernelConfig kernelConfig, + @Nullable PromptTemplateEngine promptTemplateEngine, + @Nullable SemanticTextMemory memory, + @Nullable MemoryStore memoryStore, + @Nullable AIServiceProvider aiServiceProvider) { + if (promptTemplateEngine == null) { + promptTemplateEngine = new DefaultPromptTemplateEngine(); + } + + if (kernelConfig == null) { + throw new AIException( + AIException.ErrorCodes.INVALID_CONFIGURATION, + "It is required to set a kernelConfig to build a kernel"); + } + + DefaultKernel kernel = + new DefaultKernel( + kernelConfig, promptTemplateEngine, memory, aiServiceProvider); + + if (memoryStore != null) { + MemoryConfiguration.useMemory(kernel, memoryStore, null); + } + + return kernel; + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/SkFunctionBuilders.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/SkFunctionBuilders.java new file mode 100644 index 0000000000..3969ffd306 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/SkFunctionBuilders.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +/** Provides various builders for completion functions */ +public class SkFunctionBuilders { + public SkFunctionBuilders() {} +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/coreskills/SkillImporter.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/coreskills/SkillImporter.java new file mode 100644 index 0000000000..3678e8b48f --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/coreskills/SkillImporter.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.coreskills; + +import com.microsoft.semantickernel.orchestration.NativeSKFunction; +import com.microsoft.semantickernel.skilldefinition.FunctionCollection; +import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class SkillImporter { + + public static FunctionCollection importSkill( + Object skillInstance, String skillName, KernelSkillsSupplier skillCollectionSupplier) { + List methods = + Arrays.stream(skillInstance.getClass().getMethods()) + .filter(method -> method.isAnnotationPresent(DefineSKFunction.class)) + .map( + method -> { + return NativeSKFunction.fromNativeMethod( + method, + skillInstance, + skillName, + skillCollectionSupplier); + }) + .collect(Collectors.toList()); + + return new FunctionCollection(skillName, methods); + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/DefaultSemanticTextMemory.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/DefaultSemanticTextMemory.java new file mode 100644 index 0000000000..3002128416 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/DefaultSemanticTextMemory.java @@ -0,0 +1,208 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; + +/// +/// Implementation of ./>. +/// +public class DefaultSemanticTextMemory implements SemanticTextMemory { + + @Nonnull private final EmbeddingGeneration _embeddingGenerator; + @Nonnull private /*final*/ MemoryStore _storage; + + public DefaultSemanticTextMemory( + @Nonnull MemoryStore storage, @Nonnull EmbeddingGeneration embeddingGenerator) { + this._embeddingGenerator = embeddingGenerator; + // TODO: this assignment raises EI_EXPOSE_REP2 in spotbugs (filtered out for now) + this._storage = storage; + } + + @Override + public SemanticTextMemory copy() { + // TODO: this is a shallow copy. Should it be a deep copy? + return new DefaultSemanticTextMemory(this._storage, this._embeddingGenerator); + } + + @Override + public Mono saveInformationAsync( + @Nonnull String collection, + @Nonnull String text, + @Nonnull String id, + @Nullable String description, + @Nullable String additionalMetadata) { + + Mono embedAndSave = + _embeddingGenerator + .generateEmbeddingsAsync(Collections.singletonList(text)) + .flatMap( + embeddings -> { + if (embeddings.isEmpty()) { + return Mono.empty(); + } + MemoryRecordMetadata data = + new MemoryRecordMetadata( + true, + id, + text, + description, + "", + additionalMetadata); + MemoryRecord memoryRecord = + new MemoryRecord( + data, embeddings.iterator().next(), id, null); + + return _storage.upsertAsync(collection, memoryRecord) + .onErrorResume( + e -> { + return _storage.createCollectionAsync( + collection) + .then( + _storage.upsertAsync( + collection, + memoryRecord)); + }); + }); + + return _storage.getAsync(collection, id, false) + .filter(memoryRecord -> memoryRecord.getMetadata().getText().equals(text)) + .map(record -> record.getMetadata().getId()) + .switchIfEmpty(embedAndSave); + } + + public Mono getAsync(String collection, String key, boolean withEmbedding) { + return _storage.getAsync(collection, key, withEmbedding) + .map(record -> new MemoryQueryResult(record.getMetadata(), 1d)); + } + + @Override + public Mono removeAsync(@Nonnull String collection, @Nonnull String key) { + return _storage.removeAsync(collection, key); + } + + private static final Function< + Collection>, Mono>> + transformMatchesToResults = + records -> { + if (records.isEmpty()) { + return Mono.empty(); + } + return Mono.just( + records.stream() + .map( + record -> { + Tuple2 tuple = record; + MemoryRecord memoryRecord = tuple.getT1(); + Number relevanceScore = tuple.getT2(); + return new MemoryQueryResult( + memoryRecord.getMetadata(), + relevanceScore.doubleValue()); + }) + .collect(Collectors.toList())); + }; + + @Override + public Mono> searchAsync( + @Nonnull String collection, + @Nonnull String query, + int limit, + float minRelevanceScore, + boolean withEmbeddings) { + + // TODO: break this up into smaller methods + return _embeddingGenerator + .generateEmbeddingsAsync(Collections.singletonList(query)) + .flatMap( + embeddings -> { + if (embeddings.isEmpty()) { + return Mono.empty(); + } + return _storage.getNearestMatchesAsync( + collection, + embeddings.iterator().next(), + limit, + minRelevanceScore, + withEmbeddings) + .flatMap(transformMatchesToResults); + }); + } + + @Override + public Mono> getCollectionsAsync() { + return _storage.getCollectionsAsync(); + } + + @Override + public Mono saveReferenceAsync( + @Nonnull String collection, + @Nonnull String text, + @Nonnull String externalId, + @Nonnull String externalSourceName, + @Nullable String description, + @Nullable String additionalMetadata) { + + return this._storage + .doesCollectionExistAsync(collection) + .map( + exists -> { + if (!exists) { + return this._storage.createCollectionAsync(collection); + } + return Mono.empty(); + }) + .then( + this._embeddingGenerator.generateEmbeddingsAsync( + Collections.singletonList(text))) + .map( + embeddings -> + MemoryRecord.referenceRecord( + externalId, + externalSourceName, + description, + (Embedding) embeddings.iterator().next(), + additionalMetadata, + null, + null)) + .flatMap(record -> this._storage.upsertAsync(collection, record)); + } + + public static class Builder implements SemanticTextMemory.Builder { + + @Nullable MemoryStore storage = null; + @Nullable EmbeddingGeneration embeddingGenerator = null; + + @Override + public Builder withStorage(@Nonnull MemoryStore storage) { + this.storage = storage; + return this; + } + + @Override + public Builder withEmbeddingGenerator( + @Nonnull EmbeddingGeneration embeddingGenerator) { + this.embeddingGenerator = embeddingGenerator; + return this; + } + + @Override + public SemanticTextMemory build() { + if (storage == null) { + throw new IllegalStateException("Storage must be set"); + } + if (embeddingGenerator == null) { + throw new IllegalStateException("Embedding generator must be set"); + } + return new DefaultSemanticTextMemory(storage, embeddingGenerator); + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/MemoryConfiguration.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/MemoryConfiguration.java new file mode 100644 index 0000000000..367fb2f273 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/MemoryConfiguration.java @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import com.microsoft.semantickernel.DefaultKernel; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/// +/// Kernel extension to configure the semantic memory with custom settings +/// +public class MemoryConfiguration { + /// + /// Set the semantic memory to use the given memory storage and embeddings service. + /// + /// Kernel instance + /// Memory storage + /// Kernel service id for embedding generation + + /** + * Set the semantic memory to use the given memory storage and embeddings service. + * + * @param kernel {@link Kernel} instance + * @param storage {@link MemoryStore} instance + * @param embeddingsServiceId Kernel service id for embedding generation, can be {@code null} + * @throws NullPointerException if {@code kernel} or {@code storage} is {@code null} + * @throws com.microsoft.semantickernel.KernelException if there is an error getting the + * embedding generation service + */ + public static void useMemory( + @Nonnull DefaultKernel kernel, + @Nonnull MemoryStore storage, + @Nullable String embeddingsServiceId) { + Objects.requireNonNull(kernel); + Objects.requireNonNull(storage); + + @SuppressWarnings("unchecked") + EmbeddingGeneration embeddingGenerator = + (EmbeddingGeneration) + kernel.getService(embeddingsServiceId, EmbeddingGeneration.class); + + useMemory(kernel, embeddingGenerator, storage); + } + + /// + /// Set the semantic memory to use the given memory storage and embedding generator. + /// + /// Kernel instance + /// Embedding generator + /// Memory storage + /** + * Set the semantic memory to use the given memory storage and embeddings service. + * + * @param kernel {@link Kernel} instance + * @param embeddingGenerator {@link EmbeddingGeneration} instance + * @param storage {@link MemoryStore} instance + * @throws NullPointerException if {@code kernel}, {@code embeddingGenerator}, or {@code + * storage} is {@code null} + */ + public static void useMemory( + @Nonnull DefaultKernel kernel, + EmbeddingGeneration embeddingGenerator, + MemoryStore storage) { + Objects.requireNonNull(kernel); + Objects.requireNonNull(embeddingGenerator); + Objects.requireNonNull(storage); + + kernel.registerMemory(new DefaultSemanticTextMemory(storage, embeddingGenerator)); + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/VolatileMemoryStore.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/VolatileMemoryStore.java new file mode 100644 index 0000000000..2f04deec37 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/memory/VolatileMemoryStore.java @@ -0,0 +1,289 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; +import reactor.util.function.Tuples; + +/** A simple volatile memory embeddings store. */ +public class VolatileMemoryStore implements MemoryStore { + + private final Map> _store = new ConcurrentHashMap<>(); + + /** Constructs a new {@link VolatileMemoryStore} object. */ + public VolatileMemoryStore() {} + + @Override + public Mono createCollectionAsync(@Nonnull String collectionName) { + Objects.requireNonNull(collectionName); + return Mono.fromRunnable( + () -> this._store.putIfAbsent(collectionName, new ConcurrentHashMap<>())); + } + + @Override + public Mono doesCollectionExistAsync(@Nonnull String collectionName) { + Objects.requireNonNull(collectionName); + return Mono.just(this._store.containsKey(collectionName)); + } + + @Override + public Mono> getCollectionsAsync() { + return Mono.just(Collections.unmodifiableList(new ArrayList<>(this._store.keySet()))); + } + + @Override + public Mono deleteCollectionAsync(@Nonnull String collectionName) { + Objects.requireNonNull(collectionName); + return Mono.fromRunnable( + () -> { + if (this._store.containsKey(collectionName)) { + this._store.remove(collectionName); + } else { + throw new MemoryException( + MemoryException.ErrorCodes + .ATTEMPTED_TO_ACCESS_NONEXISTENT_COLLECTION, + collectionName); + } + }); + } + + @Override + public Mono upsertAsync(@Nonnull String collectionName, @Nonnull MemoryRecord record) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(record); + + return Mono.fromCallable( + () -> { + // Contract: + // Does not guarantee that the collection exists. + + Map collection = + _store.computeIfAbsent(collectionName, k -> new ConcurrentHashMap<>()); + + String key = record.getMetadata().getId(); + // Assumption is that MemoryRecord will always have a non-null id. + assert key != null; + + // Contract: + // If the record already exists, it will be updated. + // If the record does not exist, it will be created. + collection.put(key, record); + return key; + }); + } + + @Override + public Mono> upsertBatchAsync( + @Nonnull String collectionName, @Nonnull Collection records) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(records); + + return Mono.fromCallable( + () -> { + Map collection = + _store.computeIfAbsent(collectionName, k -> new ConcurrentHashMap<>()); + Set keys = new HashSet<>(); + records.forEach( + record -> { + String key = record.getMetadata().getId(); + // Assumption is that MemoryRecord will always have a non-null id. + assert key != null; + // Contract: + // If the record already exists, it will be updated. + // If the record does not exist, it will be created. + collection.put(key, record); + keys.add(key); + }); + return keys; + }); + } + + @Override + public Mono getAsync( + @Nonnull String collectionName, @Nonnull String key, boolean withEmbedding) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(key); + + return Mono.fromCallable( + () -> { + Map collection = this._store.get(collectionName); + MemoryRecord record = collection != null ? collection.get(key) : null; + if (record != null) { + if (withEmbedding) { + return record; + } else { + return MemoryRecord.fromMetadata( + record.getMetadata(), + null, + record.getMetadata().getId(), + record.getTimestamp()); + } + } + return null; + }); + } + + @Override + public Mono> getBatchAsync( + @Nonnull String collectionName, + @Nonnull Collection keys, + boolean withEmbeddings) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(keys); + + return Mono.fromCallable( + () -> { + Map collection = getCollection(collectionName); + Set records = new HashSet<>(); + keys.forEach( + key -> { + MemoryRecord record = collection.get(key); + if (record != null) { + if (withEmbeddings) { + records.add(record); + } else { + records.add( + MemoryRecord.fromMetadata( + record.getMetadata(), + null, + record.getMetadata().getId(), + record.getTimestamp())); + } + } + }); + return records; + }); + } + + @Override + public Mono removeAsync(@Nonnull String collectionName, @Nonnull String key) { + return Mono.fromRunnable( + () -> { + Map collection = this._store.get(collectionName); + if (collection != null) collection.remove(key); + }); + } + + @Override + public Mono removeBatchAsync( + @Nonnull String collectionName, @Nonnull Collection keys) { + return Mono.fromRunnable( + () -> { + Map collection = this._store.get(collectionName); + keys.forEach(collection::remove); + }); + } + + @Override + public Mono>> getNearestMatchesAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + int limit, + float minRelevanceScore, + boolean withEmbeddings) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(embedding); + + if (limit <= 0) { + return Mono.just(Collections.emptyList()); + } + + return Mono.fromCallable( + () -> { + Map collection = getCollection(collectionName); + if (collection == null || collection.isEmpty()) { + return Collections.emptyList(); + } + + Collection> nearestMatches = new ArrayList<>(); + collection + .values() + .forEach( + record -> { + if (record != null) { + float similarity = + embedding.cosineSimilarity( + record.getEmbedding()); + if (similarity >= minRelevanceScore) { + if (withEmbeddings) { + nearestMatches.add( + Tuples.of(record, similarity)); + } else { + nearestMatches.add( + Tuples.of( + MemoryRecord.fromMetadata( + record.getMetadata(), + null, + record.getMetadata() + .getId(), + record.getTimestamp()), + similarity)); + } + } + } + }); + + List> result = + nearestMatches.stream() + // sort by similarity score, descending + .sorted( + Comparator.comparing( + Tuple2::getT2, (a, b) -> Float.compare(b, a))) + .limit(limit) + .collect(Collectors.toList()); + + return result; + }); + } + + @Override + public Mono> getNearestMatchAsync( + @Nonnull String collectionName, + @Nonnull Embedding embedding, + float minRelevanceScore, + boolean withEmbedding) { + Objects.requireNonNull(collectionName); + Objects.requireNonNull(embedding); + + return getNearestMatchesAsync( + collectionName, embedding, 1, minRelevanceScore, withEmbedding) + .flatMap( + nearestMatches -> { + if (nearestMatches.isEmpty()) { + return Mono.empty(); + } + return Mono.just(nearestMatches.iterator().next()); + }); + } + + protected Map getCollection(@Nonnull String collectionName) { + Objects.requireNonNull(collectionName); + Map collection = this._store.get(collectionName); + if (collection == null) { + throw new MemoryException( + MemoryException.ErrorCodes.ATTEMPTED_TO_ACCESS_NONEXISTENT_COLLECTION, + collectionName); + } + return collection; + } + + public static class Builder implements MemoryStore.Builder { + @Override + public VolatileMemoryStore build() { + return new VolatileMemoryStore(); + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKFunction.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKFunction.java new file mode 100644 index 0000000000..b282d892f5 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultCompletionSKFunction.java @@ -0,0 +1,408 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.azure.core.exception.HttpResponseException; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.ai.AIException; +import com.microsoft.semantickernel.orchestration.FunctionNotRegisteredException.ErrorCodes; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig; +import com.microsoft.semantickernel.skilldefinition.FunctionView; +import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier; +import com.microsoft.semantickernel.skilldefinition.ParameterView; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.util.List; +import java.util.UUID; +import java.util.function.BiFunction; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/// +/// Standard Semantic Kernel callable function. +/// SKFunction is used to extend one C# , , , +/// with additional methods required by the kernel. +/// +public class DefaultCompletionSKFunction + extends DefaultSemanticSKFunction + implements CompletionSKFunction { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCompletionSKFunction.class); + + private final SemanticFunctionConfig functionConfig; + private SKSemanticAsyncTask function; + private final CompletionRequestSettings requestSettings; + + @Nullable private DefaultTextCompletionSupplier aiService; + + public DefaultCompletionSKFunction( + List parameters, + String skillName, + String functionName, + String description, + CompletionRequestSettings requestSettings, + SemanticFunctionConfig functionConfig, + @Nullable KernelSkillsSupplier kernelSkillsSupplier) { + super(parameters, skillName, functionName, description, kernelSkillsSupplier); + // TODO + // Verify.NotNull(delegateFunction, "The function delegate is empty"); + // Verify.ValidSkillName(skillName); + // Verify.ValidFunctionName(functionName); + // Verify.ParametersUniqueness(parameters); + this.requestSettings = requestSettings; + this.functionConfig = functionConfig; + } + + /* + /// + public string Name { get; } + + /// + public string SkillName { get; } + + /// + public string Description { get; } + + /// + public bool IsSemantic { get; } + + /// + public CompleteRequestSettings RequestSettings + { + get { return this._aiRequestSettings; } + } + + /// + /// List of function parameters + /// + public IList Parameters { get; } + + /// + /// Create a native function instance, wrapping a native object method + /// + /// Object containing the method to invoke + /// Signature of the method to invoke + /// SK skill name + /// Application logger + /// SK function instance + */ + + private SKContext buildContext() { + assertSkillSupplierRegistered(); + return SKBuilders.context() + .withVariables(SKBuilders.variables().build()) + .withSkills(getSkillsSupplier() == null ? null : getSkillsSupplier().get()) + .build(); + } + + /** + * Method to aggregate partitioned results of a semantic function + * + * @param partitionedInput Input to aggregate + * @param contextIn Semantic Kernel context + * @return Aggregated results + */ + @Override + public Mono aggregatePartitionedResultsAsync( + List partitionedInput, @Nullable SKContext contextIn) { + + SKContext context; + if (contextIn == null) { + context = buildContext(); + } else { + context = contextIn; + } + + // Function that takes the current context, updates it with the latest input and invokes the + // function + BiFunction, String, Flux> executeNextChunk = + (contextInput, input) -> + contextInput.concatMap( + newContext -> { + SKContext updated = newContext.copy().update(input); + return invokeAsync(updated, null); + }); + + Flux results = + Flux.fromIterable(partitionedInput) + .scanWith(() -> Flux.just(context), executeNextChunk) + .skip(1) // Skip the first element, which is the initial context + .concatMap(it -> it); + + return results.map( + result -> { + return result.getResult(); + }) + .collect(Collectors.joining("\n")) + .map(context::update); + } + + // Run the semantic function + @Override + protected Mono invokeAsyncInternal( + SKContext context, @Nullable CompletionRequestSettings settings) { + // TODO + // this.VerifyIsSemantic(); + // this.ensureContextHasSkills(context); + + if (function == null) { + throw new FunctionNotRegisteredException( + ErrorCodes.FUNCTION_NOT_REGISTERED, this.getName()); + } + + if (settings == null) { + settings = this.requestSettings; + } + + if (this.aiService.get() == null) { + throw new IllegalStateException("Failed to initialise aiService"); + } + + CompletionRequestSettings finalSettings = settings; + + return function.run(this.aiService.get(), finalSettings, context) + .map( + result -> { + return context.update(result.getVariables()); + }); + } + + @Override + public void registerOnKernel(Kernel kernel) { + this.function = + (TextCompletion client, + CompletionRequestSettings requestSettings, + SKContext contextInput) -> { + SKContext context = contextInput.copy(); + // TODO + // Verify.NotNull(client, "AI LLM backed is empty"); + + PromptTemplate func = functionConfig.getTemplate(); + + return func.renderAsync(context) + .flatMap( + prompt -> + performCompletionRequest( + client, requestSettings, prompt, context)) + .doOnError( + ex -> { + LOGGER.warn( + "Something went wrong while rendering the semantic" + + " function or while executing the text" + + " completion. Function: {}.{}. Error: {}", + getSkillName(), + getName(), + ex.getMessage()); + + // Common message when you attempt to send text completion + // requests to a chat completion model: + // "logprobs, best_of and echo parameters are not + // available on gpt-35-turbo model" + if (ex instanceof HttpResponseException + && ((HttpResponseException) ex) + .getResponse() + .getStatusCode() + == 400 + && ex.getMessage() + .contains( + "parameters are not available" + + " on")) { + LOGGER.warn( + "This error indicates that you have attempted" + + " to use a chat completion model in a" + + " text completion service. Try using a" + + " chat completion service instead when" + + " building your kernel, for instance when" + + " building your service use" + + " SKBuilders.chatCompletion() rather than" + + " SKBuilders.textCompletionService()."); + } + }); + }; + + this.setSkillsSupplier(kernel::getSkills); + this.aiService = () -> kernel.getService(null, TextCompletion.class); + } + + private static Mono performCompletionRequest( + TextCompletion client, + CompletionRequestSettings requestSettings, + String prompt, + SKContext context) { + + LOGGER.debug("RENDERED PROMPT: \n{}", prompt); + + switch (client.defaultCompletionType()) { + case NON_STREAMING: + return client.completeAsync(prompt, requestSettings) + .single() + .map(completion -> context.update(completion.get(0))); + + case STREAMING: + default: + return client.completeStreamAsync(prompt, requestSettings) + .filter(completion -> !completion.isEmpty()) + .take(1) + .single() + .map(context::update); + } + } + + @Override + public Class getType() { + return CompletionRequestSettings.class; + } + + private static String randomFunctionName() { + return "func" + UUID.randomUUID(); + } + + @Override + public FunctionView describe() { + return new FunctionView( + super.getName(), + super.getSkillName(), + super.getDescription(), + super.getParametersView(), + true, + false); + } + + public static class Builder implements CompletionSKFunction.Builder { + + private Kernel kernel; + @Nullable private String promptTemplate = null; + @Nullable private String functionName = null; + @Nullable private String skillName = null; + @Nullable private String description = null; + private PromptTemplateConfig.CompletionConfig completionConfig = + new PromptTemplateConfig.CompletionConfig(); + @Nullable private SemanticFunctionConfig functionConfig = null; + @Nullable private PromptTemplateConfig promptTemplateConfig = null; + + @Override + public CompletionSKFunction build() { + if (kernel == null) { + throw new AIException( + AIException.ErrorCodes.INVALID_CONFIGURATION, + "Called builder to create a function without setting the kernel"); + } + + if (functionName == null) { + functionName = randomFunctionName(); + } + + // Verify.NotNull(functionConfig, "Function configuration is empty"); + if (skillName == null) { + skillName = ReadOnlySkillCollection.GlobalSkill; + } + + if (functionConfig == null) { + + if (description == null) { + description = "Generic function, unknown purpose"; + } + + if (promptTemplate == null) { + throw new AIException( + AIException.ErrorCodes.INVALID_CONFIGURATION, + "Must set prompt template before building"); + } + + if (promptTemplateConfig == null) { + promptTemplateConfig = + new PromptTemplateConfig(description, "completion", completionConfig); + } + + PromptTemplate template = + SKBuilders.promptTemplate() + .withPromptTemplateConfig(promptTemplateConfig) + .withPromptTemplate(promptTemplate) + .withPromptTemplateEngine(kernel.getPromptTemplateEngine()) + .build(); + + // Prepare lambda wrapping AI logic + functionConfig = new SemanticFunctionConfig(promptTemplateConfig, template); + } + + CompletionRequestSettings requestSettings = + CompletionRequestSettings.fromCompletionConfig( + functionConfig.getConfig().getCompletionConfig()); + + PromptTemplate promptTemplate = functionConfig.getTemplate(); + + DefaultCompletionSKFunction function = + new DefaultCompletionSKFunction( + promptTemplate.getParameters(), + skillName, + functionName, + functionConfig.getConfig().getDescription(), + requestSettings, + functionConfig, + null); + + kernel.registerSemanticFunction(function); + return function; + } + + @Override + public CompletionSKFunction.Builder withKernel(Kernel kernel) { + this.kernel = kernel; + return this; + } + + @Override + public CompletionSKFunction.Builder withPromptTemplate(String promptTemplate) { + this.promptTemplate = promptTemplate; + return this; + } + + @Override + public CompletionSKFunction.Builder withPromptTemplateConfig( + PromptTemplateConfig promptTemplateConfig) { + this.promptTemplateConfig = promptTemplateConfig; + return this; + } + + @Override + public CompletionSKFunction.Builder withCompletionConfig( + PromptTemplateConfig.CompletionConfig completionConfig) { + this.completionConfig = completionConfig; + return this; + } + + @Override + public CompletionSKFunction.Builder withSemanticFunctionConfig( + SemanticFunctionConfig functionConfig) { + this.functionConfig = functionConfig; + return this; + } + + @Override + public CompletionSKFunction.Builder withSkillName(@Nullable String skillName) { + this.skillName = skillName; + return this; + } + + @Override + public CompletionSKFunction.Builder withFunctionName(@Nullable String functionName) { + this.functionName = functionName; + return this; + } + + @Override + public CompletionSKFunction.Builder withDescription(String description) { + this.description = description; + return this; + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultContextVariables.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultContextVariables.java new file mode 100644 index 0000000000..2b931ff857 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultContextVariables.java @@ -0,0 +1,178 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.skilldefinition.CaseInsensitiveMap; +import java.util.Collections; +import java.util.Map; +import javax.annotation.Nullable; +import reactor.util.annotation.NonNull; + +/// +/// Context Variables is a data structure that holds temporary data while a task is being performed. +/// It is accessed and manipulated by functions in the pipeline. +/// +class DefaultContextVariables implements ContextVariables, WritableContextVariables { + + private final CaseInsensitiveMap variables; + + /// + /// In the simplest scenario, the data is an input string, stored here. + /// + // public string Input => this._variables[MainKey]; + + /// + /// Constructor for context variables. + /// + /// Optional value for the main variable of the context. + DefaultContextVariables(@NonNull String content) { + this.variables = new CaseInsensitiveMap<>(); + this.variables.put(MAIN_KEY, content); + } + + DefaultContextVariables(Map variables) { + this.variables = new CaseInsensitiveMap<>(variables); + } + + @Override + public ContextVariables setVariable(@NonNull String key, @NonNull String content) { + this.variables.put(key, content); + return this; + } + + @Override + public ContextVariables appendToVariable(@NonNull String key, @NonNull String content) { + String existing = this.variables.get(key); + + String newVal; + if (existing == null) { + newVal = content; + } else { + newVal = existing + content; + } + + return setVariable(key, newVal); + } + + @Override + public Map asMap() { + return Collections.unmodifiableMap(variables); + } + + /// + /// Updates the main input text with the new value after a function is complete. + /// + /// The new input value, for the next function in the pipeline, or as a + // result for the user + /// if the pipeline reached the end. + /// The current instance + @Override + public ContextVariables update(@NonNull String content) { + return setVariable(MAIN_KEY, content); + } + + public DefaultContextVariables update(@NonNull DefaultContextVariables newData) { + return update(newData, true); + } + + /// + /// Updates all the local data with new data, merging the two datasets. + /// Do not discard old data + /// + /// New data to be merged + /// Whether to merge and keep old data, or replace. False == discard old + // data. + /// The current instance + + @Override + public DefaultContextVariables update(@NonNull ContextVariables newData, boolean merge) { + /* + // If requested, discard old data and keep only the new one. + if (!merge) { this._variables.Clear(); } + + foreach (KeyValuePair varData in newData._variables) + { + this._variables[varData.Key] = varData.Value; + } + + */ + this.variables.putAll(newData.asMap()); + return this; + } + + @Override + public ContextVariables remove(String key) { + variables.remove(key); + return this; + } + + @Override + public WritableContextVariables writableClone() { + return new DefaultContextVariables(variables); + } + + @Override + @Nullable + public String getInput() { + return get(MAIN_KEY); + } + + @Override + public String prettyPrint() { + return variables.entrySet().stream() + .reduce( + "", + (str, entry) -> + str + + System.lineSeparator() + + entry.getKey() + + ": " + + entry.getValue(), + (a, b) -> a + b); + } + + @Override + @Nullable + public String get(String key) { + return variables.get(key); + } + + public static class WritableBuilder implements WritableContextVariables.Builder { + @Override + public WritableContextVariables build(Map map) { + return new DefaultContextVariables(map); + } + } + + public static class Builder implements ContextVariables.Builder { + + private final Map variables; + + public Builder() { + variables = new CaseInsensitiveMap<>(); + this.variables.put(MAIN_KEY, ""); + } + + @Override + public ContextVariables.Builder withVariable(String key, String value) { + variables.put(key, value); + return this; + } + + @Override + public Builder withInput(String content) { + variables.put(MAIN_KEY, content); + return this; + } + + @Override + public Builder withVariables(Map map) { + variables.putAll(map); + return this; + } + + @Override + public ContextVariables build() { + return new DefaultContextVariables(variables); + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSKContext.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSKContext.java new file mode 100644 index 0000000000..c078264ab1 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSKContext.java @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.memory.SemanticTextMemory; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import javax.annotation.Nullable; + +public class DefaultSKContext extends AbstractSKContext { + + protected DefaultSKContext(SKContext toClone, String errorDescription, Exception exception) { + super(toClone, errorDescription, exception); + } + + public DefaultSKContext(ContextVariables variables) { + super(variables); + } + + public DefaultSKContext( + ContextVariables variables, + @Nullable SemanticTextMemory memory, + @Nullable ReadOnlySkillCollection skillCollection) { + super(variables, memory, skillCollection); + } + + @Override + protected SKContext getThis() { + return this; + } + + @Override + public SKContext build( + ContextVariables variables, + @Nullable SemanticTextMemory memory, + @Nullable ReadOnlySkillCollection skillCollection) { + return new DefaultSKContext(variables, memory, skillCollection); + } + + public static class Builder implements SKContext.Builder { + + private ContextVariables variables; + private ReadOnlySkillCollection skills; + private SemanticTextMemory memory; + + @Override + public SKContext failed(SKContext toClone, String errorDescription, Exception exception) { + return new DefaultSKContext(toClone, errorDescription, exception); + } + + @Override + public SKContext build() { + if (variables == null) { + variables = SKBuilders.variables().build(); + } + return new DefaultSKContext(variables, memory, skills); + } + + @Override + public SKContext.Builder withVariables(ContextVariables variables) { + this.variables = variables; + return this; + } + + @Override + public SKContext.Builder withSkills(@Nullable ReadOnlySkillCollection skills) { + if (skills != null) { + this.skills = skills; + } + return this; + } + + @Override + public SKContext.Builder withMemory(@Nullable SemanticTextMemory memory) { + if (memory != null) { + this.memory = memory.copy(); + } + return this; + } + + @Override + public SKContext.Builder clone(SKContext context) { + return withVariables(context.getVariables()) + .withSkills(context.getSkills()) + .withMemory(context.getSemanticMemory()); + } + + @Override + public SKContext.Builder withKernel(Kernel kernel) { + if (memory == null) { + memory = kernel.getMemory(); + } + if (skills == null) { + skills = kernel.getSkills(); + } + if (variables == null) { + variables = SKBuilders.variables().build(); + } + return this; + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKFunction.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKFunction.java new file mode 100644 index 0000000000..7f032198cf --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultSemanticSKFunction.java @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.memory.NullMemory; +import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier; +import com.microsoft.semantickernel.skilldefinition.ParameterView; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/// +/// Standard Semantic Kernel callable function. +/// SKFunction is used to extend one C# , , , +/// with additional methods required by the kernel. +/// +public abstract class DefaultSemanticSKFunction + extends AbstractSkFunction + implements SKFunction { + + public DefaultSemanticSKFunction( + List parameters, + String skillName, + String functionName, + String description, + @Nullable KernelSkillsSupplier kernelSkillsSupplier) { + super( + parameters, + skillName, + functionName, + description, + Collections.emptyList(), + kernelSkillsSupplier); + } + + @Override + public Mono invokeAsync( + @Nullable String input, + @Nullable SKContext context, + @Nullable RequestConfiguration settings) { + if (context == null) { + assertSkillSupplierRegistered(); + context = + SKBuilders.context() + .withVariables(SKBuilders.variables().build()) + .withMemory(NullMemory.getInstance()) + .withSkills(super.getSkillsSupplier().get()) + .build(); + } else { + context = context.copy(); + } + + if (input != null) { + context = context.update(input); + } + + return this.invokeAsync(context, settings); + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultTextCompletionSupplier.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultTextCompletionSupplier.java new file mode 100644 index 0000000000..e339bd9504 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/DefaultTextCompletionSupplier.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.util.function.Supplier; + +public interface DefaultTextCompletionSupplier extends Supplier { + + public static TextCompletion getInstance(Kernel kernel) { + return kernel.getService(null, TextCompletion.class); + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/NativeSKFunction.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/NativeSKFunction.java new file mode 100644 index 0000000000..5c4193766e --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/NativeSKFunction.java @@ -0,0 +1,538 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import static com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters.NO_DEFAULT_VALUE; + +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.ai.AIException; +import com.microsoft.semantickernel.ai.AIException.ErrorCodes; +import com.microsoft.semantickernel.skilldefinition.FunctionView; +import com.microsoft.semantickernel.skilldefinition.KernelSkillsSupplier; +import com.microsoft.semantickernel.skilldefinition.ParameterView; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +/// +/// Standard Semantic Kernel callable function. +/// SKFunction is used to extend one C# , , , +/// with additional methods required by the kernel. +/// +public class NativeSKFunction extends AbstractSkFunction { + + private static final Logger LOGGER = LoggerFactory.getLogger(NativeSKFunction.class); + + private final SKNativeTask function; + + public NativeSKFunction( + SKNativeTask delegateFunction, + List parameters, + String skillName, + String functionName, + String description, + List returnParameter, + KernelSkillsSupplier skillCollection) { + super(parameters, skillName, functionName, description, returnParameter, skillCollection); + // TODO + // Verify.NotNull(delegateFunction, "The function delegate is empty"); + // Verify.ValidSkillName(skillName); + // Verify.ValidFunctionName(functionName); + // Verify.ParametersUniqueness(parameters); + + this.function = delegateFunction; + } + + @Override + public FunctionView describe() { + return new FunctionView( + super.getName(), + super.getSkillName(), + super.getDescription(), + super.getParametersView(), + false, + false); + } + + @Override + public Class getType() { + return Void.class; + } + + @Override + public void registerOnKernel(Kernel kernel) { + // No actions needed + } + + private static class MethodDetails { + + public final boolean hasSkFunctionAttribute; + public final SKNativeTask function; + public final List parameters; + public final String name; + public final String description; + private final String returnType; + private final String returnDescription; + + private MethodDetails( + boolean hasSkFunctionAttribute, + SKNativeTask function, + List parameters, + String name, + String description, + String returnType, + String returnDescription) { + this.hasSkFunctionAttribute = hasSkFunctionAttribute; + this.function = function; + this.parameters = parameters; + this.name = name; + this.description = description; + this.returnType = returnType; + this.returnDescription = returnDescription; + } + + public String getReturnType() { + return returnType; + } + + public String getReturnDescription() { + return returnDescription; + } + } + + public static NativeSKFunction fromNativeMethod( + Method methodSignature, + Object methodContainerInstance, + String skillName, + KernelSkillsSupplier kernelSkillsSupplier) { + if (skillName == null || skillName.isEmpty()) { + skillName = ReadOnlySkillCollection.GlobalSkill; + } + + MethodDetails methodDetails = getMethodDetails(methodSignature, methodContainerInstance); + + // If the given method is not a valid SK function + if (!methodSignature.isAnnotationPresent(DefineSKFunction.class)) { + throw new RuntimeException("Not a valid function"); + } + + ParameterView returnParam = + new ParameterView("return", methodDetails.getReturnDescription(), ""); + + return new NativeSKFunction( + methodDetails.function, + methodDetails.parameters, + skillName, + methodDetails.name, + methodDetails.description, + Collections.singletonList(returnParam), + kernelSkillsSupplier); + } + + // Run the native function + @Override + protected Mono invokeAsyncInternal(SKContext context, @Nullable Void settings) { + return this.function.run(context); + } + + private static MethodDetails getMethodDetails( + Method methodSignature, Object methodContainerInstance) { + // Verify.NotNull(methodSignature, "Method is NULL"); + + // String name = methodSignature.getName(); + + boolean hasSkFunctionAttribute = + methodSignature.isAnnotationPresent(DefineSKFunction.class); + + if (!hasSkFunctionAttribute) { + throw new RuntimeException("method is not annotated with DefineSKFunction"); + } + SKNativeTask function = getFunction(methodSignature, methodContainerInstance); + + // boolean hasStringParam = + // Arrays.asList(methodSignature.getGenericParameterTypes()).contains(String.class); + + String name = methodSignature.getAnnotation(DefineSKFunction.class).name(); + + if (name == null || name.isEmpty()) { + name = methodSignature.getName(); + } + + String description = methodSignature.getAnnotation(DefineSKFunction.class).description(); + + List parameters = getParameters(methodSignature); + + String returnType = methodSignature.getAnnotation(DefineSKFunction.class).returnType(); + String returnDescription = + methodSignature.getAnnotation(DefineSKFunction.class).returnDescription(); + + return new MethodDetails( + hasSkFunctionAttribute, + function, + parameters, + name, + description, + returnType, + returnDescription); + } + + private static List getParameters(Method method) { + + List params = + Arrays.stream(method.getParameters()) + .filter( + parameter -> + parameter.isAnnotationPresent(SKFunctionParameters.class) + || parameter.isAnnotationPresent( + SKFunctionInputAttribute.class)) + .map( + parameter -> { + if (parameter.isAnnotationPresent(SKFunctionParameters.class)) { + SKFunctionParameters annotation = + parameter.getAnnotation(SKFunctionParameters.class); + return new ParameterView( + annotation.name(), + annotation.description(), + annotation.defaultValue()); + } else { + SKFunctionInputAttribute annotation = + parameter.getAnnotation( + SKFunctionInputAttribute.class); + return new ParameterView( + "input", annotation.description(), ""); + } + }) + .collect(Collectors.toList()); + + HashSet out = new HashSet<>(params); + + boolean hasInput = params.stream().anyMatch(p -> p.getName().equals("input")); + + if (!hasInput) { + List inputArgs = + determineInputArgs(method).stream() + .map( + parameter -> { + return new ParameterView("input"); + }) + .collect(Collectors.toList()); + out.addAll(inputArgs); + } + + return new ArrayList<>(out); + } + + private static SKNativeTask getFunction(Method method, Object instance) { + return (contextInput) -> { + SKContext context = contextInput.copy(); + + Set inputArgs = determineInputArgs(method); + + try { + List args = + Arrays.stream(method.getParameters()) + .map(getParameters(method, context, inputArgs)) + .collect(Collectors.toList()); + + Mono mono; + if (method.getReturnType().isAssignableFrom(Mono.class)) { + try { + mono = (Mono) method.invoke(instance, args.toArray()); + } catch (IllegalAccessException | InvocationTargetException e) { + return Mono.error(e); + } + } else { + mono = invokeAsyncFunction(method, instance, args); + } + + return mono.map( + it -> { + if (it instanceof Iterable) { + // Handle return from things like Mono> + // from {{function 'input'}} as part of the prompt. + it = ((Iterable) it).iterator().next(); + } + if (it instanceof SKContext) { + return it; + } else { + return context.update((String) it); + } + }); + } catch (Exception e) { + return Mono.error(e); + } + }; + } + + private static Mono invokeAsyncFunction( + Method method, Object instance, List args) { + return Mono.defer( + () -> + Mono.fromCallable( + () -> { + try { + if (method.getReturnType().getName().equals("void") + || method.getReturnType() + .equals(Void.class)) { + method.invoke(instance, args.toArray()); + return null; + } else { + return method.invoke(instance, args.toArray()); + } + } catch (InvocationTargetException e) { + throw new AIException( + ErrorCodes.INVALID_REQUEST, + "Function threw an exception: " + + method.getName(), + e.getCause()); + } catch (IllegalAccessException e) { + throw new AIException( + ErrorCodes.INVALID_REQUEST, + "Unable to access function " + + method.getName(), + e); + } + }) + .subscribeOn(Schedulers.boundedElastic())); + } + + private static Function getParameters( + Method method, SKContext context, Set inputArgs) { + return parameter -> { + if (SKContext.class.isAssignableFrom(parameter.getType())) { + return context; + } else { + return getArgumentValue(method, context, parameter, inputArgs); + } + }; + } + + private static String formErrorMessage(Method method, Parameter parameter) { + Matcher matcher = Pattern.compile("arg(\\d)").matcher(parameter.getName()); + matcher.find(); + return "For the function " + + method.getDeclaringClass().getName() + + "." + + method.getName() + + ", the unknown parameter" + + " name was detected as \"" + + parameter.getName() + + "\" this is argument" + + " number " + + matcher.group(1) + + " to the function, this indicates that the argument name for this function was" + + " removed during compilation and semantic-kernel is unable to determine the name" + + " of the parameter. To support this function the argument must be annotated with" + + " @SKFunctionParameters or @SKFunctionInputAttribute. Alternatively the function" + + " was invoked with a required context variable missing and no default value."; + } + + private static Object getArgumentValue( + Method method, SKContext context, Parameter parameter, Set inputArgs) { + String variableName = getGetVariableName(parameter); + + String arg = context.getVariables().get(variableName); + if (arg == null) { + // If this is bound to input get the input value + if (inputArgs.contains(parameter)) { + String input = context.getVariables().get(ContextVariables.MAIN_KEY); + if (input != null) { + arg = input; + } + } + + if (arg == null) { + SKFunctionParameters annotation = + parameter.getAnnotation(SKFunctionParameters.class); + if (annotation != null) { + arg = annotation.defaultValue(); + + if (NO_DEFAULT_VALUE.equals(arg)) { + if (!annotation.required()) { + return null; + } + + throw new AIException( + AIException.ErrorCodes.INVALID_CONFIGURATION, + "Attempted to invoke function " + + method.getDeclaringClass().getName() + + "." + + method.getName() + + ". The context variable \"" + + variableName + + "\" has not been set, and no default value is" + + " specified."); + } + } + } + } + + if (arg == null && variableName.matches("arg\\d")) { + LOGGER.warn(formErrorMessage(method, parameter)); + } + + if (NO_DEFAULT_VALUE.equals(arg)) { + if (parameter.getName().matches("arg\\d")) { + throw new AIException( + AIException.ErrorCodes.INVALID_CONFIGURATION, + formErrorMessage(method, parameter)); + } else { + throw new AIException( + AIException.ErrorCodes.INVALID_CONFIGURATION, + "Unknown arg " + parameter.getName()); + } + } + + SKFunctionParameters annotation = parameter.getAnnotation(SKFunctionParameters.class); + if (annotation == null || annotation.type() == null) { + return arg; + } + Class type = annotation.type(); + if (Number.class.isAssignableFrom(type)) { + arg = arg.replace(",", "."); + } + + Object value = arg; + // Well-known types only + Function converter = converters.get(type); + if (converter != null) { + try { + value = converter.apply(arg); + } catch (NumberFormatException nfe) { + throw new AIException( + AIException.ErrorCodes.INVALID_CONFIGURATION, + "Invalid value for " + + parameter.getName() + + " expected " + + type.getSimpleName() + + " but got " + + arg); + } + } + return value; + } + + private static final Map, Function> converters = new HashMap<>(); + + static { + converters.put(Boolean.class, Boolean::valueOf); + converters.put(boolean.class, Boolean::valueOf); + converters.put(Byte.class, Byte::parseByte); + converters.put(byte.class, Byte::parseByte); + converters.put(Integer.class, Integer::parseInt); + converters.put(int.class, Integer::parseInt); + converters.put(Long.class, Long::parseLong); + converters.put(long.class, Long::parseLong); + converters.put(Double.class, Double::parseDouble); + converters.put(double.class, Double::parseDouble); + converters.put(Float.class, Float::parseFloat); + converters.put(float.class, Float::parseFloat); + converters.put(Short.class, Short::parseShort); + converters.put(short.class, Short::parseShort); + converters.put(String.class, it -> it); + } + + private static String getGetVariableName(Parameter parameter) { + SKFunctionParameters annotation = parameter.getAnnotation(SKFunctionParameters.class); + + if (annotation == null || annotation.name() == null || annotation.name().isEmpty()) { + return parameter.getName(); + } + return annotation.name(); + } + + private static Set determineInputArgs(Method method) { + // Something is bound to the input if either: + // - it is annotated with @SKFunctionInputAttribute + // - SKFunctionParameters annotation has a name of "input" + // - the arg name is "input" + // - there is only 1 string argument to the function + + // Get all parameters annotated with SKFunctionInputAttribute + List annotated = + Arrays.stream(method.getParameters()) + .filter(it -> it.isAnnotationPresent(SKFunctionInputAttribute.class)) + .collect(Collectors.toList()); + + if (annotated.size() > 1) { + LOGGER.warn( + "Multiple arguments of " + + method.getName() + + " have the @SKFunctionInputAttribute annotation. This is likely an" + + " error."); + } + + // Get all parameters annotated with SKFunctionParameters with a name of "input" + List annotatedWithName = + Arrays.stream(method.getParameters()) + .filter(it -> it.isAnnotationPresent(SKFunctionParameters.class)) + .filter(it -> it.getName().equals("input")) + .collect(Collectors.toList()); + + if (annotatedWithName.size() > 1) { + LOGGER.warn( + "Multiple arguments of " + + method.getName() + + " have the name input. This is likely an error."); + } + + // Get all parameters named "input", this will frequently fail as compilers strip out + // argument names + List calledInput = + Arrays.stream(method.getParameters()) + .filter(it -> getGetVariableName(it).equals("input")) + .collect(Collectors.toList()); + + // Get parameter if there is only 1 string, and it has not been annotated with + // SKFunctionParameters + List soloString = + Arrays.stream(method.getParameters()) + .filter(it -> it.getType().equals(String.class)) + .filter( + it -> + !(it.isAnnotationPresent(SKFunctionParameters.class) + && !it.getAnnotation(SKFunctionParameters.class) + .name() + .isEmpty())) + .collect(Collectors.toList()); + if (soloString.size() > 1) { + soloString.clear(); + } + + Set params = new HashSet<>(); + params.addAll(annotated); + params.addAll(annotatedWithName); + params.addAll(calledInput); + params.addAll(soloString); + + if (params.size() > 1) { + LOGGER.warn( + "Multiple arguments of " + + method.getName() + + " are bound to the input variable. This is likely an error."); + } + + return params; + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKNativeTask.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKNativeTask.java new file mode 100644 index 0000000000..e5051af455 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKNativeTask.java @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import reactor.core.publisher.Mono; + +public interface SKNativeTask extends SKTask { + Mono run(Result context); +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKSemanticAsyncTask.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKSemanticAsyncTask.java new file mode 100644 index 0000000000..d4e4243459 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKSemanticAsyncTask.java @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import reactor.core.publisher.Mono; + +public interface SKSemanticAsyncTask extends SKTask { + Mono run( + TextCompletion client, CompletionRequestSettings requestSettings, Result context); +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKTask.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKTask.java new file mode 100644 index 0000000000..136ec84b2e --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/orchestration/SKTask.java @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +public interface SKTask {} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/semanticfunctions/DefaultPromptTemplate.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/semanticfunctions/DefaultPromptTemplate.java new file mode 100644 index 0000000000..7b8ee70bcd --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/semanticfunctions/DefaultPromptTemplate.java @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.semanticfunctions; + +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.ParameterView; +import com.microsoft.semantickernel.templateengine.PromptTemplateEngine; +import com.microsoft.semantickernel.templateengine.blocks.BlockTypes; +import com.microsoft.semantickernel.templateengine.blocks.VarBlock; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.annotation.Nullable; +import reactor.core.publisher.Mono; + +/// +/// Prompt template. +/// +public class DefaultPromptTemplate implements PromptTemplate { + private final String promptTemplate; + private final PromptTemplateConfig config; + private final PromptTemplateEngine templateEngine; + + public DefaultPromptTemplate( + String promptTemplate, + PromptTemplateConfig config, + PromptTemplateEngine templateEngine) { + this.promptTemplate = promptTemplate; + this.config = config; + this.templateEngine = templateEngine; + } + + @Override + public List getParameters() { + // Parameters from config.json + List result = + this.config.getInput().getParameters().stream() + .filter(Objects::nonNull) + .map( + p -> + new ParameterView( + p.getName(), + p.getDescription(), + p.getDefaultValue())) + .collect(Collectors.toList()); + + List seen = + result.stream().map(ParameterView::getName).collect(Collectors.toList()); + + List listFromTemplate = + templateEngine.extractBlocks(this.promptTemplate).stream() + .filter(Objects::nonNull) + .filter(x -> x.getType() == BlockTypes.Variable) + .map(x -> (VarBlock) x) + .collect(Collectors.toList()); + + List newParams = + listFromTemplate.stream() + .filter(x -> !seen.contains(x.getName())) + .map(x -> new ParameterView(x.getName())) + .collect(Collectors.toList()); + + return Stream.concat(result.stream(), newParams.stream()).collect(Collectors.toList()); + } + + @Override + public Mono renderAsync(SKContext executionContext) { + return templateEngine.renderAsync(this.promptTemplate, executionContext); + } + + public static final class Builder implements PromptTemplate.Builder { + @Nullable private String promptTemplate = null; + @Nullable private PromptTemplateConfig config = null; + @Nullable private PromptTemplateEngine promptTemplateEngine = null; + + @Override + public PromptTemplate.Builder withPromptTemplate(String promptTemplate) { + this.promptTemplate = promptTemplate; + return this; + } + + @Override + public PromptTemplate.Builder withPromptTemplateConfig(PromptTemplateConfig config) { + this.config = config; + return this; + } + + @Override + public PromptTemplate.Builder withPromptTemplateEngine( + PromptTemplateEngine promptTemplateEngine) { + this.promptTemplateEngine = promptTemplateEngine; + return this; + } + + @Override + public PromptTemplate build() { + if (promptTemplate == null || config == null || promptTemplateEngine == null) { + throw new IllegalStateException( + "PromptTemplate, PromptTemplateConfig and promptTemplateEngine must be" + + " set"); + } + return new DefaultPromptTemplate(promptTemplate, config, promptTemplateEngine); + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/CaseInsensitiveMap.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/CaseInsensitiveMap.java new file mode 100644 index 0000000000..3e244adcd3 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/CaseInsensitiveMap.java @@ -0,0 +1,138 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class CaseInsensitiveMap extends HashMap { + public CaseInsensitiveMap(Map kvMap) { + super(); + putAll(kvMap); + } + + public CaseInsensitiveMap() { + super(); + } + + @Override + public T computeIfAbsent(String key, Function mappingFunction) { + if (key == null) { + return super.computeIfAbsent(null, mappingFunction); + } + return super.computeIfAbsent(key.toLowerCase(Locale.ROOT), mappingFunction); + } + + @Override + public T computeIfPresent( + String key, BiFunction remappingFunction) { + if (key == null) { + return super.computeIfPresent(null, remappingFunction); + } + return super.computeIfPresent(key.toLowerCase(Locale.ROOT), remappingFunction); + } + + @Override + public T compute( + String key, BiFunction remappingFunction) { + if (key == null) { + return super.compute(null, remappingFunction); + } + return super.compute(key.toLowerCase(Locale.ROOT), remappingFunction); + } + + @Override + public boolean containsKey(Object key) { + if (key == null) { + return super.containsKey(null); + } + return super.containsKey(((String) key).toLowerCase(Locale.ROOT)); + } + + @Override + public T get(Object key) { + if (key == null) { + return super.get(null); + } + return super.get(((String) key).toLowerCase(Locale.ROOT)); + } + + @Override + public T getOrDefault(Object key, T defaultValue) { + if (key == null) { + return super.getOrDefault(null, defaultValue); + } + return super.getOrDefault(((String) key).toLowerCase(Locale.ROOT), defaultValue); + } + + @Override + public T merge( + String key, T value, BiFunction remappingFunction) { + if (key == null) { + return super.merge(null, value, remappingFunction); + } + return super.merge(key.toLowerCase(Locale.ROOT), value, remappingFunction); + } + + @Override + public T put(String key, T value) { + if (key == null) { + return super.put(null, value); + } + return super.put(key.toLowerCase(Locale.ROOT), value); + } + + @Override + public void putAll(Map m) { + super.putAll( + m.entrySet().stream() + .collect( + Collectors.toMap( + key -> key.getKey().toLowerCase(Locale.ROOT), + Entry::getValue))); + } + + @Override + public T putIfAbsent(String key, T value) { + if (key == null) { + return super.putIfAbsent(null, value); + } + return super.putIfAbsent(key.toLowerCase(Locale.ROOT), value); + } + + @Override + public boolean remove(Object key, Object value) { + if (key == null) { + return super.remove(null, value); + } + return super.remove(((String) key).toLowerCase(Locale.ROOT), value); + } + + @Override + public T remove(Object key) { + if (key == null) { + return super.remove(null); + } + return super.remove(((String) key).toLowerCase(Locale.ROOT)); + } + + @Override + public boolean replace(String key, T oldValue, T newValue) { + + if (key == null) { + return super.replace(null, oldValue, newValue); + } + return super.replace(key.toLowerCase(Locale.ROOT), oldValue, newValue); + } + + @Override + public T replace(String key, T value) { + if (key == null) { + return super.replace(null, value); + } + return super.replace(key.toLowerCase(Locale.ROOT), value); + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/DefaultSkillCollection.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/DefaultSkillCollection.java new file mode 100644 index 0000000000..a88bc5aa57 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/DefaultSkillCollection.java @@ -0,0 +1,153 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +import com.microsoft.semantickernel.orchestration.SKFunction; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +/// +/// Semantic Kernel default skill collection class. +/// The class holds a list of all the functions, native and semantic, known to the kernel instance. +/// The list is used by the planner and when executing pipelines of function compositions. +/// +// [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1710:Identifiers should have +// correct suffix", Justification = "It is a collection")] +// [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1711:Identifiers should not have +// incorrect suffix", Justification = "It is a collection")] +public class DefaultSkillCollection implements ReadOnlySkillCollection { + + private final CaseInsensitiveMap skillCollection; + + public static class Builder implements ReadOnlySkillCollection.Builder { + @Override + public ReadOnlySkillCollection build() { + return new DefaultSkillCollection(); + } + } + + protected Map getSkillCollection() { + return skillCollection; + } + + public DefaultSkillCollection(ReadOnlySkillCollection skillCollection) { + this(skillCollection.asMap()); + } + + public DefaultSkillCollection( + Map skillCollection) { + + Map cloned = + skillCollection.entrySet().stream() + .collect( + Collectors + ., + String, FunctionCollection> + toMap( + Map.Entry::getKey, + it -> + new FunctionCollection( + it.getValue()))); + + this.skillCollection = new CaseInsensitiveMap<>(cloned); + } + + public DefaultSkillCollection() { + this.skillCollection = new CaseInsensitiveMap<>(); + } + + public DefaultSkillCollection addSemanticFunction(SKFunction functionInstance) { + FunctionCollection existingFunctionCollection; + if (!skillCollection.containsKey(functionInstance.getSkillName())) { + existingFunctionCollection = new FunctionCollection(functionInstance.getSkillName()); + skillCollection.put(functionInstance.getSkillName(), existingFunctionCollection); + } else { + existingFunctionCollection = skillCollection.get(functionInstance.getSkillName()); + } + + existingFunctionCollection.put(functionInstance.getName(), functionInstance); + + return this; + } + + @Override + @Nullable + public > T getFunction( + String funName, @Nullable Class functionClazz) { + return getFunction(GlobalSkill, funName, functionClazz); + } + + @Override + @Nullable + public > T getFunction( + String skillName, String funName, @Nullable Class functionClazz) { + FunctionCollection skills = skillCollection.get(skillName.toLowerCase(Locale.ROOT)); + if (skills == null) { + return null; + } + return skills.getFunction(funName, functionClazz); + } + + @Nullable + @Override + public FunctionCollection getFunctions(String skillName) { + return skillCollection.get(skillName.toLowerCase(Locale.ROOT)); + } + + @Override + public boolean hasFunction(String functionName) { + return getFunction(functionName, SKFunction.class) != null; + } + + @Override + public boolean hasFunction(String skillName, String functionName) { + FunctionCollection skills = skillCollection.get(skillName.toLowerCase(Locale.ROOT)); + if (skills == null) { + return false; + } + return skills.getFunction(functionName) != null; + } + + @Override + @CheckReturnValue + public ReadOnlySkillCollection copy() { + return new DefaultSkillCollection(skillCollection); + } + + public DefaultSkillCollection addNativeFunction(SKFunction functionInstance) { + // TODO is there any difference here? + return addSemanticFunction(functionInstance); + } + + public DefaultSkillCollection merge(ReadOnlySkillCollection in) { + in.asMap() + .entrySet() + .forEach( + entry -> { + FunctionCollection existing = + skillCollection.get(entry.getKey().toLowerCase(Locale.ROOT)); + if (existing == null) { + skillCollection.put( + entry.getKey().toLowerCase(Locale.ROOT), + new FunctionCollection(entry.getValue())); + } else { + existing.merge(new FunctionCollection(entry.getValue())); + } + }); + return this; + } + + @Override + public Map asMap() { + return Collections.unmodifiableMap(skillCollection); + } + + @Override + public FunctionCollection getAllFunctions() { + return skillCollection.values().stream() + .reduce(new FunctionCollection(""), FunctionCollection::merge); + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionCollection.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionCollection.java new file mode 100644 index 0000000000..5b80674372 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/skilldefinition/FunctionCollection.java @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.skilldefinition; + +import com.microsoft.semantickernel.exceptions.SkillsNotFoundException; +import com.microsoft.semantickernel.exceptions.SkillsNotFoundException.ErrorCodes; +import com.microsoft.semantickernel.orchestration.SKFunction; +import java.util.*; +import java.util.stream.Collectors; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +/** A collection of functions. */ +public class FunctionCollection implements ReadOnlyFunctionCollection { + private final CaseInsensitiveMap> functionCollection; + + private final String skillName; + + private FunctionCollection(String skillName, Map> functionCollection) { + this.functionCollection = new CaseInsensitiveMap<>(functionCollection); + this.skillName = skillName; + } + + public FunctionCollection(String skillName, List> functionCollection) { + this( + skillName, + functionCollection.stream() + .collect( + Collectors.toMap( + it -> it.getName().toLowerCase(Locale.ROOT), it -> it))); + } + + public FunctionCollection(String skillName) { + this.skillName = skillName; + this.functionCollection = new CaseInsensitiveMap<>(); + } + + public FunctionCollection(ReadOnlyFunctionCollection value) { + this.skillName = value.getSkillName(); + this.functionCollection = + new CaseInsensitiveMap>( + Collections.unmodifiableMap( + value.getAll().stream() + .collect(Collectors.toMap(SKFunction::getName, it -> it)))); + } + + @Override + public String getSkillName() { + return skillName; + } + + @Override + public SKFunction getFunction(String functionName) { + SKFunction func = functionCollection.get(functionName.toLowerCase(Locale.ROOT)); + if (func == null) { + throw new FunctionNotFound( + FunctionNotFound.ErrorCodes.FUNCTION_NOT_FOUND, functionName); + } + return func; + } + + /** + * Get function with the given SKFunction type argument. + * + * @param functionName the name of the function to retrieve + * @param clazz The class of the SKFunction parameter type + * @param SKFunction parameter type + * @return The given function + * @throws RuntimeException if the given entry is not of the expected type + */ + @Override + public T getFunction(String functionName, @Nullable Class clazz) { + SKFunction func = getFunction(functionName); + if (clazz == null) { + return (T) func; + } + if (clazz.isInstance(func)) { + return (T) func; + } else { + throw new SkillsNotFoundException( + ErrorCodes.SKILLS_NOT_FOUND, + "Incorrect type requested, expected type of " + + clazz.getName() + + " found class of type " + + func.getClass().getName()); + } + } + + /** + * @return A clone of this collection + */ + @Override + @CheckReturnValue + public FunctionCollection copy() { + return new FunctionCollection(skillName, functionCollection); + } + + /** + * @return An unmodifiable list of all functions + */ + @Override + public List> getAll() { + return Collections.unmodifiableList(new ArrayList<>(functionCollection.values())); + } + + /** + * Add function to the collection overwriting existing function + * + * @param functionName + * @param functionInstance + * @return Collection for fluent callse + */ + public FunctionCollection put(String functionName, SKFunction functionInstance) { + this.functionCollection.put(functionName.toLowerCase(Locale.ROOT), functionInstance); + return this; + } + + /** + * Merge in the given collection to this one, duplicate function names will overwrite + * + * @param value + * @return Collection for fluent calls + */ + public FunctionCollection merge(FunctionCollection value) { + functionCollection.putAll(value.functionCollection); + return this; + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/CodeTokenizer.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/CodeTokenizer.java new file mode 100644 index 0000000000..64b68c2e35 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/CodeTokenizer.java @@ -0,0 +1,228 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine; + +import com.microsoft.semantickernel.templateengine.blocks.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/// +/// Simple tokenizer used for default SK template code language. +/// +/// BNF parsed by TemplateTokenizer: +/// [template] ::= "" | [block] | [block] [template] +/// [block] ::= [sk-block] | [text-block] +/// [sk-block] ::= "{{" [variable] "}}" | "{{" [value] "}}" | "{{" [function-call] "}}" +/// [text-block] ::= [any-char] | [any-char] [text-block] +/// [any-char] ::= any char +/// +/// BNF parsed by CodeTokenizer: +/// [template] ::= "" | [variable] " " [template] | [value] " " [template] | [function-call] " +// " [template] +/// [variable] ::= "$" [valid-name] +/// [value] ::= "'" [text] "'" | '"' [text] '"' +/// [function-call] ::= [function-id] | [function-id] [parameter] +/// [parameter] ::= [variable] | [value] +/// +/// BNF parsed by dedicated blocks +/// [function-id] ::= [valid-name] | [valid-name] "." [valid-name] +/// [valid-name] ::= [valid-symbol] | [valid-symbol] [valid-name] +/// [valid-symbol] ::= [letter] | [digit] | "_" +/// [letter] ::= "a" | "b" ... | "z" | "A" | "B" ... | "Z" +/// [digit] ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" +/// +public class CodeTokenizer { + private enum TokenTypes { + None(0), + Value(1), + Variable(2), + FunctionId(3); + + TokenTypes(int i) {} + } + + public CodeTokenizer() {} + + /// + /// Tokenize a code block, without checking for syntax errors + /// + /// Text to parse + /// A list of blocks + public List tokenize(String text) { + if (text == null) { + return new ArrayList<>(); + } + + // Remove spaces, which are ignored anyway + text = text.trim(); + + // Render NULL to "" + if (text.isEmpty()) { + return Collections.unmodifiableList(new ArrayList<>()); + } + + // Track what type of token we're reading + TokenTypes currentTokenType = TokenTypes.None; + + // Track the content of the current token + StringBuilder currentTokenContent = new StringBuilder(); + + char textValueDelimiter = '\0'; + + List blocks = new ArrayList<>(); + char nextChar = text.charAt(0); + + // Tokens must be separated by spaces, track their presence + boolean spaceSeparatorFound = false; + + // 1 char only edge case + if (text.length() == 1) { + switch (nextChar) { + case Symbols.VarPrefix: + blocks.add(new VarBlock(text)); + break; + + case Symbols.DblQuote: + case Symbols.SglQuote: + blocks.add(new ValBlock(text)); + break; + + default: + blocks.add(new FunctionIdBlock(text)); + break; + } + + return blocks; + } + + boolean skipNextChar = false; + for (int nextCharCursor = 1; nextCharCursor < text.length(); nextCharCursor++) { + char currentChar = nextChar; + nextChar = text.charAt(nextCharCursor); + + if (skipNextChar) { + skipNextChar = false; + continue; + } + + // First char is easy + if (nextCharCursor == 1) { + if (isVarPrefix(currentChar)) { + currentTokenType = TokenTypes.Variable; + } else if (isQuote(currentChar)) { + currentTokenType = TokenTypes.Value; + textValueDelimiter = currentChar; + } else { + currentTokenType = TokenTypes.FunctionId; + } + + currentTokenContent.append(currentChar); + continue; + } + + // While reading a values between quotes + if (currentTokenType == TokenTypes.Value) { + // If the current char is escaping the next special char: + // - skip the current char (escape char) + // - add the next (special char) + // - jump to the one after (to handle "\\" properly) + if (currentChar == Symbols.EscapeChar && CanBeEscaped(nextChar)) { + currentTokenContent.append(nextChar); + skipNextChar = true; + continue; + } + + currentTokenContent.append(currentChar); + + // When we reach the end of the value + if (currentChar == textValueDelimiter) { + blocks.add(new ValBlock(currentTokenContent.toString())); + currentTokenContent = new StringBuilder(); + currentTokenType = TokenTypes.None; + spaceSeparatorFound = false; + } + + continue; + } + + // If we're not between quotes, a space signals the end of the current token + // Note: there might be multiple consecutive spaces + if (IsBlankSpace(currentChar)) { + if (currentTokenType == TokenTypes.Variable) { + blocks.add(new VarBlock(currentTokenContent.toString())); + currentTokenContent = new StringBuilder(); + } else if (currentTokenType == TokenTypes.FunctionId) { + blocks.add(new FunctionIdBlock(currentTokenContent.toString())); + currentTokenContent = new StringBuilder(); + } + + spaceSeparatorFound = true; + currentTokenType = TokenTypes.None; + + continue; + } + + // If we're not inside a quoted value and we're not processing a space + currentTokenContent.append(currentChar); + + if (currentTokenType == TokenTypes.None) { + if (!spaceSeparatorFound) { + throw new TemplateException( + TemplateException.ErrorCodes.SYNTAX_ERROR, + "Tokens must be separated by one space least"); + } + + if (isQuote(currentChar)) { + // A quoted value starts here + currentTokenType = TokenTypes.Value; + textValueDelimiter = currentChar; + } else if (isVarPrefix(currentChar)) { + // A variable starts here + currentTokenType = TokenTypes.Variable; + } else { + // A function Id starts here + currentTokenType = TokenTypes.FunctionId; + } + } + } + + // Capture last token + currentTokenContent.append(nextChar); + switch (currentTokenType) { + case Value: + blocks.add(new ValBlock(currentTokenContent.toString())); + break; + + case Variable: + blocks.add(new VarBlock(currentTokenContent.toString())); + break; + + case FunctionId: + blocks.add(new FunctionIdBlock(currentTokenContent.toString())); + break; + + case None: + throw new TemplateException( + TemplateException.ErrorCodes.SYNTAX_ERROR, + "Tokens must be separated by one space least"); + } + + return blocks; + } + + private static boolean isVarPrefix(char c) { + return (c == Symbols.VarPrefix); + } + + private static boolean IsBlankSpace(char c) { + return Character.isWhitespace(c); + } + + private static boolean isQuote(char c) { + return c == Symbols.DblQuote || c == Symbols.SglQuote; + } + + private static boolean CanBeEscaped(char c) { + return c == Symbols.DblQuote || c == Symbols.SglQuote || c == Symbols.EscapeChar; + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/DefaultPromptTemplateEngine.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/DefaultPromptTemplateEngine.java new file mode 100644 index 0000000000..76855128b3 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/DefaultPromptTemplateEngine.java @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine; + +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.templateengine.blocks.Block; +import com.microsoft.semantickernel.templateengine.blocks.CodeRendering; +import com.microsoft.semantickernel.templateengine.blocks.TextRendering; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/// +/// Given a prompt, that might contain references to variables and functions: +/// - Get the list of references +/// - Resolve each reference +/// - Variable references are resolved using the context variables +/// - Function references are resolved invoking those functions +/// - Functions can be invoked passing in variables +/// - Functions do not receive the context variables, unless specified using a special variable +/// - Functions can be invoked in order and in parallel so the context variables must be +// immutable when invoked within the template +/// +public class DefaultPromptTemplateEngine implements PromptTemplateEngine { + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPromptTemplateEngine.class); + + private final TemplateTokenizer tokenizer; + + public DefaultPromptTemplateEngine() { + tokenizer = new TemplateTokenizer(); + } + + @Override + public List extractBlocks(String templateText) { + return extractBlocks(templateText, true); + } + + public List extractBlocks(String templateText, boolean validate) { + // TODO + // this._log.LogTrace("Extracting blocks from template: {0}", templateText); + List blocks = this.tokenizer.tokenize(templateText); + + if (validate) { + blocks.forEach( + block -> { + if (!block.isValid()) { + throw new TemplateException(TemplateException.ErrorCodes.SYNTAX_ERROR); + } + }); + } + + return blocks; + } + + /// + @Override + public Mono renderAsync(String templateText, SKContext context) { + // TODO + // this._log.LogTrace("Rendering string template: {0}", templateText); + List blocks = this.extractBlocks(templateText); + return this.renderAsync(blocks, context); + } + + /// + public Mono renderAsync(List blocks, SKContext context) { + return Flux.fromIterable(blocks) + .concatMap( + block -> { + if (block instanceof TextRendering) { + return Mono.just( + ((TextRendering) block).render(context.getVariables())); + } else if (block instanceof CodeRendering) { + return ((CodeRendering) block).renderCodeAsync(context); + } else { + String message = + "Unexpected block type, the block doesn't have a rendering" + + " method"; + LOGGER.error(message); + return Mono.error( + new TemplateException( + TemplateException.ErrorCodes.UNEXPECTED_BLOCK_TYPE, + message)); + } + }) + .collectList() + .map( + values -> { + StringBuilder sb = new StringBuilder(); + values.forEach(sb::append); + return sb.toString(); + }); + /* + this._log.LogTrace("Rendering list of {0} blocks", blocks.Count); + var result = new StringBuilder(); + foreach (var block in blocks) + { + switch (block) + { + case ITextRendering staticBlock: + result.Append(staticBlock.Render(context.Variables)); + break; + + case ICodeRendering dynamicBlock: + result.Append(await dynamicBlock.RenderCodeAsync(context)); + break; + + default: + const string error = "Unexpected block type, the block doesn't have a rendering method"; + this._log.LogError(error); + throw new TemplateException(TemplateException.ErrorCodes.UNEXPECTED_BLOCK_TYPE, error); + } + } + + // TODO: remove PII, allow tracing prompts differently + this._log.LogDebug("Rendered prompt: {0}", result); + return result.ToString(); + + */ + } + + public static final class Builder implements PromptTemplateEngine.Builder { + @Override + public PromptTemplateEngine build() { + return new DefaultPromptTemplateEngine(); + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/TemplateException.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/TemplateException.java new file mode 100644 index 0000000000..9261b9aa72 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/TemplateException.java @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine; + +import com.microsoft.semantickernel.SKException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class TemplateException extends SKException { + + @Nonnull private final ErrorCodes errorCode; + + /** + * Initializes a new instance of the {@code TemplateException} class with a provided error code. + * + * @param error The error code. + */ + public TemplateException(@Nonnull ErrorCodes error) { + this(error, null, null); + } + + /** + * Initializes a new instance of the {@code TemplateException} class with a provided error code. + * + * @param errorCode The error code. + * @param message The exception message. + */ + public TemplateException(@Nonnull ErrorCodes errorCode, @Nullable String message) { + this(errorCode, message, null); + } + + /** + * Initializes a new instance of the {@code TemplateException} class with a provided error code. + * + * @param errorCode The error code. + * @param message The exception message. + * @param innerException The exception that is the cause of the current exception. + */ + public TemplateException( + @Nonnull ErrorCodes errorCode, + @Nullable String message, + @Nullable Throwable innerException) { + super(formatDefaultMessage(errorCode.getMessage(), message), innerException); + this.errorCode = errorCode; + } + + // spotless:off + + /** + *

+ * Gets the error code for this exception. + *

+ */ + //spotless:on + public ErrorCodes getErrorCode() { + return errorCode; + } + + // spotless:off + + /** + *

+ * Translate the error code into a default message. + *

+ */ + //spotless:on + private static String getDefaultMessage( + @Nonnull ErrorCodes errorCode, @Nullable String message) { + return String.format("%s: %s", errorCode.getMessage(), message); + } + + // spotless:off + + /** + *

+ * Error codes for {@code TemplateException}. + *

+ */ + //spotless:on + public enum ErrorCodes { + + // spotless:off + /** + *

+ * Unknown error. + *

+ */ + //spotless:on + UNKNOWN_ERROR("Unknown error"), + + // spotless:off + /** + *

+ * Syntax error, the template syntax used is not valid. + *

+ */ + //spotless:on + SYNTAX_ERROR("Syntax error, the template syntax used is not valid"), + + // spotless:off + /** + *

+ * The block type produced be the tokenizer was not expected. + *

+ */ + UNEXPECTED_BLOCK_TYPE("The block type produced be the tokenizer was not expected"), + + //spotless:off + /** + *

+ * The template requires an unknown function. + *

+ */ + //spotless:on + FUNCTION_NOT_FOUND("The template requires an unknown function"), + + // spotless:off + /** + *

+ * The template execution failed, e.g. a function call threw an exception. + *

+ */ + //spotless:on + RUNTIME_ERROR("The template execution failed, e.g. a function call threw an exception"); + + private final String message; + + ErrorCodes(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/TemplateTokenizer.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/TemplateTokenizer.java new file mode 100644 index 0000000000..ee4bc04488 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/TemplateTokenizer.java @@ -0,0 +1,224 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine; + +import com.microsoft.semantickernel.templateengine.blocks.Block; +import com.microsoft.semantickernel.templateengine.blocks.CodeBlock; +import com.microsoft.semantickernel.templateengine.blocks.Symbols; +import com.microsoft.semantickernel.templateengine.blocks.TextBlock; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/// +/// Simple tokenizer used for default SK template language. +/// +/// BNF parsed by TemplateTokenizer: +/// [template] ::= "" | [block] | [block] [template] +/// [block] ::= [sk-block] | [text-block] +/// [sk-block] ::= "{{" [variable] "}}" | "{{" [value] "}}" | "{{" [function-call] "}}" +/// [text-block] ::= [any-char] | [any-char] [text-block] +/// [any-char] ::= any char +/// +/// BNF parsed by CodeTokenizer: +/// [template] ::= "" | [variable] " " [template] | [value] " " [template] | [function-call] " +// " [template] +/// [variable] ::= "$" [valid-name] +/// [value] ::= "'" [text] "'" | '"' [text] '"' +/// [function-call] ::= [function-id] | [function-id] [parameter] +/// [parameter] ::= [variable] | [value] +/// +/// BNF parsed by dedicated blocks +/// [function-id] ::= [valid-name] | [valid-name] "." [valid-name] +/// [valid-name] ::= [valid-symbol] | [valid-symbol] [valid-name] +/// [valid-symbol] ::= [letter] | [digit] | "_" +/// [letter] ::= "a" | "b" ... | "z" | "A" | "B" ... | "Z" +/// [digit] ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" +/// +public class TemplateTokenizer { + /* + /// + /// Create a new instance of SK tokenizer + /// + /// + public TemplateTokenizer(ILogger? log = null) + { + this._log = log ?? NullLogger.Instance; + this._codeTokenizer = new CodeTokenizer(this._log); + } + */ + /// + /// Extract blocks from the given text + /// + /// Text to parse + /// List of blocks found in the text + public List tokenize(String text) { + // An empty block consists of 4 chars: "{{}}" + int EMPTY_CODE_BLOCK_LENGTH = 4; + // A block shorter than 5 chars is either empty or invalid, e.g. "{{ }}" and "{{$}}" + int MIN_CODE_BLOCK_LENGTH = EMPTY_CODE_BLOCK_LENGTH + 1; + + // Render NULL to "" + if (text == null || text.isEmpty()) { + return Collections.singletonList(new TextBlock("")); + } + + // If the template is "empty" return the content as a text block + if (text.length() < MIN_CODE_BLOCK_LENGTH) { + return Collections.singletonList(new TextBlock(text)); + } + + List blocks = new ArrayList<>(); + + int endOfLastBlock = 0; + + int blockStartPos = 0; + boolean blockStartFound = false; + + boolean insideTextValue = false; + char textValueDelimiter = '\0'; + + boolean skipNextChar = false; + + char nextChar = text.charAt(0); + for (int nextCharCursor = 1; nextCharCursor < text.length(); nextCharCursor++) { + int currentCharPos = nextCharCursor - 1; + int cursor = nextCharCursor; + char currentChar = nextChar; + nextChar = text.charAt(nextCharCursor); + + if (skipNextChar) { + skipNextChar = false; + continue; + } + + // When "{{" is found outside a value + // Note: "{{ {{x}}" => ["{{ ", "{{x}}"] + if (!insideTextValue + && currentChar == Symbols.BlockStarter + && nextChar == Symbols.BlockStarter) { + // A block starts at the first "{" + blockStartPos = currentCharPos; + blockStartFound = true; + } + + // After having found '{{' + if (blockStartFound) { + // While inside a text value, when the end quote is found + if (insideTextValue) { + if (currentChar == Symbols.EscapeChar && canBeEscaped(nextChar)) { + skipNextChar = true; + continue; + } + + if (currentChar == textValueDelimiter) { + insideTextValue = false; + } + } else { + // A value starts here + if (isQuote(currentChar)) { + insideTextValue = true; + textValueDelimiter = currentChar; + } + // If the block ends here + else if (currentChar == Symbols.BlockEnder && nextChar == Symbols.BlockEnder) { + // If there is plain text between the current var/val/code block and the + // previous one, capture that as a TextBlock + if (blockStartPos > endOfLastBlock) { + blocks.add(new TextBlock(text, endOfLastBlock, blockStartPos)); + } + + // Extract raw block + String contentWithDelimiters = subStr(text, blockStartPos, cursor + 1); + + // Remove "{{" and "}}" delimiters and trim empty chars + String contentWithoutDelimiters = + contentWithDelimiters + .substring(2, contentWithDelimiters.length() - 2) + .trim(); + + if (contentWithoutDelimiters.length() == 0) { + // If what is left is empty, consider the raw block a Text Block + blocks.add(new TextBlock(contentWithDelimiters)); + } else { + List codeBlocks = + this.codeTokenizer.tokenize(contentWithoutDelimiters); + + switch (codeBlocks.get(0).getType()) { + case Variable: + if (codeBlocks.size() > 1) { + throw new TemplateException( + TemplateException.ErrorCodes.SYNTAX_ERROR, + "Invalid token detected after the variable: " + + contentWithoutDelimiters); + } + + blocks.add(codeBlocks.get(0)); + break; + + case Value: + if (codeBlocks.size() > 1) { + throw new TemplateException( + TemplateException.ErrorCodes.SYNTAX_ERROR, + "Invalid token detected after the value: " + + contentWithoutDelimiters); + } + + blocks.add(codeBlocks.get(0)); + break; + + case FunctionId: + if (codeBlocks.size() > 2) { + throw new TemplateException( + TemplateException.ErrorCodes.SYNTAX_ERROR, + "Functions support only one parameter: " + + contentWithoutDelimiters); + } + + blocks.add(new CodeBlock(codeBlocks, contentWithoutDelimiters)); + break; + + case Code: + case Text: + case Undefined: + default: + throw new TemplateException( + TemplateException.ErrorCodes.UNEXPECTED_BLOCK_TYPE, + "Code tokenizer returned an incorrect first token type " + + codeBlocks.get(0).getType()); + } + } + + endOfLastBlock = cursor + 1; + blockStartFound = false; + } + } + } + } + + // If there is something left after the last block, capture it as a TextBlock + if (endOfLastBlock < text.length()) { + blocks.add(new TextBlock(text, endOfLastBlock, text.length())); + } + + return Collections.unmodifiableList(blocks); + } + + /* + #region private ================================================================================ + + private readonly ILogger _log; + */ + private final CodeTokenizer codeTokenizer = new CodeTokenizer(); + + private static String subStr(String text, int startIndex, int stopIndex) { + return text.substring(startIndex, stopIndex); + } + + private static boolean isQuote(char c) { + return c == Symbols.DblQuote || c == Symbols.SglQuote; + } + + private static boolean canBeEscaped(char c) { + return c == Symbols.DblQuote || c == Symbols.SglQuote || c == Symbols.EscapeChar; + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/CodeBlock.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/CodeBlock.java new file mode 100644 index 0000000000..514f21750b --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/CodeBlock.java @@ -0,0 +1,139 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.orchestration.SKFunction; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection; +import com.microsoft.semantickernel.templateengine.TemplateException; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +public final class CodeBlock extends Block implements CodeRendering { + + private static final Logger LOGGER = LoggerFactory.getLogger(CodeBlock.class); + private final List tokens; + + public CodeBlock(List tokens, String content) { + super(content, BlockTypes.Code); + this.tokens = Collections.unmodifiableList(tokens); + } + + @Override + public boolean isValid() { + Optional invalid = tokens.stream().filter(token -> !token.isValid()).findFirst(); + if (invalid.isPresent()) { + LOGGER.error("Invalid block" + invalid.get().getContent()); + return false; + } + + if (this.tokens.size() > 1) { + if (this.tokens.get(0).getType() != BlockTypes.FunctionId) { + LOGGER.error("Unexpected second token found: " + this.tokens.get(1).getContent()); + return false; + } + + if (this.tokens.get(1).getType() != BlockTypes.Value + && this.tokens.get(1).getType() != BlockTypes.Variable) { + LOGGER.error("Functions support only one parameter"); + return false; + } + } + + if (this.tokens.size() > 2) { + LOGGER.error("Unexpected second token found: " + this.tokens.get(1).getContent()); + return false; + } + + return true; + } + + @Override + public Mono renderCodeAsync(SKContext context) { + if (!this.isValid()) { + throw new TemplateException(TemplateException.ErrorCodes.SYNTAX_ERROR); + } + + // this.Log.LogTrace("Rendering code: `{0}`", this.Content); + + switch (this.tokens.get(0).getType()) { + case Value: + case Variable: + return Mono.just( + ((TextRendering) this.tokens.get(0)).render(context.getVariables())); + + case FunctionId: + return this.renderFunctionCallAsync((FunctionIdBlock) this.tokens.get(0), context); + + case Undefined: + case Text: + case Code: + default: + throw new RuntimeException("Unknown type"); + } + } + + private Mono renderFunctionCallAsync(FunctionIdBlock fBlock, SKContext context) { + // context.ThrowIfSkillCollectionNotSet(); + SKFunction function = this.getFunctionFromSkillCollection(context.getSkills(), fBlock); + if (function == null) { + // var errorMsg = $ "Function `{fBlock.Content}` not found"; + // this.Log.LogError(errorMsg); + throw new RuntimeException("Function not found"); + } + + ContextVariables variables = context.getVariables(); + + // If the code syntax is {{functionName $varName}} use $varName instead of $input + // If the code syntax is {{functionName 'value'}} use "value" instead of $input + if (this.tokens.size() > 1) { + // TODO: PII + // this.Log.LogTrace("Passing variable/value: `{0}`", this._tokens[1].Content); + String content = this.tokens.get(1).getContent(); + String input = ((TextRendering) this.tokens.get(1)).render(variables); + if (content.startsWith("$")) { + String varName = content.substring(1); + variables = variables.writableClone().setVariable(varName, input); + } else variables = variables.writableClone().update(input); + } + + Mono result = + function.invokeWithCustomInputAsync( + variables, context.getSemanticMemory(), context.getSkills()); + + return result.map( + it -> { + return it.getResult(); + }); + } + + @Nullable + private SKFunction getFunctionFromSkillCollection( + ReadOnlySkillCollection skills, FunctionIdBlock fBlock) { + String skillName = fBlock.getSkillName(); + // Function in the global skill + if ((skillName == null || skillName.isEmpty()) + && skills.hasFunction(fBlock.getFunctionName())) { + SKFunction function = skills.getFunction(fBlock.getFunctionName(), SKFunction.class); + return function; + } + + // Function within a specific skill + if (!(skillName == null || skillName.isEmpty())) { + + ReadOnlyFunctionCollection skill = skills.getFunctions(fBlock.getSkillName()); + + if (skill != null) { + return skill.getFunction(fBlock.getFunctionName()); + } + } + + return null; + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/CodeRendering.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/CodeRendering.java new file mode 100644 index 0000000000..a4e4ffe00e --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/CodeRendering.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +import com.microsoft.semantickernel.orchestration.SKContext; +import reactor.core.publisher.Mono; + +/** Interface of dynamic blocks that need async IO to be rendered. */ +public interface CodeRendering { + /** + * Render the block using the given context, potentially using external I/O. + * + * @param context SK execution context + * @return Rendered content + */ + Mono renderCodeAsync(SKContext context); +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/FunctionIdBlock.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/FunctionIdBlock.java new file mode 100644 index 0000000000..32e0aa5882 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/FunctionIdBlock.java @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +import com.microsoft.semantickernel.orchestration.ContextVariables; +import javax.annotation.Nullable; + +public final class FunctionIdBlock extends Block implements TextRendering { + private final String skillName; + + private final String functionName; + + public FunctionIdBlock(String content) { + super(content, BlockTypes.FunctionId); + + String[] functionNameParts = this.getContent().split("\\.", -1); + if (functionNameParts.length > 2) { + throw new RuntimeException( + "A function name can contain at most one dot separating the skill name from the" + + " function name"); + } + + if (functionNameParts.length == 2) { + this.skillName = functionNameParts[0]; + this.functionName = functionNameParts[1]; + return; + } + + this.functionName = this.getContent(); + this.skillName = ""; + } + + @Override + @Nullable + public String render(ContextVariables variables) { + return this.getContent(); + } + + @Override + public boolean isValid() { + if (!this.getContent().matches("^[a-zA-Z0-9_.]*$")) { + // errorMsg = "The function identifier is empty"; + return false; + } + + if (hasMoreThanOneDot(this.getContent())) { + // errorMsg = "The function identifier can contain max one '.' char separating skill + // name from function name"; + return false; + } + + // errorMsg = ""; + return true; + } + + private static boolean hasMoreThanOneDot(String value) { + if (value == null || value.length() < 2) { + return false; + } + + return value.matches("^.*\\..*\\..*$"); + } + + public String getSkillName() { + return skillName; + } + + public String getFunctionName() { + return functionName; + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/Symbols.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/Symbols.java new file mode 100644 index 0000000000..994d2c113f --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/Symbols.java @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +public class Symbols { + public static final char BlockStarter = '{'; + public static final char BlockEnder = '}'; + + public static final char VarPrefix = '$'; + + public static final char DblQuote = '"'; + public static final char SglQuote = '\''; + public static final char EscapeChar = '\\'; + + public static final char Space = ' '; + public static final char Tab = '\t'; + public static final char NewLine = '\n'; + public static final char CarriageReturn = '\r'; +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/TextBlock.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/TextBlock.java new file mode 100644 index 0000000000..5760f3a3ad --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/TextBlock.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +import com.microsoft.semantickernel.orchestration.ContextVariables; + +public final class TextBlock extends Block implements TextRendering { + + public TextBlock(String text) { + super(text, BlockTypes.Text); + } + + @Override + public boolean isValid() { + return true; + } + + @Override + public String render(ContextVariables variables) { + return super.getContent(); + } + + public TextBlock(String text, int startIndex, int stopIndex) { + super(text.substring(startIndex, stopIndex), BlockTypes.Text); + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/TextRendering.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/TextRendering.java new file mode 100644 index 0000000000..f9440f94ec --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/TextRendering.java @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +import com.microsoft.semantickernel.orchestration.ContextVariables; +import javax.annotation.Nullable; + +/// +/// Interface of static blocks that don't need async IO to be rendered. +/// +public interface TextRendering { + /// + /// Render the block using only the given variables. + /// + /// Optional variables used to render the block + /// Rendered content + @Nullable + String render(ContextVariables variables); +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/ValBlock.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/ValBlock.java new file mode 100644 index 0000000000..bb57680d10 --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/ValBlock.java @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +import com.microsoft.semantickernel.orchestration.ContextVariables; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.util.annotation.Nullable; + +public final class ValBlock extends Block implements TextRendering { + + private static final Logger LOGGER = LoggerFactory.getLogger(ValBlock.class); + + // Cache the first and last char + private char first = '\0'; + private char last = '\0'; + + // Content, excluding start/end quote chars + private String value = ""; + + public ValBlock(String quotedValue) { + super(quotedValue.trim(), BlockTypes.Value); + + if (this.getContent().length() < 2) { + LOGGER.error("A value must have single quotes or double quotes on both sides"); + return; + } + + this.first = this.getContent().charAt(0); + this.last = this.getContent().charAt(getContent().length() - 1); + this.value = this.getContent().substring(1, this.getContent().length() - 2); + } + + @Override + @Nullable + public String render(ContextVariables variables) { + return value; + } + + @Override + public boolean isValid() { + // Content includes the quotes, so it must be at least 2 chars long + if (this.getContent().length() < 2) { + LOGGER.error("A value must have single quotes or double quotes on both sides"); + return false; + } + + // Check if delimiting chars are consistent + if (first != last) { + LOGGER.error( + "A value must be defined using either single quotes or double quotes, not" + + " both"); + return false; + } + + return true; + } + + public static boolean hasValPrefix(@Nullable String text) { + return text != null + && text.length() > 0 + && (text.charAt(0) == Symbols.DblQuote || text.charAt(0) == Symbols.SglQuote); + } +} diff --git a/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/VarBlock.java b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/VarBlock.java new file mode 100644 index 0000000000..33d115745b --- /dev/null +++ b/java/semantickernel-core/src/main/java/com/microsoft/semantickernel/templateengine/blocks/VarBlock.java @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.templateengine.blocks; + +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.templateengine.TemplateException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class VarBlock extends Block implements TextRendering { + + private static final Logger LOGGER = LoggerFactory.getLogger(VarBlock.class); + private final String name; + + public VarBlock(String content) { + super(content, BlockTypes.Variable); + + if (content.length() < 2) { + LOGGER.error("The variable name is empty"); + } + + this.name = content.substring(1); + } + + @Override + public String render(ContextVariables variables) { + if (variables == null) { + return ""; + } + + if (name == null || name.isEmpty()) { + throw new TemplateException( + TemplateException.ErrorCodes.SYNTAX_ERROR, + "Variable rendering failed, the variable name is empty"); + } + + String value = variables.asMap().get(name); + + if (value == null) { + + LOGGER.warn("Variable `{}{}` not found", Symbols.VarPrefix, name); + } + + return value != null ? value : ""; + } + + @Override + public boolean isValid() { + if (getContent() == null || getContent().isEmpty()) { + LOGGER.error( + "A variable must start with the symbol {} and have a name", Symbols.VarPrefix); + return false; + } + + if (getContent().charAt(0) != Symbols.VarPrefix) { + LOGGER.error("A variable must start with the symbol {}", Symbols.VarPrefix); + return false; + } + + if (getContent().length() < 2) { + LOGGER.error("The variable name is empty"); + return false; + } + + if (!name.matches("^[a-zA-Z0-9_]*$")) { + LOGGER.error( + "The variable name '{}' contains invalid characters. " + + "Only alphanumeric chars and underscore are allowed.", + name); + return false; + } + + return true; + } + + public String getName() { + return name; + } +} diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.Kernel$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.Kernel$Builder new file mode 100644 index 0000000000..e73ba8ab01 --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.Kernel$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.DefaultKernel$Builder \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.builders.FunctionBuilders b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.builders.FunctionBuilders new file mode 100644 index 0000000000..28eefc6d44 --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.builders.FunctionBuilders @@ -0,0 +1 @@ +com.microsoft.semantickernel.SkFunctionBuilders \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.memory.MemoryStore$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.memory.MemoryStore$Builder new file mode 100644 index 0000000000..9fbed01682 --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.memory.MemoryStore$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.memory.VolatileMemoryStore$Builder \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.ContextVariables$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.ContextVariables$Builder new file mode 100644 index 0000000000..3c63e96e4f --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.ContextVariables$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.orchestration.DefaultContextVariables$Builder \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.SKContext$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.SKContext$Builder new file mode 100644 index 0000000000..1d200d14da --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.SKContext$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.orchestration.DefaultSKContext$Builder \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.WritableContextVariables$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.WritableContextVariables$Builder new file mode 100644 index 0000000000..c04843d998 --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.orchestration.WritableContextVariables$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.orchestration.DefaultContextVariables$WritableBuilder \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.semanticfunctions.PromptTemplate$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.semanticfunctions.PromptTemplate$Builder new file mode 100644 index 0000000000..5617f90e8d --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.semanticfunctions.PromptTemplate$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.semanticfunctions.DefaultPromptTemplate$Builder \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection$Builder new file mode 100644 index 0000000000..5619c9c53a --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection$Builder \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.templateengine.PromptTemplateEngine$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.templateengine.PromptTemplateEngine$Builder new file mode 100644 index 0000000000..f80254e2d7 --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.templateengine.PromptTemplateEngine$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.templateengine.DefaultPromptTemplateEngine$Builder \ No newline at end of file diff --git a/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.textcompletion.CompletionSKFunction$Builder b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.textcompletion.CompletionSKFunction$Builder new file mode 100644 index 0000000000..354182690a --- /dev/null +++ b/java/semantickernel-core/src/main/resources/META-INF/services/com.microsoft.semantickernel.textcompletion.CompletionSKFunction$Builder @@ -0,0 +1 @@ +com.microsoft.semantickernel.orchestration.DefaultCompletionSKFunction$Builder \ No newline at end of file diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/AiServiceRegistryTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/AiServiceRegistryTest.java new file mode 100644 index 0000000000..5f3e002911 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/AiServiceRegistryTest.java @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.CompletionType; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import reactor.core.publisher.Flux; + +public class AiServiceRegistryTest { + + @Test + public void registeredServicesAreAvailableInTheKernel() { + runFunctionWithAiService(true); + } + + @Test + public void singleServiceIsRegisteredAsDefault() { + runFunctionWithAiService(false); + } + + private static void runFunctionWithAiService(boolean setAsDefault) { + KernelConfig config = SKBuilders.kernelConfig().build(); + TextCompletion service = Mockito.mock(TextCompletion.class); + Mockito.when(service.defaultCompletionType()).thenReturn(CompletionType.STREAMING); + Mockito.when(service.completeStreamAsync(Mockito.any(), Mockito.any())) + .thenReturn(Flux.just("foo")); + + Kernel kernel = + SKBuilders.kernel() + .withAIService("a-service", service, setAsDefault, TextCompletion.class) + .withConfiguration(config) + .build(); + + Assertions.assertSame(kernel.getService("a-service", TextCompletion.class), service); + + CompletionSKFunction function = + kernel.importSkillFromDirectory("FunSkill", "../../samples/skills") + .getFunction("joke", CompletionSKFunction.class); + + function.invokeAsync("time travel to dinosaur age").block(); + + Mockito.verify(service, Mockito.times(1)).completeStreamAsync(Mockito.any(), Mockito.any()); + } + + @Test + public void noServiceThrowsAnError() { + KernelConfig config = SKBuilders.kernelConfig().build(); + + Kernel kernel = SKBuilders.kernel().withConfiguration(config).build(); + + Assertions.assertThrows( + KernelException.class, () -> kernel.getService("a-service", TextCompletion.class)); + + Assertions.assertThrows( + KernelException.class, + () -> { + CompletionSKFunction function = + kernel.importSkillFromDirectory("FunSkill", "../../samples/skills") + .getFunction("joke", CompletionSKFunction.class); + + function.invokeAsync("time travel to dinosaur age").block(); + }); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/DefaultKernelTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/DefaultKernelTest.java new file mode 100644 index 0000000000..ac1edb9098 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/DefaultKernelTest.java @@ -0,0 +1,405 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.ChatChoice; +import com.azure.ai.openai.models.ChatCompletions; +import com.azure.ai.openai.models.ChatCompletionsOptions; +import com.azure.ai.openai.models.ChatMessage; +import com.azure.ai.openai.models.Choice; +import com.azure.ai.openai.models.Completions; +import com.azure.ai.openai.models.CompletionsOptions; +import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatcher; +import org.mockito.Mockito; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; +import reactor.util.function.Tuple3; +import reactor.util.function.Tuples; + +public class DefaultKernelTest { + + @Test + void contextVariableTest() { + + String model = "a-model"; + + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient( + Tuples.of("A", "a"), Tuples.of("user: Aauser: B", "b")); + + Kernel kernel = buildKernel(model, client); + + String prompt = "{{$history}}user: {{$user_input}}\n"; + + CompletionSKFunction chat = + kernel.getSemanticFunctionBuilder() + .withKernel(kernel) + .withPromptTemplate(prompt) + .withFunctionName("ChatBot") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0.7, 0.5, 0, 0, 2000)) + .build(); + + SKContext readOnlySkContext = + SKBuilders.context() + .withKernel(kernel) + .build() + .setVariable("history", "") + .setVariable("user_input", "A"); + + SKContext result = chat.invokeAsync(readOnlySkContext, null).block(); + + if (result == null) { + Assertions.fail(); + } + + Assertions.assertEquals("a", result.getResult()); + + result = + result.appendToVariable("history", "user: A" + result.getResult()) + .setVariable("user_input", "B"); + + result = chat.invokeAsync(result, null).block(); + if (result == null) { + Assertions.fail(); + } + Assertions.assertEquals("b", result.getResult()); + } + + @Test + void tellAJoke() { + String expectedResponse = "a result joke"; + OpenAIAsyncClient client = mockCompletionOpenAIAsyncClient("WRITE", expectedResponse); + String model = "a-model-name"; + Kernel kernel = buildKernel(model, client); + + CompletionSKFunction function = + kernel.importSkillFromDirectory("FunSkill", "../../samples/skills") + .getFunction("joke", CompletionSKFunction.class); + + Mono mono = function.invokeAsync("time travel to dinosaur age"); + SKContext result = mono.block(); + + String expected = + "WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE TOPIC BELOW\n" + + "\n" + + "JOKE MUST BE:\n" + + "- G RATED\n" + + "- WORKPLACE/FAMILY SAFE\n" + + "NO SEXISM, RACISM OR OTHER BIAS/BIGOTRY\n" + + "\n" + + "BE CREATIVE AND FUNNY. I WANT TO LAUGH.\n" + + "Incorporate the style suggestion, if provided: \n" + + "+++++\n" + + "\n" + + "time travel to dinosaur age\n" + + "+++++\n"; + + assertCompletionsWasCalledWithModelAndText(client, model, expected); + + assertTheResultEquals(result, expectedResponse); + } + + public static Kernel buildKernel(String model, OpenAIAsyncClient client) { + TextCompletion textCompletion = new OpenAITextCompletion(client, model); + + return SKBuilders.kernel().withDefaultAIService(textCompletion).build(); + } + + private static OpenAIAsyncClient mockCompletionOpenAIAsyncClient(String arg, String response) { + List> responses = + Collections.singletonList(Tuples.of(arg, response)); + + return mockCompletionOpenAIAsyncClient(responses.toArray(new Tuple2[0])); + } + + /* + * Mocks a Text Completion client where if the prompt matches it will return the + * first arg it will return the response, + * i.e: + * + * mockCompletionOpenAIAsyncClient( + * List.<>of( + * Tuples.of("Tell me a joke", "This is a joke") + * ) + * ); + * + * This if the client is prompted with "Tell me a joke", the mocked client would + * respond with "This is a joke" + */ + public static OpenAIAsyncClient mockCompletionOpenAIAsyncClient( + Tuple2... responses) { + + List, String, Consumer>> matchers = + Arrays.stream(responses) + .map( + response -> + Tuples + ., String, Consumer> + of( + arg -> + arg.contains( + response.getT1()), + response.getT2(), + (arg) -> {})) + .collect(Collectors.toList()); + + return DefaultKernelTest.mockCompletionOpenAIAsyncClientMatchAndAssert( + matchers.toArray(new Tuple3[0])); + } + + public static OpenAIAsyncClient mockCompletionOpenAIAsyncClientMatch( + Tuple2, String>... responses) { + + Tuple3[] withAssert = + Arrays.stream(responses) + .map( + spec -> + Tuples + ., String, Consumer> + of(spec.getT1(), spec.getT2(), arg -> {})) + .collect(Collectors.toList()) + .toArray(new Tuple3[0]); + + return mockCompletionOpenAIAsyncClientMatchAndAssert(withAssert); + } + + public static OpenAIAsyncClient mockCompletionOpenAIAsyncClientMatchAndAssert( + Tuple3, String, Consumer>... responses) { + OpenAIAsyncClient openAIAsyncClient = Mockito.mock(OpenAIAsyncClient.class); + + for (Tuple3, String, Consumer> response : responses) { + mockChatCompletionResponse(openAIAsyncClient, response); + mockChatCompletionResponseStreaming(openAIAsyncClient, response); + mockTextCompletionResponse(openAIAsyncClient, response); + mockTextCompletionResponseStreaming(openAIAsyncClient, response); + } + return openAIAsyncClient; + } + + private static void mockTextCompletionResponse( + OpenAIAsyncClient openAIAsyncClient, + Tuple3, String, Consumer> response) { + Choice choice = Mockito.mock(Choice.class); + Mockito.when(choice.getText()).thenReturn(response.getT2()); + Completions completions = Mockito.mock(Completions.class); + Mockito.when(completions.getChoices()).thenReturn(Collections.singletonList(choice)); + Mockito.when(completions.getId()).thenReturn(UUID.randomUUID().toString()); + + Mockito.when( + openAIAsyncClient.getCompletions( + Mockito.any(String.class), + Mockito.argThat( + it -> response.getT1().matches(it.getPrompt().get(0))))) + .then( + (arg) -> { + response.getT3() + .accept( + ((CompletionsOptions) arg.getArgument(1)) + .getPrompt() + .get(0)); + return Mono.just(completions); + }) + .thenReturn(Mono.just(completions)); + + Mockito.when( + openAIAsyncClient.getCompletions( + Mockito.any(String.class), + Mockito.argThat(it -> response.getT1().matches(it)))) + .then( + (arg) -> { + response.getT3() + .accept( + ((CompletionsOptions) arg.getArgument(1)) + .getPrompt() + .get(0)); + return Mono.just(completions); + }) + .thenReturn(Mono.just(completions)); + } + + private static void mockTextCompletionResponseStreaming( + OpenAIAsyncClient openAIAsyncClient, + Tuple3, String, Consumer> response) { + Choice choice = Mockito.mock(Choice.class); + Mockito.when(choice.getText()).thenReturn(response.getT2()); + Completions completions = Mockito.mock(Completions.class); + Mockito.when(completions.getChoices()).thenReturn(Collections.singletonList(choice)); + Mockito.when(completions.getId()).thenReturn(UUID.randomUUID().toString()); + + Mockito.when( + openAIAsyncClient.getCompletionsStream( + Mockito.any(String.class), + Mockito.argThat( + it -> response.getT1().matches(it.getPrompt().get(0))))) + .then( + (arg) -> { + response.getT3() + .accept( + ((CompletionsOptions) arg.getArgument(1)) + .getPrompt() + .get(0)); + return Flux.just(completions); + }) + .thenReturn(Flux.just(completions)); + + Mockito.when( + openAIAsyncClient.getCompletionsStream( + Mockito.any(String.class), + Mockito.argThat( + it -> + response.getT1() + .matches( + it.getPrompt() + .get( + it.getPrompt() + .size() + - 1))))) + .then( + (arg) -> { + response.getT3() + .accept( + ((CompletionsOptions) arg.getArgument(1)) + .getPrompt() + .get(0)); + return Flux.just(completions); + }) + .thenReturn(Flux.just(completions)); + } + + private static void mockChatCompletionResponse( + OpenAIAsyncClient openAIAsyncClient, + Tuple3, String, Consumer> response) { + ChatMessage message = Mockito.mock(ChatMessage.class); + Mockito.when(message.getContent()).thenReturn(response.getT2()); + ChatChoice chatChoice = Mockito.mock(ChatChoice.class); + Mockito.when(chatChoice.getMessage()).thenReturn(message); + ChatCompletions chatCompletions = Mockito.mock(ChatCompletions.class); + + Mockito.when(chatCompletions.getChoices()) + .thenReturn(Collections.singletonList(chatChoice)); + Mockito.when(chatCompletions.getId()).thenReturn(UUID.randomUUID().toString()); + + ArgumentMatcher completionMatcher = + chatCompletionsOptions -> + response.getT1() + .matches( + chatCompletionsOptions.getMessages().stream() + .map(ChatMessage::getContent) + .collect(Collectors.joining("\n"))); + + Mockito.when( + openAIAsyncClient.getChatCompletions( + Mockito.any(String.class), Mockito.argThat(completionMatcher))) + .thenReturn(Mono.just(chatCompletions)); + } + + private static void mockChatCompletionResponseStreaming( + OpenAIAsyncClient openAIAsyncClient, + Tuple3, String, Consumer> response) { + + String responseStr = response.getT2(); + + String[] responseArray = + new String[] { + responseStr.substring(0, responseStr.length() / 2), + responseStr.substring(responseStr.length() / 2) + }; + + List choices = + Arrays.stream(responseArray) + .map( + r -> { + ChatMessage message = Mockito.mock(ChatMessage.class); + Mockito.when(message.getContent()).thenReturn(r); + ChatChoice chatChoice = Mockito.mock(ChatChoice.class); + Mockito.when(chatChoice.getDelta()).thenReturn(message); + Mockito.when(chatChoice.getMessage()).thenReturn(message); + return chatChoice; + }) + .collect(Collectors.toList()); + + ChatCompletions chatCompletions = Mockito.mock(ChatCompletions.class); + Mockito.when(chatCompletions.getChoices()).thenReturn(choices); + Mockito.when(chatCompletions.getId()).thenReturn(UUID.randomUUID().toString()); + + ArgumentMatcher completionMatcher = + chatCompletionsOptions -> + response.getT1() + .matches( + chatCompletionsOptions.getMessages().stream() + .map(ChatMessage::getContent) + .collect(Collectors.joining("\n"))); + + Mockito.when( + openAIAsyncClient.getChatCompletionsStream( + Mockito.any(String.class), Mockito.argThat(completionMatcher))) + .thenReturn(Flux.just(chatCompletions)); + } + + @Test + void inlineFunctionTest() { + + String model = "a-model"; + + String expectedResponse = "foo"; + OpenAIAsyncClient openAIAsyncClient = + mockCompletionOpenAIAsyncClient("block", expectedResponse); + + Kernel kernel = buildKernel(model, openAIAsyncClient); + + String text = "A block of text\n"; + + String prompt = "{{$input}}\n" + "Summarize the content above."; + + CompletionSKFunction summarize = + SKBuilders.completionFunctions() + .withKernel(kernel) + .withPromptTemplate(prompt) + .withFunctionName("summarize") + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0.2, 0.5, 0, 0, 2000)) + .build(); + + Mono mono = summarize.invokeAsync(text); + SKContext result = mono.block(); + + String expected = "A block of text\n\nSummarize the content above."; + + assertCompletionsWasCalledWithModelAndText(openAIAsyncClient, model, expected); + assertTheResultEquals(result, expectedResponse); + } + + private void assertTheResultEquals(SKContext result, String expected) { + Assertions.assertEquals(expected, result.getResult()); + } + + private static void assertCompletionsWasCalledWithModelAndText( + OpenAIAsyncClient openAIAsyncClient, String model, String expected) { + + Mockito.verify(openAIAsyncClient, Mockito.times(1)) + .getCompletionsStream( + Mockito.matches(model), + Mockito.argThat( + completionsOptions -> + completionsOptions.getPrompt().size() == 1 + && completionsOptions + .getPrompt() + .get(0) + .equals(expected))); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/TextEmbeddingsTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/TextEmbeddingsTest.java new file mode 100644 index 0000000000..bf41c8e817 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/TextEmbeddingsTest.java @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.EmbeddingItem; +import com.azure.ai.openai.models.Embeddings; +import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration; +import com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import reactor.core.publisher.Mono; + +public class TextEmbeddingsTest { + + private static OpenAIAsyncClient mockEmbeddingOpenAIAsyncClient() { + OpenAIAsyncClient openAIAsyncClient = Mockito.mock(OpenAIAsyncClient.class); + Embeddings embeddings = Mockito.mock(Embeddings.class); + EmbeddingItem embeddingItem = Mockito.mock(EmbeddingItem.class); + + Mockito.when(embeddingItem.getEmbedding()).thenReturn(Collections.singletonList(1.0)); + + Mockito.when(embeddings.getData()).thenReturn(Collections.singletonList(embeddingItem)); + + Mockito.when( + openAIAsyncClient.getEmbeddings( + Mockito.any(String.class), + Mockito.argThat( + it -> + it != null + && it.getModel() + .equals("text-embedding-ada-002")))) + .thenReturn(Mono.just(embeddings)); + + return openAIAsyncClient; + } + + @Test + public void testEmbedding() { + testEmbeddingGeneration(mockEmbeddingOpenAIAsyncClient(), 1); + } + + public void testEmbeddingGeneration(OpenAIAsyncClient client, int expectedEmbeddingSize) { + String model = "text-embedding-ada-002"; + EmbeddingGeneration embeddingGeneration = + new OpenAITextEmbeddingGeneration(client, model); + + List data = new ArrayList<>(); + data.add("This is just"); + data.add("a test"); + + embeddingGeneration + .generateEmbeddingsAsync(data) + .block() + .forEach( + embedding -> { + Assertions.assertEquals( + expectedEmbeddingSize, embedding.getVector().size()); + }); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletionTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletionTest.java new file mode 100644 index 0000000000..302638f51f --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/connectors/ai/openai/chatcompletion/OpenAIChatCompletionTest.java @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.connectors.ai.openai.chatcompletion; + +import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.ChatCompletions; +import com.azure.ai.openai.models.ChatCompletionsOptions; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.ai.AIException; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.syntaxexamples.Example17ChatGPTTest; +import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuples; + +public class OpenAIChatCompletionTest { + + @Test + public void chatCompletionCanBeUsedAsATextCompletion() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient(Tuples.of("Run completion", "A-RESULT")); + Kernel kernel = + SKBuilders.kernel() + .withDefaultAIService( + SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("gpt-3.5-turbo-0301") + .build()) + .build(); + + TextCompletion textCompletion = kernel.getService(null, TextCompletion.class); + + List result = + textCompletion + .completeAsync("Run completion", new CompletionRequestSettings()) + .block(); + + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals("A-RESULT", result.get(0)); + } + + @Test + public void azureOpenAIChatSampleAsync() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient(Tuples.of("Today is", "A-RESULT")); + + String message = "Hi, I'm looking for book suggestions"; + Example17ChatGPTTest.mockResponse(client, message, "1st response"); + + String result = getRunExample(client, message); + Assertions.assertEquals("1st response", result); + } + + private static String getRunExample(OpenAIAsyncClient client, String message) { + Kernel kernel = + SKBuilders.kernel() + .withDefaultAIService( + SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("gpt-3.5-turbo-0301") + .build()) + .build(); + + ChatCompletion chatGPT = kernel.getService(null, ChatCompletion.class); + + OpenAIChatHistory chatHistory = + chatGPT.createNewChat("You are a librarian, expert about books"); + + // First user message + chatHistory.addUserMessage(message); + ChatHistory.Message createdMessage = chatHistory.getLastMessage().get(); + Assertions.assertEquals(ChatHistory.AuthorRoles.User, createdMessage.getAuthorRoles()); + Assertions.assertEquals(message, createdMessage.getContent()); + + // First bot assistant message + return chatGPT.generateMessageAsync(chatHistory, null).block(); + } + + @Test + public void emptyResponseThrowsError() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient(Tuples.of("Today is", "A-RESULT")); + + String message = "Hi, I'm looking for book suggestions"; + + ChatCompletions completion = Mockito.mock(ChatCompletions.class); + Mockito.when(completion.getChoices()).thenReturn(new ArrayList<>()); + + Mockito.when( + client.getChatCompletions( + Mockito.any(), + Mockito.argThat( + msg -> { + return msg != null + && msg.getMessages() + .get(msg.getMessages().size() - 1) + .getContent() + .equals(message); + }))) + .thenReturn(Mono.just(completion)); + + Assertions.assertThrows(AIException.class, () -> getRunExample(client, message)); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/MemoryExceptionTests.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/MemoryExceptionTests.java new file mode 100644 index 0000000000..9aed89927c --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/MemoryExceptionTests.java @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class MemoryExceptionTests { + @Test + void itRoundtripsArgsToErrorCodeCtor() { + // Arrange + MemoryException e = + new MemoryException(MemoryException.ErrorCodes.FAILED_TO_CREATE_COLLECTION); + + // Assert + assertEquals(MemoryException.ErrorCodes.FAILED_TO_CREATE_COLLECTION, e.getErrorCode()); + assertTrue(e.getMessage().contains("Failed to create collection")); + assertNull(e.getCause()); + } + + @Test + void itRoundtripsArgsToErrorCodeMessageCtor() { + // Arrange + String message = "this is a test"; + MemoryException e = + new MemoryException( + MemoryException.ErrorCodes.FAILED_TO_CREATE_COLLECTION, message); + + // Assert + assertEquals(MemoryException.ErrorCodes.FAILED_TO_CREATE_COLLECTION, e.getErrorCode()); + assertTrue(e.getMessage().contains("Failed to create collection")); + assertTrue(e.getMessage().contains(message)); + assertNull(e.getCause()); + } + + @Test + void itRoundtripsArgsToErrorCodeMessageExceptionCtor() { + // Arrange + String message = "this is a test"; + Exception inner = new NumberFormatException(); + MemoryException e = + new MemoryException( + MemoryException.ErrorCodes.FAILED_TO_CREATE_COLLECTION, message, inner); + + // Assert + assertEquals(MemoryException.ErrorCodes.FAILED_TO_CREATE_COLLECTION, e.getErrorCode()); + assertTrue(e.getMessage().contains("Failed to create collection")); + assertTrue(e.getMessage().contains(message)); + assertSame(inner, e.getCause()); + } + + @Test + void itAllowsNullMessageAndInnerExceptionInCtors() { + // Arrange + MemoryException e = + new MemoryException( + MemoryException.ErrorCodes.FAILED_TO_CREATE_COLLECTION, null, null); + + // Assert + assertEquals(MemoryException.ErrorCodes.FAILED_TO_CREATE_COLLECTION, e.getErrorCode()); + assertTrue(e.getMessage().contains("Failed to create collection")); + assertNull(e.getCause()); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/MemoryRecordTests.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/MemoryRecordTests.java new file mode 100644 index 0000000000..29cf908680 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/MemoryRecordTests.java @@ -0,0 +1,265 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import java.time.ZonedDateTime; +import java.util.Arrays; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +class MemoryRecordTests { + private static final boolean _isReference = false; + private static final String _id = "Id"; + private static final String _text = "text"; + private static final String _description = "description"; + private static final String _externalSourceName = "externalSourceName"; + private static final String _additionalMetadata = "value"; + private static final Embedding _embedding = new Embedding(Arrays.asList(1f, 2f, 3f)); + + @Test + void itCanBeConstructedFromMetadataAndVector() { + // Arrange + MemoryRecordMetadata metadata = + new MemoryRecordMetadata( + _isReference, + _id, + _text, + _description, + _externalSourceName, + _additionalMetadata); + + // Act + MemoryRecord memoryRecord = + new MemoryRecord(metadata, _embedding, "key", ZonedDateTime.now()); + + // Assert + assertEquals(_isReference, memoryRecord.getMetadata().isReference()); + assertEquals(_id, memoryRecord.getMetadata().getId()); + assertEquals(_text, memoryRecord.getMetadata().getText()); + assertEquals(_description, memoryRecord.getMetadata().getDescription()); + assertEquals(_externalSourceName, memoryRecord.getMetadata().getExternalSourceName()); + assertEquals(_embedding.getVector(), memoryRecord.getEmbedding().getVector()); + } + + @Test + void itCanBeConstructedFromMetadata() { + // Arrange + MemoryRecordMetadata metadata = + new MemoryRecordMetadata( + _isReference, + _id, + _text, + _description, + _externalSourceName, + _additionalMetadata); + + // Act + MemoryRecord memoryRecord = + MemoryRecord.fromMetadata(metadata, _embedding, "key", ZonedDateTime.now()); + + // Assert + assertEquals(_isReference, memoryRecord.getMetadata().isReference()); + assertEquals(_id, memoryRecord.getMetadata().getId()); + assertEquals(_text, memoryRecord.getMetadata().getText()); + assertEquals(_description, memoryRecord.getMetadata().getDescription()); + assertEquals(_externalSourceName, memoryRecord.getMetadata().getExternalSourceName()); + assertEquals(_embedding.getVector(), memoryRecord.getEmbedding().getVector()); + } + + @Test + void itCanBeConstructedFromMetadataAndNulls() { + // Arrange + MemoryRecordMetadata metadata = + new MemoryRecordMetadata( + _isReference, + _id, + _text, + _description, + _externalSourceName, + _additionalMetadata); + + // Act + MemoryRecord memoryRecord = MemoryRecord.fromMetadata(metadata, null, null, null); + + // Assert + assertEquals(_isReference, memoryRecord.getMetadata().isReference()); + assertEquals(_id, memoryRecord.getMetadata().getId()); + assertEquals(_text, memoryRecord.getMetadata().getText()); + assertEquals(_description, memoryRecord.getMetadata().getDescription()); + assertEquals(_externalSourceName, memoryRecord.getMetadata().getExternalSourceName()); + assertEquals(Embedding.empty().getVector(), memoryRecord.getEmbedding().getVector()); + assertEquals("", memoryRecord.getKey()); + assertEquals(null, memoryRecord.getTimestamp()); + } + + @Test + void itCanBeCreatedToRepresentLocalData() { + // Arrange + MemoryRecord memoryRecord = + MemoryRecord.localRecord(_id, _text, _description, _embedding, null, null, null); + + // Assert + assertFalse(memoryRecord.getMetadata().isReference()); + assertEquals(_id, memoryRecord.getMetadata().getId()); + assertEquals(_text, memoryRecord.getMetadata().getText()); + assertEquals(_description, memoryRecord.getMetadata().getDescription()); + assertEquals("", memoryRecord.getMetadata().getExternalSourceName()); + assertEquals(_embedding.getVector(), memoryRecord.getEmbedding().getVector()); + } + + @Test + void itCanBeCreatedToRepresentExternalData() { + // Arrange + MemoryRecord memoryRecord = + MemoryRecord.referenceRecord( + _id, _externalSourceName, _description, _embedding, null, null, null); + + // Assert + assertTrue(memoryRecord.getMetadata().isReference()); + assertEquals(_id, memoryRecord.getMetadata().getId()); + assertEquals("", memoryRecord.getMetadata().getText()); + assertEquals(_description, memoryRecord.getMetadata().getDescription()); + assertEquals(_externalSourceName, memoryRecord.getMetadata().getExternalSourceName()); + assertEquals(_embedding.getVector(), memoryRecord.getEmbedding().getVector()); + } + + @Test + @Disabled("fromJsonMetadata is not implemented") + void itCanBeCreatedFromSerializedMetadata() { + // Arrange + String jsonString = + "{" + + "\"is_reference\" : false" + + "\"id\" : \"Id\"" + + "\"text\" : \"text\"" + + "\"description\" : \"description\"" + + "\"external_source_name\" : \"externalSourceName\"" + + "\"additional_metadata\" : \"value\"" + + "}"; + + // Act + MemoryRecord memoryRecord = null; // MemoryRecord.fromJsonMetadata(jsonString, _embedding); + + // Assert + assertEquals(_isReference, memoryRecord.getMetadata().isReference()); + assertEquals(_id, memoryRecord.getMetadata().getId()); + assertEquals(_text, memoryRecord.getMetadata().getText()); + assertEquals(_description, memoryRecord.getMetadata().getDescription()); + assertEquals(_externalSourceName, memoryRecord.getMetadata().getExternalSourceName()); + assertEquals(_additionalMetadata, memoryRecord.getMetadata().getAdditionalMetadata()); + assertEquals(_embedding.getVector(), memoryRecord.getEmbedding().getVector()); + } + + @Test + @Disabled("JSON deserialization is not implemented") + void itCanBeDeserializedFromJson() { + // Arrange + String jsonString = + "{" + + " \"metadata\" : {" + + " \"is_reference\" : false" + + " \"id\" : \"Id\"" + + " \"text\" : \"text\"" + + " \"description\" : \"description\"" + + " \"external_source_name\" : \"externalSourceName\"" + + " \"additional_metadata\" : \"value\"" + + " }" + + " \"embedding\" : {" + + " \"vector\" : [ 1, 2, 3 ]" + + " }" + + "}"; + + // Act + MemoryRecord memoryRecord = null; // JsonSerializer.Deserialize(jsonString); + + // Assert + assertNotNull(memoryRecord); + assertEquals(_isReference, memoryRecord.getMetadata().isReference()); + assertEquals(_id, memoryRecord.getMetadata().getId()); + assertEquals(_text, memoryRecord.getMetadata().getText()); + assertEquals(_description, memoryRecord.getMetadata().getDescription()); + assertEquals(_externalSourceName, memoryRecord.getMetadata().getExternalSourceName()); + assertEquals(_externalSourceName, memoryRecord.getMetadata().getExternalSourceName()); + assertEquals(_embedding.getVector(), memoryRecord.getEmbedding().getVector()); + } + + @Test + @Disabled("JSON serialization is not implemented") + void itCanBeSerialized() { + // Arrange + String jsonString = + "{" + + " \"metadata\" : {" + + " \"is_reference\" : false" + + " \"id\" : \"Id\"" + + " \"text\" : \"text\"" + + " \"description\" : \"description\"" + + " \"external_source_name\" : \"externalSourceName\"" + + " \"additional_metadata\" : \"value\"" + + " }" + + " \"embedding\" : {" + + " \"vector\" : [ 1, 2, 3 ]" + + " }" + + "\"key\" : \"key\"" + + "\"timestamp\": null" + + "}"; + + MemoryRecordMetadata metadata = + new MemoryRecordMetadata( + _isReference, + _id, + _text, + _description, + _externalSourceName, + _additionalMetadata); + MemoryRecord memoryRecord = + new MemoryRecord(metadata, _embedding, "key", ZonedDateTime.now()); + + // Act + String serializedRecord = null; // JsonSerializer.Serialize(memoryRecord); + jsonString = jsonString.replaceAll("\n", ""); + jsonString = jsonString.replaceAll(" ", ""); + + // Assert + assertEquals(jsonString, serializedRecord); + } + + @Test + @Disabled("JSON serialization is not implemented") + void itsMetadataCanBeSerialized() { + // Arrange + String jsonString = + "{" + + " \"is_reference\" : false" + + " \"id\" : \"Id\"" + + " \"text\" : \"text\"" + + " \"description\" : \"description\"" + + " \"external_source_name\" : \"externalSourceName\"" + + " \"additional_metadata\" : \"value\"" + + "}"; + + MemoryRecordMetadata metadata = + new MemoryRecordMetadata( + _isReference, + _id, + _text, + _description, + _externalSourceName, + _additionalMetadata); + MemoryRecord memoryRecord = + new MemoryRecord(metadata, _embedding, "key", ZonedDateTime.now()); + + // Act + String serializedMetadata = // memoryRecord.getSerializedMetadata(); + jsonString = jsonString.replaceAll("\n", ""); + jsonString = jsonString.replaceAll(" ", ""); + + // Assert + assertEquals(jsonString, serializedMetadata); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/VolatileMemoryStoreTests.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/VolatileMemoryStoreTests.java new file mode 100644 index 0000000000..b829b3f7c0 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/memory/VolatileMemoryStoreTests.java @@ -0,0 +1,942 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.memory; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.microsoft.semantickernel.ai.embeddings.Embedding; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Flux; +import reactor.util.function.Tuple2; + +class VolatileMemoryStoreTests { + private VolatileMemoryStore _db; + + @BeforeEach + void setUp() { + this._db = new VolatileMemoryStore(); + } + + private int _collectionNum = 0; + + private static final String NULL_ADDITIONAL_METADATA = null; + private static final String NULL_KEY = null; + private static final ZonedDateTime NULL_TIMESTAMP = null; + + private Collection createBatchRecords(int numRecords) { + assertTrue(numRecords % 2 == 0, "Number of records must be even"); + assertTrue(numRecords > 0, "Number of records must be greater than 0"); + + List records = new ArrayList<>(numRecords); + for (int i = 0; i < numRecords / 2; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + for (int i = numRecords / 2; i < numRecords; i++) { + MemoryRecord testRecord = + MemoryRecord.referenceRecord( + "test" + i, + "sourceName" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + records.add(testRecord); + } + + return records; + } + + @Test + void initializeDbConnectionSucceeds() { + assertNotNull(this._db); + } + + @Test + void itCanCreateAndGetCollectionAsync() { + // Arrange + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + this._db.createCollectionAsync(collection).block(); + Collection collections = this._db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertFalse(collections.isEmpty()); + assertTrue(collections.contains(collection)); + } + + @Test + void itHandlesExceptionsWhenCreatingCollectionAsync() { + // Arrange + String collection = null; + + // Assert + assertThrows( + NullPointerException.class, + () -> this._db.createCollectionAsync(collection).block(), + "Should not be able to create collection with null name"); + } + + @Test + @Disabled("inconsistency between memory store implementations") + void itCannotInsertIntoNonExistentCollectionAsync() { + + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Assert + assertThrows( + MemoryException.class, + () -> this._db.upsertAsync(collection, testRecord).block(), + "Should not be able to insert into a non-existent collection"); + } + + @Test + void getAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + this._db.createCollectionAsync(collection).block(); + String key = this._db.upsertAsync(collection, testRecord).block(); + MemoryRecord actualDefault = this._db.getAsync(collection, key, false).block(); + MemoryRecord actualWithEmbedding = this._db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actualDefault); + assertNotNull(actualDefault.getEmbedding()); + assertNotNull(actualDefault.getEmbedding().getVector()); + assertTrue(actualDefault.getEmbedding().getVector().isEmpty()); + assertNotNull(actualWithEmbedding); + assertNotNull(actualWithEmbedding.getEmbedding()); + assertNotNull(actualWithEmbedding.getEmbedding().getVector()); + assertFalse(actualWithEmbedding.getEmbedding().getVector().isEmpty()); + assertNotEquals(testRecord, actualDefault); + assertEquals(testRecord, actualWithEmbedding); + } + + @Test + void itCanUpsertAndRetrieveARecordWithNoTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + this._db.createCollectionAsync(collection).block(); + String key = this._db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = this._db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord, actual); + } + + @Test + void itCanUpsertAndRetrieveARecordWithTimestampAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + ZonedDateTime.now(ZoneId.of("UTC"))); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + this._db.createCollectionAsync(collection).block(); + String key = this._db.upsertAsync(collection, testRecord).block(); + MemoryRecord actual = this._db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertEquals(testRecord, actual); + } + + @Test + void upsertReplacesExistingRecordWithSameIdAsync() { + // Arrange + String commonId = "test"; + MemoryRecord testRecord = + MemoryRecord.localRecord( + commonId, + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + MemoryRecord testRecord2 = + MemoryRecord.localRecord( + commonId, + "text2", + "description2", + new Embedding(Arrays.asList(1f, 2f, 4f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + this._db.createCollectionAsync(collection).block(); + String key = this._db.upsertAsync(collection, testRecord).block(); + String key2 = this._db.upsertAsync(collection, testRecord2).block(); + MemoryRecord actual = this._db.getAsync(collection, key, true).block(); + + // Assert + assertNotNull(actual); + assertNotEquals(testRecord, actual); + assertEquals(key, key2); + assertEquals(testRecord2, actual); + } + + @Test + void existingRecordCanBeRemovedAsync() { + // Arrange + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test", + "text", + "description", + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + this._db.createCollectionAsync(collection).block(); + String key = this._db.upsertAsync(collection, testRecord).block(); + assertNotNull(key); + this._db.removeAsync(collection, key).block(); + MemoryRecord actual = this._db.getAsync(collection, key, false).block(); + + // Assert + assertNull(actual); + } + + @Test + void removingNonExistingRecordDoesNothingAsync() { + // Arrange + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + this._db.removeAsync(collection, "key").block(); + MemoryRecord actual = this._db.getAsync(collection, "key", false).block(); + + // Assert + assertNull(actual); + } + + @Test + void itCanListAllDatabaseCollectionsAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(this._collectionNum, this._collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Flux.fromArray(testCollections) + .concatMap(collection -> this._db.createCollectionAsync(collection)) + .blockLast(); + + // Act + Collection collections = this._db.getCollectionsAsync().block(); + + // Assert + assertNotNull(collections); + assertEquals(numCollections, collections.size()); + for (String collection : testCollections) { + assertTrue( + collections.contains(collection), + "Collections does not contain the newly-created collection " + collection); + } + } + + @Test + void getNearestMatchesReturnsAllResultsWithNoMinScoreAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + // Act + float threshold = -1f; + Collection> topNResults = + this._db + .getNearestMatchesAsync( + collection, compareEmbedding, topN, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertEquals(topN, topNResults.size()); + Tuple2[] topNResultsArray = topNResults.toArray(new Tuple2[0]); + for (int j = 0; j < topN - 1; j++) { + int compare = + Double.compare(topNResultsArray[j].getT2(), topNResultsArray[j + 1].getT2()); + assertTrue(compare >= 0); + } + } + + @Test + void getNearestMatchesReturnsLimit() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + // Act + float threshold = -1f; + Collection> topNResults = + this._db + .getNearestMatchesAsync( + collection, compareEmbedding, i / 2, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertEquals(i / 2, topNResults.size()); + } + + @Test + void getNearestMatchesReturnsEmptyIfLimitZero() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + // Act + float threshold = -1f; + Collection> topNResults = + this._db + .getNearestMatchesAsync(collection, compareEmbedding, 0, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchesReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Collection> topNResults = + this._db + .getNearestMatchesAsync( + collection, compareEmbedding, Integer.MAX_VALUE, threshold, false) + .block(); + + // Assert + assertNotNull(topNResults); + assertTrue(topNResults.isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsEmptyEmbeddingUnlessSpecifiedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + // Act + float threshold = 0.75f; + Tuple2 topNResultDefault = + this._db + .getNearestMatchAsync(collection, compareEmbedding, threshold, false) + .block(); + Tuple2 topNResultWithEmbedding = + this._db + .getNearestMatchAsync(collection, compareEmbedding, threshold, true) + .block(); + + // Assert + assertNotNull(topNResultDefault); + assertNotNull(topNResultWithEmbedding); + assertNotNull(topNResultDefault.getT1().getEmbedding()); + assertNotNull(topNResultDefault.getT1().getEmbedding().getVector()); + assertTrue(topNResultDefault.getT1().getEmbedding().getVector().isEmpty()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding()); + assertNotNull(topNResultWithEmbedding.getT1().getEmbedding().getVector()); + assertFalse(topNResultWithEmbedding.getT1().getEmbedding().getVector().isEmpty()); + } + + @Test + void getNearestMatchAsyncReturnsExpectedAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + int i = 0; + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -1f, -1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 2f, 3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(-1f, -2f, -3f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + i++; + testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, -1f, -2f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + + // Act + float threshold = 0.75f; + Tuple2 topNResult = + this._db + .getNearestMatchAsync(collection, compareEmbedding, threshold, false) + .block(); + + // Assert + assertNotNull(topNResult); + assertEquals("test0", topNResult.getT1().getMetadata().getId()); + assertTrue(topNResult.getT2() >= threshold); + } + + @Test + void getNearestMatcheReturnsEmptyIfCollectionEmpty() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + + // Act + float threshold = -1f; + Tuple2 topNResults = + this._db + .getNearestMatchAsync(collection, compareEmbedding, threshold, false) + .block(); + + // Assert + assertNull(topNResults); + } + + @Test + void getNearestMatchesDifferentiatesIdenticalVectorsByKeyAsync() { + // Arrange + Embedding compareEmbedding = new Embedding(Arrays.asList(1f, 1f, 1f)); + int topN = 4; + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + + for (int i = 0; i < 10; i++) { + MemoryRecord testRecord = + MemoryRecord.localRecord( + "test" + i, + "text" + i, + "description" + i, + new Embedding(Arrays.asList(1f, 1f, 1f)), + NULL_ADDITIONAL_METADATA, + NULL_KEY, + NULL_TIMESTAMP); + this._db.upsertAsync(collection, testRecord).block(); + } + + // Act + Collection> topNResults = + this._db + .getNearestMatchesAsync(collection, compareEmbedding, topN, 0.75f, true) + .block(); + Collection topNKeys = + topNResults.stream() + .map(tuple -> tuple.getT1().getKey()) + .sorted() + .collect(Collectors.toList()); + + // Assert + assertEquals(topN, topNResults.size()); + assertEquals(topN, topNKeys.size()); + for (Iterator> iterator = topNResults.iterator(); + iterator.hasNext(); ) { + Tuple2 tuple = iterator.next(); + int compare = Float.compare(tuple.getT2(), 0.75f); + assertTrue(topNKeys.contains(tuple.getT1().getKey())); + assertTrue(compare >= 0); + } + } + + @Test + void itCanBatchUpsertRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + // Act + Collection keys = this._db.upsertBatchAsync(collection, records).block(); + Collection resultRecords = + this._db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertEquals(numRecords, keys.size()); + assertEquals(numRecords, resultRecords.size()); + } + + @Test + void itCanBatchGetRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + Collection keys = this._db.upsertBatchAsync(collection, records).block(); + + // Act + Collection results = this._db.getBatchAsync(collection, keys, false).block(); + + // Assert + assertNotNull(keys); + assertNotNull(results); + assertEquals(numRecords, results.size()); + } + + @Test + void itCanBatchRemoveRecordsAsync() { + // Arrange + int numRecords = 10; + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + Collection records = this.createBatchRecords(numRecords); + + List keys = new ArrayList<>(); + for (String key : this._db.upsertBatchAsync(collection, records).block()) { + keys.add(key); + } + + // Act + this._db.removeBatchAsync(collection, keys).block(); + + // Assert + for (MemoryRecord result : this._db.getBatchAsync(collection, keys, true).block()) { + assertNull(result); + } + } + + @Test + void collectionsCanBeDeletedAsync() { + // Arrange + int numCollections = 3; + String[] testCollections = + IntStream.range(this._collectionNum, this._collectionNum += numCollections) + .mapToObj(i -> "test_collection" + i) + .toArray(String[]::new); + + Flux.fromArray(testCollections) + .concatMap(collection -> this._db.createCollectionAsync(collection)) + .blockLast(); + + // Act + Collection collections = this._db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(numCollections, collections.size()); + + // Act + for (String collection : collections) { + this._db.deleteCollectionAsync(collection).block(); + } + + // Assert + collections = this._db.getCollectionsAsync().block(); + assertNotNull(collections); + assertEquals(0, collections.size()); + } + + @Test + void itThrowsWhenDeletingNonExistentCollectionAsync() { + // Arrange + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + assertThrows( + MemoryException.class, () -> this._db.deleteCollectionAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnTrueForExistingCollection() { + // Arrange + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + this._db.createCollectionAsync(collection).block(); + + // Act + assertTrue(this._db.doesCollectionExistAsync(collection).block()); + } + + @Test + void doesCollectionExistAsyncReturnFalseForNonExistentCollection() { + // Arrange + String collection = "test_collection" + this._collectionNum; + this._collectionNum++; + + // Act + assertFalse(this._db.doesCollectionExistAsync(collection).block()); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/orchestration/NativeSKFunctionTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/orchestration/NativeSKFunctionTest.java new file mode 100644 index 0000000000..478325baae --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/orchestration/NativeSKFunctionTest.java @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.orchestration; + +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.ai.AIException; +import com.microsoft.semantickernel.coreskills.SkillImporter; +import com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection; +import com.microsoft.semantickernel.skilldefinition.FunctionCollection; +import com.microsoft.semantickernel.skilldefinition.FunctionNotFound; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.util.Objects; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import reactor.core.publisher.Mono; + +public class NativeSKFunctionTest { + + @Test + public void singleStringIsBoundToInput() { + class SinleStringSkill { + @DefineSKFunction + public String doSomething(String anInput) { + return ""; + } + } + + SinleStringSkill skill = Mockito.spy(new SinleStringSkill()); + FunctionCollection skills = + SkillImporter.importSkill(skill, "test", DefaultSkillCollection::new); + SKContext ignore = skills.getFunction("doSomething").invokeAsync("foo").block(); + Mockito.verify(skill, Mockito.times(1)).doSomething("foo"); + } + + @Test + public void annotatedWithSKFunctionInputAttributeIsBoundToInput() { + class With2Inputs { + @DefineSKFunction + public String doSomething( + @SKFunctionInputAttribute(description = "") String anInput, + @SKFunctionParameters(name = "secondInput") String secondInput) { + return ""; + } + } + With2Inputs skill = Mockito.spy(new With2Inputs()); + FunctionCollection skills = + SkillImporter.importSkill(skill, "test", DefaultSkillCollection::new); + ContextVariables variables = SKBuilders.variables().build(); + variables = variables.writableClone().appendToVariable("input", "foo"); + variables = variables.writableClone().appendToVariable("secondInput", "ignore"); + skills.getFunction("doSomething").invokeWithCustomInputAsync(variables, null, null).block(); + Mockito.verify(skill, Mockito.times(1)).doSomething("foo", "ignore"); + } + + @Test + public void annotatedWithNonInputIsBound() { + class With2InputParameters { + @DefineSKFunction + public String doSomething( + @SKFunctionParameters(name = "anInput") String anInput, + @SKFunctionParameters(name = "secondInput") String secondInput) { + return ""; + } + } + With2InputParameters skill = Mockito.spy(new With2InputParameters()); + FunctionCollection skills = + SkillImporter.importSkill(skill, "test", DefaultSkillCollection::new); + ContextVariables variables = SKBuilders.variables().build(); + variables = variables.writableClone().appendToVariable("anInput", "foo"); + variables = variables.writableClone().appendToVariable("secondInput", "ignore"); + skills.getFunction("doSomething").invokeWithCustomInputAsync(variables, null, null).block(); + Mockito.verify(skill, Mockito.times(1)).doSomething("foo", "ignore"); + } + + @Test + public void nonExistentVariableCreatesError() { + class DoesNotExist { + @DefineSKFunction + public String doSomething(@SKFunctionParameters(name = "doesNotExist") String anInput) { + return ""; + } + } + DoesNotExist skill = Mockito.spy(new DoesNotExist()); + FunctionCollection skills = + SkillImporter.importSkill(skill, "test", DefaultSkillCollection::new); + ContextVariables variables = + SKBuilders.variables().build().writableClone().appendToVariable("input", "foo"); + Assertions.assertThrows( + AIException.class, + () -> { + skills.getFunction("doSomething") + .invokeWithCustomInputAsync(variables, null, null) + .block(); + }); + Mockito.verify(skill, Mockito.never()).doSomething("foo"); + } + + @Test + public void noAnnotationCreatesError() { + class AnnotationDoesNotExist { + public String doSomething(String anInput) { + return ""; + } + } + + AnnotationDoesNotExist skill = Mockito.spy(new AnnotationDoesNotExist()); + Assertions.assertThrows( + FunctionNotFound.class, + () -> { + FunctionCollection skills = + SkillImporter.importSkill(skill, "test", DefaultSkillCollection::new); + skills.getFunction("doSomething").invokeAsync("foo"); + }); + Mockito.verify(skill, Mockito.never()).doSomething("foo"); + } + + @Test + public void contextIsBound() { + class WithContext { + @DefineSKFunction + public String doSomething(SKContext context) { + return ""; + } + } + + WithContext skill = Mockito.spy(new WithContext()); + FunctionCollection skills = + SkillImporter.importSkill(skill, "test", DefaultSkillCollection::new); + SKContext ignore = skills.getFunction("doSomething").invokeAsync("foo").block(); + Mockito.verify(skill, Mockito.only()).doSomething(Mockito.notNull()); + } + + @Test + public void withMonoReturn() { + class WithMono { + @DefineSKFunction + public Mono doSomething() { + return Mono.just("A-RESULT"); + } + } + + WithMono skill = Mockito.spy(new WithMono()); + FunctionCollection skills = + SkillImporter.importSkill(skill, "test", DefaultSkillCollection::new); + SKContext result = skills.getFunction("doSomething").invokeAsync("foo").block(); + Assertions.assertEquals("A-RESULT", Objects.requireNonNull(result).getResult()); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlannerTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlannerTest.java new file mode 100644 index 0000000000..304ad5a770 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/planner/actionplanner/ActionPlannerTest.java @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.actionplanner; + +import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import reactor.util.function.Tuples; + +public class ActionPlannerTest { + + public static class SkillWithSomeArgs { + @DefineSKFunction(name = "aFunction") + public String aFunction( + @SKFunctionParameters( + name = "input1", + description = "The first input to the function") + String input1, + @SKFunctionParameters( + name = "input2", + description = "The second input to the function") + String input2) { + return "A-RESULT"; + } + } + + @Test + public void inputsAreCorrectlyPassed() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient( + Tuples.of( + "plan", + "{\n" + + " \"plan\" : {\n" + + " \"function\" : \"SkillWithSomeArgs.aFunction\",\n" + + " \"parameters\" : {\n" + + " \"input1\" : \"Cleopatra\",\n" + + " \"input2\" : \"Anthony\"\n" + + " },\n" + + " \"rationale\" : \"na\"\n" + + " }\n" + + "}\n")); + + Kernel kernel = + SKBuilders.kernel() + .withDefaultAIService( + SKBuilders.textCompletion() + .withModelId("text-davinci-002") + .withOpenAIClient(client) + .build()) + .build(); + + SkillWithSomeArgs skill = Mockito.spy(new SkillWithSomeArgs()); + kernel.importSkill(skill, "SkillWithSomeArgs"); + + ActionPlanner planner = new ActionPlanner(kernel, null); + + String goal = "Write a poem about Cleopatra."; + + Plan plan = planner.createPlanAsync(goal).block(); + String planResult = plan.invokeAsync(goal).block().getResult(); + + Assertions.assertEquals("A-RESULT", planResult); + + Mockito.verify(skill, Mockito.atLeastOnce()).aFunction("Cleopatra", "Anthony"); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/planner/stepwiseplanner/StepwisePlannerTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/planner/stepwiseplanner/StepwisePlannerTest.java new file mode 100644 index 0000000000..f2db77bc46 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/planner/stepwiseplanner/StepwisePlannerTest.java @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.planner.stepwiseplanner; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.ChatChoice; +import com.azure.ai.openai.models.ChatCompletions; +import com.azure.ai.openai.models.ChatMessage; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.coreskills.TimeSkill; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import com.microsoft.semantickernel.util.EmbeddedResourceLoader; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class StepwisePlannerTest { + + @Test + public void runChatCompletion() { + Kernel kernel = getKernel(); + SKContext result = + runWithQuestion(kernel, "What year is the first world cup divided by 2").block(); + + Assertions.assertEquals( + "The year of the first world cup is 1930, and when divided by 2, the result is" + + " 965.", + result.getResult()); + } + + public static class WebSearchEngineSkill { + + @DefineSKFunction(description = "Perform a web search.", name = "search") + public Mono search( + @SKFunctionParameters(description = "Text to search for", name = "query") + String input, + @SKFunctionParameters( + description = "Number of results", + name = "count", + defaultValue = "1", + type = Integer.class) + Integer count, + @SKFunctionParameters( + description = "Number of results to skip", + name = "offset", + defaultValue = "0", + type = Integer.class) + Integer offset) { + return Mono.just("1930"); + } + } + + public static class AdvancedCalculator { + @DefineSKFunction( + description = "Useful for getting the result of a non-trivial math expression.", + name = "Calculator") + public Mono Calculator( + @SKFunctionParameters( + description = + "A valid mathematical expression that could be executed by" + + " a calculator capable of more advanced math" + + " functions like sin/cosine/floor.", + name = "input") + String input) { + return Mono.just("40"); + } + } + + private static Mono runWithQuestion(Kernel kernel, String question) { + WebSearchEngineSkill webSearchEngineSkill = new WebSearchEngineSkill(); + + kernel.importSkill(webSearchEngineSkill, "WebSearch"); + kernel.importSkill(new AdvancedCalculator(), "AdvancedCalculator"); + kernel.importSkill(new TimeSkill(), "time"); + + System.out.println("*****************************************************"); + System.out.println("Question: " + question); + + StepwisePlanner planner = new DefaultStepwisePlanner(kernel, null, null, null); + + Plan plan = planner.createPlan(question); + + return plan.invokeAsync(SKBuilders.context().withKernel(kernel).build()); + } + + private static Kernel getKernel() { + OpenAIAsyncClient client = Mockito.mock(OpenAIAsyncClient.class); + + AtomicInteger callCount = new AtomicInteger(0); + + Mockito.when(client.getChatCompletionsStream(Mockito.any(), Mockito.any())) + .then( + (Answer>) + invocationOnMock -> { + int index = callCount.incrementAndGet(); + + String response = + EmbeddedResourceLoader.readFile( + "response" + index + ".txt", + StepwisePlannerTest.class); + + ChatMessage chatMessage = Mockito.mock(ChatMessage.class); + Mockito.when(chatMessage.getContent()).thenReturn(response); + + ChatChoice chatChoice = Mockito.mock(ChatChoice.class); + Mockito.when(chatChoice.getMessage()).thenReturn(chatMessage); + Mockito.when(chatChoice.getDelta()).thenReturn(chatMessage); + + ChatCompletions chatCompletion = + Mockito.mock(ChatCompletions.class); + Mockito.when(chatCompletion.getChoices()) + .thenReturn(Arrays.asList(chatChoice)); + Mockito.when(chatCompletion.getId()).thenReturn("foo"); + + return Flux.just(chatCompletion); + }); + + TextCompletion textCompletion = + SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("gpt-35-turbo") + .build(); + + return SKBuilders.kernel().withDefaultAIService(textCompletion).build(); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example01NativeFunctionsTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example01NativeFunctionsTest.java new file mode 100644 index 0000000000..d1529442aa --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example01NativeFunctionsTest.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import com.microsoft.semantickernel.coreskills.TextSkill; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class Example01NativeFunctionsTest { + + @Test + public void run() { + // Load native skill + TextSkill text = new TextSkill(); + + // Use function without kernel + String result = text.uppercase("ciao!"); + + Assertions.assertEquals("CIAO!", result); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example02PipelineTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example02PipelineTest.java new file mode 100644 index 0000000000..0c27a02dfc --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example02PipelineTest.java @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.DefaultKernelTest; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.coreskills.TextSkill; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; + +public class Example02PipelineTest { + @Test + public void run() { + OpenAIAsyncClient client = DefaultKernelTest.mockCompletionOpenAIAsyncClient(); + Kernel kernel = DefaultKernelTest.buildKernel("model", client); + + // Load native skill + ReadOnlyFunctionCollection text = kernel.importSkill(new TextSkill(), null); + + Mono result = + kernel.runAsync( + " i n f i n i t e s p a c e ", + text.getFunction("LStrip"), + text.getFunction("RStrip"), + text.getFunction("Uppercase")); + + Assertions.assertEquals("I N F I N I T E S P A C E", result.block().getResult()); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example03VariablesTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example03VariablesTest.java new file mode 100644 index 0000000000..a137a4356c --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example03VariablesTest.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.DefaultKernelTest; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.orchestration.ContextVariables; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import com.microsoft.semantickernel.syntaxexamples.skills.StaticTextSkill; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; + +public class Example03VariablesTest { + @Test + public void run() { + OpenAIAsyncClient client = DefaultKernelTest.mockCompletionOpenAIAsyncClient(); + Kernel kernel = DefaultKernelTest.buildKernel("model", client); + + // Load native skill + ReadOnlyFunctionCollection functionCollection = + kernel.importSkill(new StaticTextSkill(), "text"); + + ContextVariables variables = + SKBuilders.variables() + .withInput("Today is: ") + .build() + .writableClone() + .setVariable("day", "Monday"); + + Mono result = + kernel.runAsync( + variables, + functionCollection.getFunction("AppendDay"), + functionCollection.getFunction("Uppercase")); + + Assertions.assertEquals("TODAY IS: MONDAY", result.block().getResult()); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example04CombineLLMPromptsAndNativeCodeTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example04CombineLLMPromptsAndNativeCodeTest.java new file mode 100644 index 0000000000..f54ed7f884 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example04CombineLLMPromptsAndNativeCodeTest.java @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.syntaxexamples.skills.SearchEngineSkill; +import com.microsoft.semantickernel.textcompletion.TextCompletion; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuples; + +public class Example04CombineLLMPromptsAndNativeCodeTest { + + @Test + public void run() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient( + Tuples.of( + "Gran Torre Santiago is the tallest building in South America", + "A-SUMMARY")); + + Kernel kernel = + SKBuilders.kernel() + .withAIService( + "text-davinci-002", + new OpenAITextCompletion(client, "text-davinci-002"), + false, + TextCompletion.class) + .withAIService( + "text-davinci-003", + new OpenAITextCompletion(client, "text-davinci-003"), + true, + TextCompletion.class) + .build(); + + kernel.importSkill(new SearchEngineSkill(), null); + kernel.importSkillFromDirectory("SummarizeSkill", "../../samples/skills", "SummarizeSkill"); + + // Run + String ask = "What's the tallest building in South America?"; + + Mono result = + kernel.runAsync(ask, kernel.getSkills().getFunction("Search", null)); + + Assertions.assertEquals( + "Gran Torre Santiago is the tallest building in South America", + result.block().getResult()); + + result = + kernel.runAsync( + ask, + kernel.getSkills().getFunction("Search", null), + kernel.getSkill("SummarizeSkill").getFunction("Summarize", null)); + + Assertions.assertEquals("A-SUMMARY", result.block().getResult()); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example05UsingThePlannerTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example05UsingThePlannerTest.java new file mode 100644 index 0000000000..b3e5d29714 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example05UsingThePlannerTest.java @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClientMatch; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatcher; +import reactor.util.function.Tuples; + +public class Example05UsingThePlannerTest { + + public static SequentialPlanner getPlanner(Kernel kernel) { + kernel.importSkillFromDirectory("SummarizeSkill", "../../samples/skills", "SummarizeSkill"); + kernel.importSkillFromDirectory("WriterSkill", "../../samples/skills", "WriterSkill"); + + return new SequentialPlanner(kernel, null, null); + } + + @Test + public void run() { + ArgumentMatcher matcher = + prompt -> { + return prompt.contains( + "Create an XML plan step by step, to satisfy the goal given"); + }; + + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClientMatch(Tuples.of(matcher, "A-PLAN")); + + Kernel kernel = + SKBuilders.kernel() + .withDefaultAIService( + SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build()) + .build(); + + SequentialPlanner planner = getPlanner(kernel); + System.out.println( + planner.createPlanAsync( + "Write a poem about John Doe, then translate it into Italian.") + .block() + .toEmbeddingString()); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example06TemplateLanguageTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example06TemplateLanguageTest.java new file mode 100644 index 0000000000..2805714b39 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example06TemplateLanguageTest.java @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.coreskills.TimeSkill; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplate; +import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig; +import com.microsoft.semantickernel.textcompletion.CompletionSKFunction; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuples; + +public class Example06TemplateLanguageTest { + + @Test + public void run() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient(Tuples.of("Today is", "A-RESULT")); + + Kernel kernel = + SKBuilders.kernel() + .withDefaultAIService( + SKBuilders.textCompletion() + .withModelId("text-davinci-003") + .withOpenAIClient(client) + .build()) + .build(); + + // Load native skill into the kernel skill collection, sharing its functions + // with prompt + // templates + // Functions loaded here are available as "time.*" + kernel.importSkill(new TimeSkill(), "time"); + + // Semantic Function invoking time.Date and time.Time native functions + String functionDefinition = + "\n" + + "Today is: {{time.Date}}\n" + + "Current time is: {{time.Time}}\n" + + "\n" + + "Answer to the following questions using JSON syntax, including the data" + + " used.\n" + + "Is it morning, afternoon, evening, or night" + + " (morning/afternoon/evening/night)?\n" + + "Is it weekend time (weekend/not weekend)?"; + + PromptTemplate promptRenderer = + SKBuilders.promptTemplate() + .withPromptTemplateConfig(new PromptTemplateConfig()) + .withPromptTemplate(functionDefinition) + .withPromptTemplateEngine(kernel.getPromptTemplateEngine()) + .build(); + + SKContext skContext = SKBuilders.context().withSkills(kernel.getSkills()).build(); + + Mono renderedPrompt = promptRenderer.renderAsync(skContext); + + String renderedText = renderedPrompt.block(); + + // Check that it has been rendered + Assertions.assertTrue(!renderedText.contains("time.Date")); + + // Run the prompt / semantic function + CompletionSKFunction kindOfDay = + kernel.getSemanticFunctionBuilder() + .withKernel(kernel) + .withPromptTemplate(functionDefinition) + .withCompletionConfig( + new PromptTemplateConfig.CompletionConfig(0, 0, 0, 0, 256)) + .build(); + + Assertions.assertEquals("A-RESULT", kindOfDay.invokeAsync("").block().getResult()); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example12SequentialPlannerTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example12SequentialPlannerTest.java new file mode 100644 index 0000000000..e904a97730 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example12SequentialPlannerTest.java @@ -0,0 +1,202 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; // Copyright (c) Microsoft. All rights + +// reserved. + +import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.coreskills.TextSkill; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.planner.PlanningException; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner; +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.io.IOException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import reactor.util.function.Tuples; + +public class Example12SequentialPlannerTest { + @Test + public void poetrySamplesAsync() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient( + Tuples.of( + "Create an XML plan step by step", + "\n" + + "\n" + + "\n" + + "\n" + + ""), + Tuples.of("Generate a short funny poem or limerick", "A POEM"), + Tuples.of( + "Translate the input below into Italian", + "a poem translated to italian")); + + SequentialPlanner planner = getSequentialPlanner(client); + Plan plan = + planner.createPlanAsync( + "Write a poem about John Doe, then translate it into Italian, then" + + " convert it to uppercase.") + .block(); + SKContext result = plan.invokeAsync().block(); + Assertions.assertEquals("A POEM TRANSLATED TO ITALIAN", result.getResult()); + } + + @Test + public void resultIsInvalidXml() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient( + Tuples.of("Create an XML plan step by step", "")); + + SequentialPlanner planner = getSequentialPlanner(client); + Assertions.assertThrows( + PlanningException.class, + () -> { + planner.createPlanAsync( + "Write a poem about John Doe, then translate it into Italian," + + " then convert it to uppercase.") + .block(); + }); + } + + private static SequentialPlanner getSequentialPlanner(OpenAIAsyncClient client) { + Kernel kernel = getKernel(client); + + return new SequentialPlanner(kernel, null, null); + } + + private static Kernel getKernel(OpenAIAsyncClient client) { + Kernel kernel = + SKBuilders.kernel() + .withDefaultAIService( + SKBuilders.textCompletion() + .withModelId("text-davinci-002") + .withOpenAIClient(client) + .build()) + .build(); + + kernel.importSkillFromDirectory("SummarizeSkill", "../../samples/skills", "SummarizeSkill"); + kernel.importSkillFromDirectory("WriterSkill", "../../samples/skills", "WriterSkill"); + kernel.importSkill(new TextSkill(), "TextSkill"); + return kernel; + } + + public static class EmailSkill { + @DefineSKFunction( + name = "SendEmail", + description = "Given an e-mail and message body, send an email") + public void sendEmail( + @SKFunctionInputAttribute(description = "The body of the email message to send.") + String input, + @SKFunctionParameters( + description = "The email address to send email to.", + name = "email_address") + String emailAddress) { + System.out.println("Emailing to " + emailAddress + "\n" + input); + } + + @DefineSKFunction( + name = "GetEmailAddressAsync", + description = "Lookup an email address for a person given a name") + public String getEmailAddressAsync( + @SKFunctionInputAttribute(description = "The name of the person to email.") + String input) { + return "fake@example.com"; + } + } + + @Test + public void emailSamplesAsync() throws IOException { + + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient( + Tuples.of( + "Create an XML plan step by step", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""), + Tuples.of( + "Summarize the following text in two sentences or less", + "Once upon a time, in a faraway kingdom, there lived a kind and" + + " just king named Arjun. He ruled over his kingdom with" + + " fairness and compassion, earning him the love and" + + " admiration of his people. However, the kingdom was plagued" + + " by a terrible dragon that lived in the nearby mountains and" + + " terrorized the nearby villages, burning their crops and" + + " homes. The king had tried everything to defeat the dragon," + + " but to no avail. One day, a young woman named Mira" + + " approached the king and offered to help defeat the dragon." + + " She was a skilled archer and claimed that she had a plan to" + + " defeat the dragon once and for all. The king was skeptical," + + " but desperate for a solution, so he agreed to let her try." + + " Mira set out for the dragon's lair and, with the help of" + + " her trusty bow and arrow, she was able to strike the dragon" + + " with a single shot through its heart, killing it instantly." + + " The people rejoiced and the kingdom was at peace once" + + " again. The king was so grateful to Mira that he asked her" + + " to marry him and she agreed. They ruled the kingdom" + + " together, ruling with fairness and compassion, just as" + + " Arjun had done before. They lived happily ever after, with" + + " the people of the kingdom remembering Mira as the brave" + + " young woman who saved them from the dragon."), + Tuples.of("Translate the input below", "a poem translated to french")); + + Kernel kernel = getKernel(client); + + EmailSkill email = Mockito.spy(new EmailSkill()); + + kernel.importSkill(email, "EmailSkill"); + + SequentialPlanner planner = new SequentialPlanner(kernel, null, null); + + Plan plan = + planner.createPlanAsync( + "Summarize an input, translate to french, and e-mail to John Doe") + .block(); + + System.out.println("Original plan:"); + System.out.println(plan.toPlanString()); + + String input = + "Once upon a time, in a faraway kingdom, there lived a kind and just king named" + + " Arjun. He ruled over his kingdom with fairness and compassion, earning him" + + " the love and admiration of his people. However, the kingdom was plagued by" + + " a terrible dragon that lived in the nearby mountains and terrorized the" + + " nearby villages, burning their crops and homes. The king had tried" + + " everything to defeat the dragon, but to no avail. One day, a young woman" + + " named Mira approached the king and offered to help defeat the dragon. She" + + " was a skilled archer and claimed that she had a plan to defeat the dragon" + + " once and for all. The king was skeptical, but desperate for a solution, so" + + " he agreed to let her try. Mira set out for the dragon's lair and, with the" + + " help of her trusty bow and arrow, she was able to strike the dragon with a" + + " single shot through its heart, killing it instantly. The people rejoiced" + + " and the kingdom was at peace once again. The king was so grateful to Mira" + + " that he asked her to marry him and she agreed. They ruled the kingdom" + + " together, ruling with fairness and compassion, just as Arjun had done" + + " before. They lived happily ever after, with the people of the kingdom" + + " remembering Mira as the brave young woman who saved them from the dragon."; + + plan.invokeAsync(input).block(); + + Mockito.verify(email, Mockito.times(1)) + .sendEmail( + Mockito.matches("a poem translated to french"), + Mockito.matches("fake@example.com")); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example13ConversationSummarySkillTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example13ConversationSummarySkillTest.java new file mode 100644 index 0000000000..f98aeaf92a --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example13ConversationSummarySkillTest.java @@ -0,0 +1,234 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.DefaultKernelTest; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.coreskills.ConversationSummarySkill; +import com.microsoft.semantickernel.orchestration.SKContext; +import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import reactor.util.function.Tuples; + +public class Example13ConversationSummarySkillTest { + private static final String ChatTranscript = + "\n" + + "John: Hello, how are you?\n" + + "Jane: I'm fine, thanks. How are you?\n" + + "John: I'm doing well, writing some example code.\n" + + "Jane: That's great! I'm writing some example code too.\n" + + "John: What are you writing?\n" + + "Jane: I'm writing a chatbot.\n" + + "John: That's cool. I'm writing a chatbot too.\n" + + "Jane: What language are you writing it in?\n" + + "John: I'm writing it in C#.\n" + + "Jane: I'm writing it in Python.\n" + + "John: That's cool. I need to learn Python.\n" + + "Jane: I need to learn C#.\n" + + "John: Can I try out your chatbot?\n" + + "Jane: Sure, here's the link.\n" + + "John: Thanks!\n" + + "Jane: You're welcome.\n" + + "Jane: Look at this poem my chatbot wrote:\n" + + "Jane: Roses are red\n" + + "Jane: Violets are blue\n" + + "Jane: I'm writing a chatbot\n" + + "Jane: What about you?\n" + + "John: That's cool. Let me see if mine will write a poem, too.\n" + + "John: Here's a poem my chatbot wrote:\n" + + "John: The singularity of the universe is a mystery.\n" + + "John: The universe is a mystery.\n" + + "John: The universe is a mystery.\n" + + "John: The universe is a mystery.\n" + + "John: Looks like I need to improve mine, oh well.\n" + + "Jane: You might want to try using a different model.\n" + + "Jane: I'm using the GPT-3 model.\n" + + "John: I'm using the GPT-2 model. That makes sense.\n" + + "John: Here is a new poem after updating the model.\n" + + "John: The universe is a mystery.\n" + + "John: The universe is a mystery.\n" + + "John: The universe is a mystery.\n" + + "John: Yikes, it's really stuck isn't it. Would you help me debug my code?\n" + + "Jane: Sure, what's the problem?\n" + + "John: I'm not sure. I think it's a bug in the code.\n" + + "Jane: I'll take a look.\n" + + "Jane: I think I found the problem.\n" + + "Jane: It looks like you're not passing the right parameters to the model.\n" + + "John: Thanks for the help!\n" + + "Jane: I'm now writing a bot to summarize conversations. I want to make sure it" + + " works when the conversation is long.\n" + + "John: So you need to keep talking with me to generate a long conversation?\n" + + "Jane: Yes, that's right.\n" + + "John: Ok, I'll keep talking. What should we talk about?\n" + + "Jane: I don't know, what do you want to talk about?\n" + + "John: I don't know, it's nice how CoPilot is doing most of the talking for us." + + " But it definitely gets stuck sometimes.\n" + + "Jane: I agree, it's nice that CoPilot is doing most of the talking for us.\n" + + "Jane: But it definitely gets stuck sometimes.\n" + + "John: Do you know how long it needs to be?\n" + + "Jane: I think the max length is 1024 tokens. Which is approximately 1024*4= 4096" + + " characters.\n" + + "John: That's a lot of characters.\n" + + "Jane: Yes, it is.\n" + + "John: I'm not sure how much longer I can keep talking.\n" + + "Jane: I think we're almost there. Let me check.\n" + + "Jane: I have some bad news, we're only half way there.\n" + + "John: Oh no, I'm not sure I can keep going. I'm getting tired.\n" + + "Jane: I'm getting tired too.\n" + + "John: Maybe there is a large piece of text we can use to generate a long" + + " conversation.\n" + + "Jane: That's a good idea. Let me see if I can find one. Maybe Lorem Ipsum?\n" + + "John: Yeah, that's a good idea.\n" + + "Jane: I found a Lorem Ipsum generator.\n" + + "Jane: Here's a 4096 character Lorem Ipsum text:\n" + + "Jane: Lorem ipsum dolor sit amet, con\n" + + "Jane: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc" + + " sit amet aliquam\n" + + "Jane: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc" + + " sit amet aliquam\n" + + "Jane: Darn, it's just repeating stuf now.\n" + + "John: I think we're done.\n" + + "Jane: We're not though! We need like 1500 more characters.\n" + + "John: Oh Cananda, our home and native land.\n" + + "Jane: True patriot love in all thy sons command.\n" + + "John: With glowing hearts we see thee rise.\n" + + "Jane: The True North strong and free.\n" + + "John: From far and wide, O Canada, we stand on guard for thee.\n" + + "Jane: God keep our land glorious and free.\n" + + "John: O Canada, we stand on guard for thee.\n" + + "Jane: O Canada, we stand on guard for thee.\n" + + "Jane: That was fun, thank you. Let me check now.\n" + + "Jane: I think we need about 600 more characters.\n" + + "John: Oh say can you see?\n" + + "Jane: By the dawn's early light.\n" + + "John: What so proudly we hailed.\n" + + "Jane: At the twilight's last gleaming.\n" + + "John: Whose broad stripes and bright stars.\n" + + "Jane: Through the perilous fight.\n" + + "John: O'er the ramparts we watched.\n" + + "Jane: Were so gallantly streaming.\n" + + "John: And the rockets' red glare.\n" + + "Jane: The bombs bursting in air.\n" + + "John: Gave proof through the night.\n" + + "Jane: That our flag was still there.\n" + + "John: Oh say does that star-spangled banner yet wave.\n" + + "Jane: O'er the land of the free.\n" + + "John: And the home of the brave.\n" + + "Jane: Are you a Seattle Kraken Fan?\n" + + "John: Yes, I am. I love going to the games.\n" + + "Jane: I'm a Seattle Kraken Fan too. Who is your favorite player?\n" + + "John: I like watching all the players, but I think my favorite is Matty" + + " Beniers.\n" + + "Jane: Yeah, he's a great player. I like watching him too. I also like watching" + + " Jaden Schwartz.\n" + + "John: Adam Larsson is another good one. The big cat!\n" + + "Jane: WE MADE IT! It's long enough. Thank you!\n" + + "John: Can you automate generating long text next time?\n" + + "Jane: I will.\n" + + "John: You're welcome. I'm glad we could help. Goodbye!\n" + + "Jane: Goodbye!"; + + @Test + public void conversationSummarySkillAsync() { + + OpenAIAsyncClient client = + DefaultKernelTest.mockCompletionOpenAIAsyncClientMatch( + Tuples.of( + arg -> { + Assertions.assertTrue( + arg.contains("Summarize the conversation")); + return arg.contains("Hello, how are you"); + }, + "Summary of first half"), + Tuples.of( + arg -> { + Assertions.assertTrue( + arg.contains("Summarize the conversation")); + return arg.contains("I think we're almost there"); + }, + "Summary of second half")); + + Kernel kernel = DefaultKernelTest.buildKernel("model", client); + + ReadOnlyFunctionCollection conversationSummarySkill = + kernel.importSkill(new ConversationSummarySkill(kernel), null); + + SKContext summary = + conversationSummarySkill + .getFunction("SummarizeConversation") + .invokeAsync(ChatTranscript) + .block(); + + Assertions.assertTrue(summary.getResult().contains("Summary of first half")); + Assertions.assertTrue(summary.getResult().contains("Summary of second half")); + } + + @Test + public void getConversationActionItemsAsync() { + + OpenAIAsyncClient client = + DefaultKernelTest.mockCompletionOpenAIAsyncClientMatch( + Tuples.of( + arg -> { + Assertions.assertTrue( + arg.contains("You are an action item extractor")); + return arg.contains("Hello, how are you"); + }, + "An action item"), + Tuples.of( + arg -> { + Assertions.assertTrue( + arg.contains("You are an action item extractor")); + return arg.contains("I think we're almost there"); + }, + "Another action item")); + + Kernel kernel = DefaultKernelTest.buildKernel("model", client); + + ReadOnlyFunctionCollection conversationSummarySkill = + kernel.importSkill(new ConversationSummarySkill(kernel), null); + + SKContext summary = + conversationSummarySkill + .getFunction("GetConversationActionItems") + .invokeAsync(ChatTranscript) + .block(); + + Assertions.assertTrue(summary.getResult().contains("An action item")); + Assertions.assertTrue(summary.getResult().contains("Another action item")); + } + + @Test + public void getConversationTopicsAsync() { + + OpenAIAsyncClient client = + DefaultKernelTest.mockCompletionOpenAIAsyncClientMatch( + Tuples.of( + arg -> { + Assertions.assertTrue(arg.contains("extract key topics")); + return arg.contains("Hello, how are you"); + }, + "A topic"), + Tuples.of( + arg -> { + Assertions.assertTrue(arg.contains("extract key topics")); + return arg.contains("I think we're almost there"); + }, + "Another topic")); + + Kernel kernel = DefaultKernelTest.buildKernel("model", client); + + ReadOnlyFunctionCollection conversationSummarySkill = + kernel.importSkill(new ConversationSummarySkill(kernel), null); + + SKContext summary = + conversationSummarySkill + .getFunction("GetConversationTopics") + .invokeAsync(ChatTranscript) + .block(); + + Assertions.assertTrue(summary.getResult().contains("A topic")); + Assertions.assertTrue(summary.getResult().contains("Another topic")); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example17ChatGPTTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example17ChatGPTTest.java new file mode 100644 index 0000000000..e0456c630a --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example17ChatGPTTest.java @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.models.ChatChoice; +import com.azure.ai.openai.models.ChatCompletions; +import com.azure.ai.openai.models.ChatMessage; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.chatcompletion.ChatHistory; +import com.microsoft.semantickernel.connectors.ai.openai.chatcompletion.OpenAIChatHistory; +import java.util.Arrays; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuples; + +public class Example17ChatGPTTest { + + @Test + public void azureOpenAIChatSampleAsync() { + + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient(Tuples.of("Today is", "A-RESULT")); + + String message = "Hi, I'm looking for book suggestions"; + String secondMessage = + "I love history and philosophy, I'd like to learn something new about Greece, any" + + " suggestion?"; + + mockResponse(client, message, "1st response"); + mockResponse(client, secondMessage, "2nd response"); + + Kernel kernel = + SKBuilders.kernel() + .withDefaultAIService( + SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("gpt-3.5-turbo-0301") + .build()) + .build(); + + ChatCompletion chatGPT = kernel.getService(null, ChatCompletion.class); + + OpenAIChatHistory chatHistory = + chatGPT.createNewChat("You are a librarian, expert about books"); + + // First user message + chatHistory.addUserMessage(message); + ChatHistory.Message createdMessage = + chatHistory.getMessages().get(chatHistory.getMessages().size() - 1); + Assertions.assertEquals(ChatHistory.AuthorRoles.User, createdMessage.getAuthorRoles()); + Assertions.assertEquals(message, createdMessage.getContent()); + + // First bot assistant message + String reply = chatGPT.generateMessageAsync(chatHistory, null).block(); + Assertions.assertEquals("1st response", reply); + chatHistory.addAssistantMessage(reply); + + // Second user message + chatHistory.addUserMessage(secondMessage); + + // Second bot assistant message + reply = chatGPT.generateMessageAsync(chatHistory, null).block(); + Assertions.assertEquals("2nd response", reply); + } + + public static void mockResponse(OpenAIAsyncClient client, String message, String response) { + ChatMessage chatMessage = Mockito.mock(ChatMessage.class); + ChatChoice chatChoice = Mockito.mock(ChatChoice.class); + ChatCompletions completion = Mockito.mock(ChatCompletions.class); + + Mockito.when(completion.getChoices()).thenReturn(Arrays.asList(chatChoice)); + + Mockito.when(chatChoice.getMessage()).thenReturn(chatMessage); + + Mockito.when(chatMessage.getContent()).thenReturn(response); + + Mockito.when( + client.getChatCompletions( + Mockito.any(), + Mockito.argThat( + msg -> { + return msg != null + && msg.getMessages() + .get(msg.getMessages().size() - 1) + .getContent() + .equals(message); + }))) + .thenReturn(Mono.just(completion)); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example28ActionPlannerTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example28ActionPlannerTest.java new file mode 100644 index 0000000000..d56b9f1129 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example28ActionPlannerTest.java @@ -0,0 +1,139 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.DefaultKernelTest; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.planner.PlanningException; +import com.microsoft.semantickernel.planner.actionplanner.ActionPlanner; +import com.microsoft.semantickernel.planner.actionplanner.Plan; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import reactor.util.function.Tuples; + +public class Example28ActionPlannerTest { + + @Test + public void functionsArePassedToRequest() { + OpenAIAsyncClient client = + DefaultKernelTest.mockCompletionOpenAIAsyncClientMatchAndAssert( + Tuples.of( + arg -> arg.contains("Generate a short funny"), + "A-RESULT", + arg -> {}), + Tuples.of( + arg -> arg.contains("plan"), + "{\"plan\":{\n" + + "\"rationale\": \"the list contains a function that can turn" + + " a scenario into a short and entertaining poem\",\n" + + "\"function\": \"WriterSkill.ShortPoem\",\n" + + "\"parameters\": {\n" + + "\"input\": \"Cleopatra\"\n" + + "}}}", + request -> { + Assertions.assertTrue( + request.contains("WriterSkill.NovelOutline")); + Assertions.assertTrue( + request.contains("WriterSkill.Brainstorm")); + Assertions.assertTrue(request.contains("WriterSkill.Acronym")); + Assertions.assertTrue( + request.contains("WriterSkill.ShortPoem")); + Assertions.assertTrue(request.contains("WriterSkill.EmailTo")); + Assertions.assertTrue(request.contains("WriterSkill.EmailGen")); + Assertions.assertTrue(request.contains("WriterSkill.Rewrite")); + Assertions.assertTrue( + request.contains("WriterSkill.Translate")); + + Assertions.assertTrue( + request.contains("SummarizeSkill.Topics")); + Assertions.assertTrue( + request.contains( + "SummarizeSkill.MakeAbstractReadable")); + Assertions.assertTrue( + request.contains("SummarizeSkill.Notegen")); + Assertions.assertTrue( + request.contains("SummarizeSkill.Summarize")); + Assertions.assertTrue( + request.contains("SummarizeSkill.Topics")); + })); + + ActionPlanner planner = createPlanner(client); + String goal = "Write a poem about Cleopatra."; + Plan plan = planner.createPlanAsync(goal).block(); + String planResult = plan.invokeAsync(goal).block().getResult(); + Assertions.assertEquals("A-RESULT", planResult); + } + + @Test + public void runActionPlan() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient( + Tuples.of("Generate a short funny", "A-RESULT"), + Tuples.of( + "plan", + "{\"plan\":{\n" + + "\"rationale\": \"the list contains a function that can turn" + + " a scenario into a short and entertaining poem\",\n" + + "\"function\": \"WriterSkill.ShortPoem\",\n" + + "\"parameters\": {\n" + + "\"input\": \"Cleopatra\"\n" + + "}}}")); + + ActionPlanner planner = createPlanner(client); + String goal = "Write a poem about Cleopatra."; + Plan plan = planner.createPlanAsync(goal).block(); + String planResult = plan.invokeAsync(goal).block().getResult(); + Assertions.assertEquals("A-RESULT", planResult); + } + + @Test + public void resultIsAnonExistentFunction() { + OpenAIAsyncClient client = + mockCompletionOpenAIAsyncClient( + Tuples.of( + "plan", + "{\n" + + " \"plan\" : {\n" + + " \"function\" : \"TextSkill.md5sum\",\n" + + " \"parameters\" : {\n" + + " \"input\" : \"Cleopatra\"\n" + + " },\n" + + " \"rationale\" : \"the list contains a function that" + + " can calculate the md5sum of a string\"\n" + + " }\n" + + "}\n")); + + ActionPlanner planner = createPlanner(client); + String goal = "Write a poem about Cleopatra."; + + Assertions.assertThrows( + PlanningException.class, + () -> { + Plan plan = planner.createPlanAsync(goal).block(); + String planResult = plan.invokeAsync(goal).block().getResult(); + Assertions.assertEquals("A-RESULT", planResult); + }); + } + + public static ActionPlanner createPlanner(OpenAIAsyncClient client) { + Kernel kernel = + SKBuilders.kernel() + .withDefaultAIService( + SKBuilders.textCompletion() + .withModelId("text-davinci-002") + .withOpenAIClient(client) + .build()) + .build(); + + kernel.importSkillFromDirectory("SummarizeSkill", "../../samples/skills", "SummarizeSkill"); + kernel.importSkillFromDirectory("WriterSkill", "../../samples/skills", "WriterSkill"); + + // Create an instance of ActionPlanner. + // The ActionPlanner takes one goal and returns a single function to execute. + ActionPlanner planner = new ActionPlanner(kernel, null); + return planner; + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example33StreamingChatTest.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example33StreamingChatTest.java new file mode 100644 index 0000000000..a07caef48a --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Example33StreamingChatTest.java @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +import static com.microsoft.semantickernel.chatcompletion.ChatHistory.AuthorRoles.Assistant; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.semantickernel.DefaultKernelTest; +import com.microsoft.semantickernel.SKBuilders; +import com.microsoft.semantickernel.chatcompletion.ChatCompletion; +import com.microsoft.semantickernel.chatcompletion.ChatHistory; +import java.util.function.BiFunction; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; +import reactor.util.function.Tuples; + +public class Example33StreamingChatTest { + + @Test + public void streamingChatAsync() { + OpenAIAsyncClient client = + DefaultKernelTest.mockCompletionOpenAIAsyncClientMatch( + Tuples.of( + request -> + request.contains("You are a librarian") + && !request.contains( + "I love history and philosophy"), + "First response"), + Tuples.of( + request -> + request.contains("You are a librarian") + && request.contains( + "I love history and philosophy"), + "Second response")); + + ChatCompletion chatCompletion = + SKBuilders.chatCompletion() + .withOpenAIClient(client) + .withModelId("gpt-35-turbo") + .build(); + + ChatHistory chatHistory = + chatCompletion.createNewChat("You are a librarian, expert about books"); + + // First user message + chatHistory.addMessage( + ChatHistory.AuthorRoles.User, "Hi, I'm looking for book suggestions"); + + // First bot assistant message + String response = streamMessageOutputAsync(chatCompletion, chatHistory, Assistant).block(); + Assertions.assertEquals("First response", response); + + // Second user message + chatHistory.addMessage( + ChatHistory.AuthorRoles.User, + "I love history and philosophy, I'd like to learn something new about Greece, any" + + " suggestion?"); + + // Second bot assistant message + response = streamMessageOutputAsync(chatCompletion, chatHistory, Assistant).block(); + Assertions.assertEquals("Second response", response); + } + + private static Mono streamMessageOutputAsync( + ChatCompletion chatGPT, ChatHistory chatHistory, ChatHistory.AuthorRoles authorRole) { + BiFunction agg = (o, o2) -> o + o2; + + return chatGPT.generateMessageStream(chatHistory, null).reduce("", agg); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Examples.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Examples.java new file mode 100644 index 0000000000..11fea84f49 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/Examples.java @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples; + +public class Examples {} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/skills/SearchEngineSkill.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/skills/SearchEngineSkill.java new file mode 100644 index 0000000000..d94b5450a0 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/skills/SearchEngineSkill.java @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples.skills; + +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import reactor.core.publisher.Mono; + +public class SearchEngineSkill { + + @DefineSKFunction(description = "Append the day variable", name = "search") + public Mono search( + @SKFunctionInputAttribute(description = "Text to search") String input) { + return Mono.just("Gran Torre Santiago is the tallest building in South America"); + } +} diff --git a/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/skills/StaticTextSkill.java b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/skills/StaticTextSkill.java new file mode 100644 index 0000000000..1cdf21e9b0 --- /dev/null +++ b/java/semantickernel-core/src/test/java/com/microsoft/semantickernel/syntaxexamples/skills/StaticTextSkill.java @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.syntaxexamples.skills; + +import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionInputAttribute; +import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters; +import java.util.Locale; +import reactor.core.publisher.Mono; + +public class StaticTextSkill { + + @DefineSKFunction(description = "Change all string chars to uppercase.", name = "Uppercase") + public static Mono uppercase( + @SKFunctionInputAttribute(description = "Text to uppercase") String text) { + return Mono.just(text.toUpperCase(Locale.ROOT)); + } + + @DefineSKFunction(description = "Append the day variable", name = "appendDay") + public Mono appendDay( + @SKFunctionInputAttribute(description = "Text to append to") String input, + @SKFunctionParameters(description = "Current day", name = "day") String day) { + return Mono.just(input + day); + } +} diff --git a/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response1.txt b/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response1.txt new file mode 100644 index 0000000000..18b36dbe61 --- /dev/null +++ b/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response1.txt @@ -0,0 +1,4 @@ +[THOUGHT PROCESS] + +[QUESTION] +What year did the first world cup take place? diff --git a/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response2.txt b/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response2.txt new file mode 100644 index 0000000000..76c35d0b89 --- /dev/null +++ b/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response2.txt @@ -0,0 +1,2 @@ +[THOUGHT] To answer this question, we need to find out the year of the first world cup and then divide it by 2. We can use a web search to find the year of the first world cup and then perform the necessary calculation. +[ACTION] {{"action": "WebSearch.search","action_variables": {"query":"first world cup year","count":"1"}}} \ No newline at end of file diff --git a/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response3.txt b/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response3.txt new file mode 100644 index 0000000000..3eb1a7d24f --- /dev/null +++ b/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response3.txt @@ -0,0 +1,2 @@ +[THOUGHT] Now that we know the year of the first world cup is 1930, we can divide it by 2 to get the answer to the original question. +[ACTION] {{"action": "AdvancedCalculator.Calculator","action_variables": {"input":"1930/2"}}} \ No newline at end of file diff --git a/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response4.txt b/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response4.txt new file mode 100644 index 0000000000..eb869bc5f0 --- /dev/null +++ b/java/semantickernel-core/src/test/resources/com/microsoft/semantickernel/planner/stepwiseplanner/response4.txt @@ -0,0 +1,2 @@ +[FINAL ANSWER] +The year of the first world cup is 1930, and when divided by 2, the result is 965. \ No newline at end of file diff --git a/java/semantickernel-core/src/test/resources/log4j2.xml b/java/semantickernel-core/src/test/resources/log4j2.xml new file mode 100644 index 0000000000..50a638f0dc --- /dev/null +++ b/java/semantickernel-core/src/test/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/semantickernel-core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/java/semantickernel-core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..ca6ee9cea8 --- /dev/null +++ b/java/semantickernel-core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file diff --git a/java/semantickernel-extensions-parent/pom.xml b/java/semantickernel-extensions-parent/pom.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/java/semantickernel-extensions-parent/semantickernel-sequentialplanner-extension/pom.xml b/java/semantickernel-extensions-parent/semantickernel-sequentialplanner-extension/pom.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/java/spotbugs-exclude.xml b/java/spotbugs-exclude.xml new file mode 100644 index 0000000000..180519797a --- /dev/null +++ b/java/spotbugs-exclude.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/java/JavaReferenceSkill/pom.xml b/samples/java/JavaReferenceSkill/pom.xml index 9161cfc1cb..0ea2afe1c8 100644 --- a/samples/java/JavaReferenceSkill/pom.xml +++ b/samples/java/JavaReferenceSkill/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.microsoft.semantickernel.skills.random + com.microsoft.semantic-kernel.skills.random JavaReferenceSkill 1.0-SNAPSHOT From c9fe829686de9e0c32092aba92478f0e62b6a2ad Mon Sep 17 00:00:00 2001 From: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Date: Fri, 3 Nov 2023 13:53:40 +0000 Subject: [PATCH 002/576] Run markdown link check and spell check on PR's to the java-development branch (#3372) ### Motivation and Context Currently these checks only run on PR's to main which means that when we try to merge `java-development` to main we have to fix these issues. We need to catch these issues when code is merged to `java-development` so they can be fixed by the person who introduces the issue. ### Description Enable markdown link and spell checks for PR's to the `java-development` branch. ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone :smile: --- .github/workflows/markdown-link-check.yml | 18 +++++++++--------- .github/workflows/typos.yaml | 16 ++++++++-------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/markdown-link-check.yml b/.github/workflows/markdown-link-check.yml index 4e02c72566..2cea71de53 100644 --- a/.github/workflows/markdown-link-check.yml +++ b/.github/workflows/markdown-link-check.yml @@ -3,8 +3,8 @@ name: Check .md links on: workflow_dispatch: pull_request: - branches: [ "main" ] - + branches: ["main", "java-development"] + permissions: contents: read @@ -13,11 +13,11 @@ jobs: runs-on: ubuntu-latest # check out the latest version of the code steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - # Checks the status of hyperlinks in .md files in verbose mode - - name: Check links - uses: gaurav-nelson/github-action-markdown-link-check@v1 - with: - use-verbose-mode: 'yes' - config-file: ".github/workflows/markdown-link-check-config.json" + # Checks the status of hyperlinks in .md files in verbose mode + - name: Check links + uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + use-verbose-mode: "yes" + config-file: ".github/workflows/markdown-link-check-config.json" diff --git a/.github/workflows/typos.yaml b/.github/workflows/typos.yaml index 94931d48b5..e19b7cd61f 100644 --- a/.github/workflows/typos.yaml +++ b/.github/workflows/typos.yaml @@ -12,18 +12,18 @@ name: Spell Check on: workflow_dispatch: pull_request: - branches: [ "main", "feature*" ] + branches: ["main", "java-development", "feature*"] jobs: run: name: Spell Check with Typos runs-on: ubuntu-latest steps: - - name: Check out code - uses: actions/checkout@v4 + - name: Check out code + uses: actions/checkout@v4 - - name: Use custom config file - uses: crate-ci/typos@master - with: - config: .github/_typos.toml - write_changes: false + - name: Use custom config file + uses: crate-ci/typos@master + with: + config: .github/_typos.toml + write_changes: false From 1fd1a530adfc78b294101570ca04418868d88097 Mon Sep 17 00:00:00 2001 From: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Date: Fri, 3 Nov 2023 19:24:29 +0000 Subject: [PATCH 003/576] Update the readme to reference Java in main branch (#3377) ### Motivation and Context ### Description ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ddab6c95ce..563530d5d0 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ feature parity between our currently supported languages. Java logo @@ -80,8 +80,9 @@ from either OpenAI or Azure OpenAI and to run one of the C#, Python, and Java co ### For Java: -1. Clone and checkout the experimental Java branch: `git clone -b experimental-java https://github.com/microsoft/semantic-kernel.git` -2. Follow the instructions [here](https://github.com/microsoft/semantic-kernel/blob/experimental-java/java/samples/sample-code/README.md) +1. Clone the repository: `git clone https://github.com/microsoft/semantic-kernel.git` + 1. To access the latest Java code, clone and checkout the Java development branch: `git clone -b java-development https://github.com/microsoft/semantic-kernel.git` +2. Follow the instructions [here](https://github.com/microsoft/semantic-kernel/blob/main/java/samples/sample-code/README.md) ## Learning how to use Semantic Kernel From 23dd5257d4c568f7b29616772a0bb93837e9ffc6 Mon Sep 17 00:00:00 2001 From: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:11:50 +0000 Subject: [PATCH 004/576] .Net: Replace IPromptTemplateEngine with IPromptTemplateFactory Update prompt rendering and template engine in dotnet samples (#3348) ### Motivation and Context Making this change to enable support for multiple prompt template formats See https://github.com/microsoft/semantic-kernel/blob/main/docs/decisions/0014-custom-prompt-template-formats.md ### Description ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone :smile: ## Summary This pull request updates the prompt rendering and template engine in the dotnet samples. Specifically, it replaces the PromptTemplate class with the BasicPromptTemplate class, updates the RunSemanticFunctionAsync method to use the new class, and removes the PromptTemplateEngineTests class which is now obsolete. Additionally, a new BasicPromptTemplateFactory class is introduced to create instances of the BasicPromptTemplate class. ## Changes - Replaced PromptTemplate class with BasicPromptTemplate class - Updated RunSemanticFunctionAsync method to use BasicPromptTemplate class - Removed PromptTemplateEngineTests class as it is now obsolete - Introduced BasicPromptTemplateFactory class to create instances of BasicPromptTemplate class --- *Powered by [Microsoft Semantic Kernel](https://github.com/microsoft/semantic-kernel)* --- .../0016-custom-prompt-template-formats.md | 289 ++++++++++++ ...emantic-function-multiple-model-support.md | 172 +++++++ .../Example06_TemplateLanguage.cs | 6 +- .../Example07_BingAndGooglePlugins.cs | 6 +- .../Example30_ChatWithPrompts.cs | 9 +- .../Example40_DIContainer.cs | 4 - .../Example42_KernelBuilder.cs | 4 +- ...ateNativeFunctionsWithMultipleArguments.cs | 6 +- .../Example62_CustomAIServiceSelector.cs | 5 +- .../Prompt/BasicPromptTemplateFactoryTests.cs | 53 +++ .../Prompt/BasicPromptTemplateTests.cs | 418 ++++++++++++++++++ .../Prompt/PromptTemplateEngineTests.cs | 2 + .../BasicPromptTemplate.cs | 167 +++++++ .../BasicPromptTemplateEngine.cs | 6 +- .../BasicPromptTemplateFactory.cs | 35 ++ .../KernelBasicPromptTemplateExtensions.cs | 55 +++ .../TemplateEngine.Basic.csproj | 2 +- .../OpenAI/OpenAICompletionTests.cs | 6 +- .../KernelSemanticFunctionExtensionsTests.cs | 3 - .../PromptTemplateEngineTests.cs | 2 + .../Sequential/SequentialPlanParserTests.cs | 3 +- .../Sequential/SequentialPlannerTests.cs | 18 +- .../Planners.Core/Stepwise/StepwisePlanner.cs | 11 +- .../SemanticKernel.Abstractions/IKernel.cs | 12 +- .../TemplateEngine/IPromptTemplate.cs | 2 +- .../TemplateEngine/IPromptTemplateEngine.cs | 4 + .../TemplateEngine/IPromptTemplateFactory.cs | 21 + .../TemplateEngine/PromptTemplateConfig.cs | 23 +- .../KernelSemanticFunctionExtensions.cs | 139 +++++- dotnet/src/SemanticKernel.Core/Kernel.cs | 119 ++++- .../src/SemanticKernel.Core/KernelBuilder.cs | 82 +--- .../AggregatorPromptTemplateFactory.cs | 56 +++ .../TemplateEngine/PromptTemplate.cs | 12 +- .../AggregatorPromptTemplateFactoryTests.cs | 114 +++++ 34 files changed, 1708 insertions(+), 158 deletions(-) create mode 100644 docs/decisions/0016-custom-prompt-template-formats.md create mode 100644 docs/decisions/0017-semantic-function-multiple-model-support.md create mode 100644 dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/BasicPromptTemplateFactoryTests.cs create mode 100644 dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/BasicPromptTemplateTests.cs create mode 100644 dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplate.cs create mode 100644 dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplateFactory.cs create mode 100644 dotnet/src/Extensions/TemplateEngine.Basic/Extensions/KernelBasicPromptTemplateExtensions.cs create mode 100644 dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplateFactory.cs rename dotnet/src/{SemanticKernel.Core => SemanticKernel.Abstractions}/TemplateEngine/PromptTemplateConfig.cs (89%) create mode 100644 dotnet/src/SemanticKernel.Core/TemplateEngine/AggregatorPromptTemplateFactory.cs create mode 100644 dotnet/src/SemanticKernel.UnitTests/TemplateEngine/AggregatorPromptTemplateFactoryTests.cs diff --git a/docs/decisions/0016-custom-prompt-template-formats.md b/docs/decisions/0016-custom-prompt-template-formats.md new file mode 100644 index 0000000000..5ebb5a5e97 --- /dev/null +++ b/docs/decisions/0016-custom-prompt-template-formats.md @@ -0,0 +1,289 @@ +--- +status: approved +contact: markwallace-microsoft +date: 2023-10-26 +deciders: mabolan, markwallace-microsoft, semenshi, rbarreto +consulted: dmytrostruk +informed: +--- +# Custom Prompt Template Formats + +## Context and Problem Statement + +Semantic Kernel currently supports a custom prompt template language that allows for variable interpolation and function execution. +Semantic Kernel allows for custom prompt template formats to be integrated e.g., prompt templates using [Handlebars](https://handlebarsjs.com/) syntax. + +The purpose of this ADR is to describe how a custom prompt template formats will be supported in the Semantic Kernel. + +### Current Design + +By default the `Kernel` uses the `BasicPromptTemplateEngine` which supports the Semantic Kernel specific template format. + +#### Code Patterns + +Below is an expanded example of how to create a semantic function from a prompt template string which uses the built-in Semantic Kernel format: + +```csharp +IKernel kernel = Kernel.Builder + .WithPromptTemplateEngine(new BasicPromptTemplateEngine()) + .WithOpenAIChatCompletionService( + modelId: openAIModelId, + apiKey: openAIApiKey) + .Build(); + +kernel.ImportFunctions(new TimePlugin(), "time"); + +string templateString = "Today is: {{time.Date}} Is it weekend time (weekend/not weekend)?"; +var promptTemplateConfig = new PromptTemplateConfig(); +var promptTemplate = new PromptTemplate(templateString, promptTemplateConfig, kernel.PromptTemplateEngine); +var kindOfDay = kernel.RegisterSemanticFunction("KindOfDay", promptTemplateConfig, promptTemplate); + +var result = await kernel.RunAsync(kindOfDay); +Console.WriteLine(result.GetValue()); +``` + +We have an extension method `var kindOfDay = kernel.CreateSemanticFunction(promptTemplate);` to simplify the process to create and register a semantic function but the expanded format is shown above to highlight the dependency on `kernel.PromptTemplateEngine`. +Also the `BasicPromptTemplateEngine` is the default prompt template engine and will be loaded automatically if the package is available and not other prompt template engine is specified. + +Some issues with this: + +1. `Kernel` only supports a single `IPromptTemplateEngine` so we cannot support using multiple prompt templates at the same time. +1. `IPromptTemplateEngine` is stateless and must perform a parse of the template for each render +1. Our semantic function extension methods relay on our implementation of `IPromptTemplate` (i.e., `PromptTemplate`) which stores the template string and uses the `IPromptTemplateEngine` to render it every time. Note implementations of `IPromptTemplate` are currently stateful as they also store the parameters. + +#### Performance + +The `BasicPromptTemplateEngine` uses the `TemplateTokenizer` to parse the template i.e. extract the blocks. +Then it renders the template i.e. inserts variables and executes functions. Some sample timings for these operations: + +| Operation | Ticks | Milliseconds | +|------------------|---------|--------------| +| Extract blocks | 1044427 | 103 | +| Render variables | 168 | 0 | + +Sample template used was: `"{{variable1}} {{variable2}} {{variable3}} {{variable4}} {{variable5}}"` + +**Note: We will use the sample implementation to support the f-string template format.** + +Using `HandlebarsDotNet` for the same use case results in the following timings: + +| Operation | Ticks | Milliseconds | +|------------------|---------|--------------| +| Compile template | 66277 | 6 | +| Render variables | 4173 | 0 | + +**By separating the extract blocks/compile from the render variables operation it will be possible to optimise performance by compiling templates just once.** + +#### Implementing a Custom Prompt Template Engine + +There are two interfaces provided: + +```csharp +public interface IPromptTemplateEngine +{ + Task RenderAsync(string templateText, SKContext context, CancellationToken cancellationToken = default); +} + +public interface IPromptTemplate +{ + IReadOnlyList Parameters { get; } + + public Task RenderAsync(SKContext executionContext, CancellationToken cancellationToken = default); +} +``` + +A prototype implementation of a handlebars prompt template engine could look something like this: + +```csharp +public class HandlebarsTemplateEngine : IPromptTemplateEngine +{ + private readonly ILoggerFactory _loggerFactory; + + public HandlebarsTemplateEngine(ILoggerFactory? loggerFactory = null) + { + this._loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; + } + + public async Task RenderAsync(string templateText, SKContext context, CancellationToken cancellationToken = default) + { + var handlebars = HandlebarsDotNet.Handlebars.Create(); + + var functionViews = context.Functions.GetFunctionViews(); + foreach (FunctionView functionView in functionViews) + { + var skfunction = context.Functions.GetFunction(functionView.PluginName, functionView.Name); + handlebars.RegisterHelper($"{functionView.PluginName}_{functionView.Name}", async (writer, hcontext, parameters) => + { + var result = await skfunction.InvokeAsync(context).ConfigureAwait(true); + writer.WriteSafeString(result.GetValue()); + }); + } + + var template = handlebars.Compile(templateText); + + var prompt = template(context.Variables); + + return await Task.FromResult(prompt).ConfigureAwait(true); + } +} +``` + +**Note: This is just a prototype implementation for illustration purposes only.** + +Some issues: + +1. The `IPromptTemplate` interface is not used and causes confusion. +1. There is no way to allow developers to support multiple prompt template formats at the same time. + + +There is one implementation of `IPromptTemplate` provided in the Semantic Kernel core package. +The `RenderAsync` implementation just delegates to the `IPromptTemplateEngine`. +The `Parameters` list get's populated with the parameters defined in the `PromptTemplateConfig` and any missing variables defined in the template. + +#### Handlebars Considerations + +Handlebars does not support dynamic binding of helpers. Consider the following snippet: + +```csharp +HandlebarsHelper link_to = (writer, context, parameters) => +{ + writer.WriteSafeString($"{context["text"]}"); +}; + +string source = @"Click here: {{link_to}}"; + +var data = new +{ + url = "https://github.com/rexm/handlebars.net", + text = "Handlebars.Net" +}; + +// Act +var handlebars = HandlebarsDotNet.Handlebars.Create(); +handlebars.RegisterHelper("link_to", link_to); +var template = handlebars1.Compile(source); +// handlebars.RegisterHelper("link_to", link_to); This also works +var result = template1(data); +``` + +Handlebars allows the helpers to be registered with the `Handlebars` instance either before or after a template is compiled. +The optimum would be to have a shared `Handlebars` instance for a specific collection of functions and register the helpers just once. +For use cases where the Kernel function collection may have been mutated we will be forced to create a `Handlebars` instance at render time +and then register the helpers. This means we cannot take advantage of the performance improvement provided by compiling the template. + +## Decision Drivers + +In no particular order: + +* Support creating a semantic function without a `IKernel`instance. +* Support late binding of functions i.e., having functions resolved when the prompt is rendered. +* Support allowing the prompt template to be parsed (compiled) just once to optimize performance if needed. +* Support using multiple prompt template formats with a single `Kernel` instance. +* Provide simple abstractions which allow third parties to implement support for custom prompt template formats. + +## Considered Options + +* Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory`. +* + +### Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory` + +ISKFunction class relationships + +Below is an expanded example of how to create a semantic function from a prompt template string which uses the built-in Semantic Kernel format: + +```csharp +// Semantic function can be created once +var promptTemplateFactory = new BasicPromptTemplateFactory(); +string templateString = "Today is: {{time.Date}} Is it weekend time (weekend/not weekend)?"; +var promptTemplateConfig = new PromptTemplateConfig(); +// Line below will replace the commented out code +var promptTemplate = promptTemplateFactory.CreatePromptTemplate(templateString, promptTemplateConfig); +var kindOfDay = ISKFunction.CreateSemanticFunction("KindOfDay", promptTemplateConfig, promptTemplate) +// var promptTemplate = new PromptTemplate(promptTemplate, promptTemplateConfig, kernel.PromptTemplateEngine); +// var kindOfDay = kernel.RegisterSemanticFunction("KindOfDay", promptTemplateConfig, promptTemplate); + +// Create Kernel after creating the semantic function +// Later we will support passing a function collection to the KernelBuilder +IKernel kernel = Kernel.Builder + .WithOpenAIChatCompletionService( + modelId: openAIModelId, + apiKey: openAIApiKey) + .Build(); + +kernel.ImportFunctions(new TimePlugin(), "time"); +// Optionally register the semantic function with the Kernel +kernel.RegisterCustomFunction(kindOfDay); + +var result = await kernel.RunAsync(kindOfDay); +Console.WriteLine(result.GetValue()); +``` + +**Notes:** + +* `BasicPromptTemplateFactory` will be the default implementation and will be automatically provided in `KernelSemanticFunctionExtensions`. Developers will also be able to provide their own implementation. +* The factory uses the new `PromptTemplateConfig.TemplateFormat` to create the appropriate `IPromptTemplate` instance. +* We should look to remove `promptTemplateConfig` as a parameter to `CreateSemanticFunction`. That change is outside of the scope of this ADR. + +The `BasicPromptTemplateFactory` and `BasicPromptTemplate` implementations look as follows: + +```csharp +public sealed class BasicPromptTemplateFactory : IPromptTemplateFactory +{ + private readonly IPromptTemplateFactory _promptTemplateFactory; + private readonly ILoggerFactory _loggerFactory; + + public BasicPromptTemplateFactory(IPromptTemplateFactory promptTemplateFactory, ILoggerFactory? loggerFactory = null) + { + this._promptTemplateFactory = promptTemplateFactory; + this._loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; + } + + public IPromptTemplate? CreatePromptTemplate(string templateString, PromptTemplateConfig promptTemplateConfig) + { + if (promptTemplateConfig.TemplateFormat.Equals(PromptTemplateConfig.SEMANTICKERNEL, System.StringComparison.Ordinal)) + { + return new BasicPromptTemplate(templateString, promptTemplateConfig, this._loggerFactory); + } + else if (this._promptTemplateFactory is not null) + { + return this._promptTemplateFactory.CreatePromptTemplate(templateString, promptTemplateConfig); + } + + throw new SKException($"Invalid prompt template format {promptTemplateConfig.TemplateFormat}"); + } +} + +public sealed class BasicPromptTemplate : IPromptTemplate +{ + public BasicPromptTemplate(string templateString, PromptTemplateConfig promptTemplateConfig, ILoggerFactory? loggerFactory = null) + { + this._loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; + this._logger = this._loggerFactory.CreateLogger(typeof(BasicPromptTemplate)); + this._templateString = templateString; + this._promptTemplateConfig = promptTemplateConfig; + this._parameters = new(() => this.InitParameters()); + this._blocks = new(() => this.ExtractBlocks(this._templateString)); + this._tokenizer = new TemplateTokenizer(this._loggerFactory); + } + + public IReadOnlyList Parameters => this._parameters.Value; + + public async Task RenderAsync(SKContext executionContext, CancellationToken cancellationToken = default) + { + return await this.RenderAsync(this._blocks.Value, executionContext, cancellationToken).ConfigureAwait(false); + } + + // Not showing the implementation details +} +``` + +**Note:** + +* The call to `ExtractBlocks` is called lazily once for each prompt template +* The `RenderAsync` doesn't need to extract the blocks every time + +## Decision Outcome + +Chosen option: "Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory`", because +addresses the requirements and provides good flexibility for the future. diff --git a/docs/decisions/0017-semantic-function-multiple-model-support.md b/docs/decisions/0017-semantic-function-multiple-model-support.md new file mode 100644 index 0000000000..318285639f --- /dev/null +++ b/docs/decisions/0017-semantic-function-multiple-model-support.md @@ -0,0 +1,172 @@ +--- +# These are optional elements. Feel free to remove any of them. +status: approved +contact: markwallace-microsoft +date: 2023-10-26 +deciders: markwallace-microsoft, semenshi, rogerbarreto +consulted: mabolan, dmytrostruk +informed: +--- +# Multiple Model Support for Semantic Functions + +## Context and Problem Statement + +Developers need to be able to use multiple models e.g., using chat completion together with embeddings. + +## Use Cases + +In scope for Semantic Kernel V1.0 + +* Select Model Request Settings by Service Id. + * A Service Id uniquely identifies a registered AI Service and is typically defined in the scope of an application. +* Select AI Service and Model Request Settings By Developer Defined Strategy. + * A Developer Defined Strategy is a code first approach where a developer provides the logic. + +Out of scope for V1.0 + +* Select Model Request Settings by Model Id. + * A Model Id uniquely identifies a Large Language Model. Multiple AI service providers can support the same LLM. +* Select Model Request Settings by Provider Id and Model Id + * A Provider Id uniquely identifies an AI provider e.g. "Azure OpenAI", "OpenAI", "Hugging Face" + +## Decision Outcome + +Support just use cases listed in this ADR. + +## Descriptions of the Use Cases + +**Note: All code is pseudo code and does not accurately reflect what the final implementations will look like.** + +### Select Model Request Settings by Service Id + +_As a developer using the Semantic Kernel I can configure multiple request settings for a semantic function and associate each one with a service id so that the correct request settings are used when different services are used to execute my semantic function._ + +The semantic function template configuration allows multiple model request settings to be configured. In this case the developer configures different settings based on the service id that is used to execute the semantic function. +In the example below the semantic function is executed with "AzureText" using `max_tokens=60` because "AzureText" is the first service id in the list of models configured for the prompt. + +```csharp +// Configure a Kernel with multiple LLM's +IKernel kernel = Kernel.Builder + .WithLoggerFactory(ConsoleLogger.LoggerFactory) + .WithAzureTextCompletionService(deploymentName: aoai.DeploymentName, + endpoint: aoai.Endpoint, serviceId: "AzureText", apiKey: aoai.ApiKey) + .WithAzureChatCompletionService(deploymentName: aoai.ChatDeploymentName, + endpoint: aoai.Endpoint, serviceId: "AzureChat", apiKey: aoai.ApiKey) + .WithOpenAITextCompletionService(modelId: oai.ModelId, + serviceId: "OpenAIText", apiKey: oai.ApiKey) + .WithOpenAIChatCompletionService(modelId: oai.ChatModelId, + serviceId: "OpenAIChat", apiKey: oai.ApiKey, setAsDefault: true) + .Build(); + +// Configure semantic function with multiple LLM request settings +string configPayload = @"{ + ""schema"": 1, + ""description"": ""Hello AI, what can you do for me?"", + ""models"": [ + { ""service_id"": ""AzureText"", ""max_tokens"": 60 }, + { ""service_id"": ""AzureChat"", ""max_tokens"": 120 }, + { ""service_id"": ""OpenAIText"", ""max_tokens"": 180 }, + { ""service_id"": ""OpenAIChat"", ""max_tokens"": 240 } + ] +}"; +var templateConfig = JsonSerializer.Deserialize(configPayload); +var func = kernel.CreateSemanticFunction(prompt, config: templateConfig!, "HelloAI"); + +// Semantic function is executed with OpenAIChat using max_tokens=240 +result = await kernel.RunAsync(func); +``` + +This works by using the `IAIServiceSelector` interface as the strategy for selecting the AI service and request settings to user when invoking a semantic function. +The interface is defined as follows: + +```csharp +public interface IAIServiceSelector +{ + (T?, AIRequestSettings?) SelectAIService(IAIServiceProvider serviceProvider, IReadOnlyList? modelSettings) where T : IAIService; +} +``` + +A default `OrderedIAIServiceSelector` implementation is used which selects the AI service based on the order of the model request settings defined for the semantic function. +The implementation checks if a service exists which the corresponding service id and if it does it and the associated model request settings will be used. +In no model request settings are defined then the default text completion service is used. +A default set of request settings can be specified by leaving the service id undefined or empty, the first such default will be used. +If no default if specified and none of the specified services are available the operation will fail. + +### Select AI Service and Model Request Settings By Developer Defined Strategy + +_As a developer using the Semantic Kernel I can provide factories which select the AI service and request settings used to execute my function so that I can dynamically control which AI service is used to execute my semantic function._ + +In this case the developer configures different settings based on the model id and provides an AI Service factory which determines which AI Service will be used when the semantic function is executed. +In the example below the semantic function is executed with whatever AI Service `myServiceFactory` returns. + +```csharp +// Configure a Kernel with multiple LLM's +IKernel kernel = Kernel.Builder + .WithLoggerFactory(ConsoleLogger.LoggerFactory) + .WithAzureTextCompletionService(deploymentName: aoai.DeploymentName, // text-davinci-003 + endpoint: aoai.Endpoint, serviceId: "AzureText", apiKey: aoai.ApiKey) + .WithAzureChatCompletionService(deploymentName: aoai.ChatDeploymentName, // gpt-35-turbo + endpoint: aoai.Endpoint, serviceId: "AzureChat", apiKey: aoai.ApiKey) + .WithOpenAITextCompletionService(modelId: oai.ModelId, // text-davinci-003 + serviceId: "OpenAIText", apiKey: oai.ApiKey, setAsDefault: true) + .WithOpenAIChatCompletionService(modelId: oai.ChatModelId, // gpt-3.5-turbo + serviceId: "OpenAIChat", apiKey: oai.ApiKey) + .Build(); + +// Configure semantic function with multiple LLM request settings +string configPayload = @"{ + ""schema"": 1, + ""description"": ""Hello AI, what can you do for me?"", + ""models"": [ + { ""max_tokens"": 60 }, + { ""max_tokens"": 120 }, + { ""max_tokens"": 180 } + ] +}"; +var templateConfig = JsonSerializer.Deserialize(configPayload); +var func = kernel.CreateSemanticFunction(prompt, config: templateConfig!, "HelloAI"); + +// Semantic function is executed with AI Service and AI request Settings dynamically determined +result = await kernel.RunAsync(func, funcVariables); +``` + +## More Information + +### Select AI Service by Service Id + +The following use case is supported. Developers can create a `Kernel`` instance with multiple named AI services. When invoking a semantic function the service id (and optionally request settings to be used) can be specified. The named AI service will be used to execute the prompt. + +```csharp +var aoai = TestConfiguration.AzureOpenAI; +var oai = TestConfiguration.OpenAI; + +// Configure a Kernel with multiple LLM's +IKernel kernel = Kernel.Builder + .WithLoggerFactory(ConsoleLogger.LoggerFactory) + .WithAzureTextCompletionService(deploymentName: aoai.DeploymentName, + endpoint: aoai.Endpoint, serviceId: "AzureText", apiKey: aoai.ApiKey) + .WithAzureChatCompletionService(deploymentName: aoai.ChatDeploymentName, + endpoint: aoai.Endpoint, serviceId: "AzureChat", apiKey: aoai.ApiKey) + .WithOpenAITextCompletionService(modelId: oai.ModelId, + serviceId: "OpenAIText", apiKey: oai.ApiKey) + .WithOpenAIChatCompletionService(modelId: oai.ChatModelId, + serviceId: "OpenAIChat", apiKey: oai.ApiKey) + .Build(); + +// Invoke the semantic function and service and request settings to use +result = await kernel.InvokeSemanticFunctionAsync(prompt, + requestSettings: new OpenAIRequestSettings() + { ServiceId = "AzureText", MaxTokens = 60 }); + +result = await kernel.InvokeSemanticFunctionAsync(prompt, + requestSettings: new OpenAIRequestSettings() + { ServiceId = "AzureChat", MaxTokens = 120 }); + +result = await kernel.InvokeSemanticFunctionAsync(prompt, + requestSettings: new OpenAIRequestSettings() + { ServiceId = "OpenAIText", MaxTokens = 180 }); + +result = await kernel.InvokeSemanticFunctionAsync(prompt, + requestSettings: new OpenAIRequestSettings() + { ServiceId = "OpenAIChat", MaxTokens = 240 }); +``` diff --git a/dotnet/samples/KernelSyntaxExamples/Example06_TemplateLanguage.cs b/dotnet/samples/KernelSyntaxExamples/Example06_TemplateLanguage.cs index 9181215243..bd594d596d 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example06_TemplateLanguage.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example06_TemplateLanguage.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Connectors.AI.OpenAI; using Microsoft.SemanticKernel.Plugins.Core; +using Microsoft.SemanticKernel.TemplateEngine; using Microsoft.SemanticKernel.TemplateEngine.Basic; using RepoUtils; @@ -51,8 +52,9 @@ Is it weekend time (weekend/not weekend)? // This allows to see the prompt before it's sent to OpenAI Console.WriteLine("--- Rendered Prompt"); - var promptRenderer = new BasicPromptTemplateEngine(); - var renderedPrompt = await promptRenderer.RenderAsync(FunctionDefinition, kernel.CreateNewContext()); + var promptTemplateFactory = new BasicPromptTemplateFactory(); + var promptTemplate = promptTemplateFactory.Create(FunctionDefinition, new PromptTemplateConfig()); + var renderedPrompt = await promptTemplate.RenderAsync(kernel.CreateNewContext()); Console.WriteLine(renderedPrompt); // Run the prompt / semantic function diff --git a/dotnet/samples/KernelSyntaxExamples/Example07_BingAndGooglePlugins.cs b/dotnet/samples/KernelSyntaxExamples/Example07_BingAndGooglePlugins.cs index 84c180a204..9a7a3290b4 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example07_BingAndGooglePlugins.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example07_BingAndGooglePlugins.cs @@ -7,6 +7,7 @@ using Microsoft.SemanticKernel.Connectors.AI.OpenAI; using Microsoft.SemanticKernel.Plugins.Web; using Microsoft.SemanticKernel.Plugins.Web.Bing; using Microsoft.SemanticKernel.Plugins.Web.Google; +using Microsoft.SemanticKernel.TemplateEngine; using Microsoft.SemanticKernel.TemplateEngine.Basic; using RepoUtils; @@ -149,10 +150,11 @@ Answer: "; // If the answer contains commands, execute them using the prompt renderer. if (result.Contains("bing.search", StringComparison.OrdinalIgnoreCase)) { - var promptRenderer = new BasicPromptTemplateEngine(); + var promptTemplateFactory = new BasicPromptTemplateFactory(); + var promptTemplate = promptTemplateFactory.Create(result, new PromptTemplateConfig()); Console.WriteLine("---- Fetching information from Bing..."); - var information = await promptRenderer.RenderAsync(result, kernel.CreateNewContext()); + var information = await promptTemplate.RenderAsync(kernel.CreateNewContext()); Console.WriteLine("Information found:"); Console.WriteLine(information); diff --git a/dotnet/samples/KernelSyntaxExamples/Example30_ChatWithPrompts.cs b/dotnet/samples/KernelSyntaxExamples/Example30_ChatWithPrompts.cs index 567eef956c..fd2cad3859 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example30_ChatWithPrompts.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example30_ChatWithPrompts.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.AI.ChatCompletion; using Microsoft.SemanticKernel.Plugins.Core; +using Microsoft.SemanticKernel.TemplateEngine; using Microsoft.SemanticKernel.TemplateEngine.Basic; using RepoUtils; using Resources; @@ -83,19 +84,19 @@ public static class Example30_ChatWithPrompts // This is the user message, store it in the variable used by 28-user-prompt.txt context.Variables["userMessage"] = "extract locations as a bullet point list"; - // Instantiate the prompt renderer, which we will use to turn prompt templates + // Instantiate the prompt template factory, which we will use to turn prompt templates // into strings, that we will store into a Chat history object, which is then sent // to the Chat Model. - var promptRenderer = new BasicPromptTemplateEngine(); + var promptTemplateFactory = new BasicPromptTemplateFactory(); // Render the system prompt. This string is used to configure the chat. // This contains the context, ie a piece of a wikipedia page selected by the user. - string systemMessage = await promptRenderer.RenderAsync(systemPromptTemplate, context); + string systemMessage = await promptTemplateFactory.Create(systemPromptTemplate, new PromptTemplateConfig()).RenderAsync(context); Console.WriteLine($"------------------------------------\n{systemMessage}"); // Render the user prompt. This string is the query sent by the user // This contains the user request, ie "extract locations as a bullet point list" - string userMessage = await promptRenderer.RenderAsync(userPromptTemplate, context); + string userMessage = await promptTemplateFactory.Create(userPromptTemplate, new PromptTemplateConfig()).RenderAsync(context); Console.WriteLine($"------------------------------------\n{userMessage}"); // Client used to request answers diff --git a/dotnet/samples/KernelSyntaxExamples/Example40_DIContainer.cs b/dotnet/samples/KernelSyntaxExamples/Example40_DIContainer.cs index 88e8b20b27..65bfd35da9 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example40_DIContainer.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example40_DIContainer.cs @@ -10,9 +10,6 @@ using Microsoft.SemanticKernel.Http; using Microsoft.SemanticKernel.Memory; using Microsoft.SemanticKernel.Reliability.Basic; using Microsoft.SemanticKernel.Services; - -using Microsoft.SemanticKernel.TemplateEngine; -using Microsoft.SemanticKernel.TemplateEngine.Basic; using RepoUtils; /** @@ -82,7 +79,6 @@ public static class Example40_DIContainer collection.AddTransient((_) => ConsoleLogger.LoggerFactory); collection.AddTransient((_) => BasicHttpRetryHandlerFactory.Instance); collection.AddTransient(); - collection.AddTransient(); collection.AddTransient((_) => NullMemory.Instance); collection.AddTransient((_) => aiServicesCollection.Build()); //Registering AI service provider that is used by Kernel to resolve AI services runtime diff --git a/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs b/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs index 6638b78f70..868de3b2a6 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs @@ -24,7 +24,6 @@ using Microsoft.SemanticKernel.Reliability.Basic; using Microsoft.SemanticKernel.Reliability.Polly; using Microsoft.SemanticKernel.Services; -using Microsoft.SemanticKernel.TemplateEngine.Basic; using Polly; using Polly.Retry; @@ -81,7 +80,6 @@ public static class Example42_KernelBuilder var memory = new SemanticTextMemory(memoryStorage, textEmbeddingGenerator); var plugins = new FunctionCollection(); - var templateEngine = new BasicPromptTemplateEngine(loggerFactory); var httpHandlerFactory = BasicHttpRetryHandlerFactory.Instance; //var httpHandlerFactory = new PollyHttpRetryHandlerFactory( your policy ); @@ -99,7 +97,7 @@ public static class Example42_KernelBuilder IAIServiceProvider aiServiceProvider = aiServices.Build(); // Create kernel manually injecting all the dependencies - using var kernel3 = new Kernel(plugins, aiServiceProvider, templateEngine, memory, httpHandlerFactory, loggerFactory); + using var kernel3 = new Kernel(plugins, aiServiceProvider, memory, httpHandlerFactory, loggerFactory); // ========================================================================================================== // The kernel builder purpose is to simplify this process, automating how dependencies diff --git a/dotnet/samples/KernelSyntaxExamples/Example56_TemplateNativeFunctionsWithMultipleArguments.cs b/dotnet/samples/KernelSyntaxExamples/Example56_TemplateNativeFunctionsWithMultipleArguments.cs index 2b3810405f..de40d06b3b 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example56_TemplateNativeFunctionsWithMultipleArguments.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example56_TemplateNativeFunctionsWithMultipleArguments.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Connectors.AI.OpenAI; using Microsoft.SemanticKernel.Plugins.Core; +using Microsoft.SemanticKernel.TemplateEngine; using Microsoft.SemanticKernel.TemplateEngine.Basic; using RepoUtils; @@ -55,8 +56,9 @@ public static class Example56_TemplateNativeFunctionsWithMultipleArguments // This allows to see the prompt before it's sent to OpenAI Console.WriteLine("--- Rendered Prompt"); - var promptRenderer = new BasicPromptTemplateEngine(); - var renderedPrompt = await promptRenderer.RenderAsync(FunctionDefinition, context); + var promptTemplateFactory = new BasicPromptTemplateFactory(); + var promptTemplate = promptTemplateFactory.Create(FunctionDefinition, new PromptTemplateConfig()); + var renderedPrompt = await promptTemplate.RenderAsync(context); Console.WriteLine(renderedPrompt); // Run the prompt / semantic function diff --git a/dotnet/samples/KernelSyntaxExamples/Example62_CustomAIServiceSelector.cs b/dotnet/samples/KernelSyntaxExamples/Example62_CustomAIServiceSelector.cs index bd33907885..74096cd6fd 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example62_CustomAIServiceSelector.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example62_CustomAIServiceSelector.cs @@ -70,12 +70,11 @@ public static class Example62_CustomAIServiceSelector Console.WriteLine($"======== {prompt} ========"); var promptTemplateConfig = new PromptTemplateConfig() { ModelSettings = modelSettings }; - var promptTemplate = new PromptTemplate(prompt, promptTemplateConfig, kernel); var skfunction = kernel.RegisterSemanticFunction( "MyFunction", - promptTemplateConfig, - promptTemplate); + prompt, + promptTemplateConfig); var result = await kernel.RunAsync(skfunction); Console.WriteLine(result.GetValue()); diff --git a/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/BasicPromptTemplateFactoryTests.cs b/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/BasicPromptTemplateFactoryTests.cs new file mode 100644 index 0000000000..318ab73605 --- /dev/null +++ b/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/BasicPromptTemplateFactoryTests.cs @@ -0,0 +1,53 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.TemplateEngine; +using Microsoft.SemanticKernel.TemplateEngine.Basic; +using Xunit; + +namespace SemanticKernel.Extensions.UnitTests.TemplateEngine.Prompt; + +public sealed class BasicPromptTemplateFactoryTests +{ + [Fact] + public void ItCreatesBasicPromptTemplateByDefault() + { + // Arrange + var templateString = "{{$input}}"; + var target = new BasicPromptTemplateFactory(); + + // Act + var result = target.Create(templateString, new PromptTemplateConfig()); + + // Assert + Assert.NotNull(result); + Assert.True(result is BasicPromptTemplate); + } + + [Fact] + public void ItCreatesBasicPromptTemplate() + { + // Arrange + var templateString = "{{$input}}"; + var target = new BasicPromptTemplateFactory(); + + // Act + var result = target.Create(templateString, new PromptTemplateConfig() { TemplateFormat = "semantic-kernel" }); + + // Assert + Assert.NotNull(result); + Assert.True(result is BasicPromptTemplate); + } + + [Fact] + public void ItThrowsExceptionForUnknowPromptTemplateFormat() + { + // Arrange + var templateString = "{{$input}}"; + var target = new BasicPromptTemplateFactory(); + + // Act + // Assert + Assert.Throws(() => target.Create(templateString, new PromptTemplateConfig() { TemplateFormat = "unknown-format" })); + } +} diff --git a/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/BasicPromptTemplateTests.cs b/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/BasicPromptTemplateTests.cs new file mode 100644 index 0000000000..2a592f5027 --- /dev/null +++ b/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/BasicPromptTemplateTests.cs @@ -0,0 +1,418 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Orchestration; +using Microsoft.SemanticKernel.Services; +using Microsoft.SemanticKernel.TemplateEngine; +using Microsoft.SemanticKernel.TemplateEngine.Basic; +using Microsoft.SemanticKernel.TemplateEngine.Basic.Blocks; +using Moq; +using SemanticKernel.Extensions.UnitTests.XunitHelpers; +using Xunit; +using Xunit.Abstractions; + +namespace SemanticKernel.Extensions.UnitTests.TemplateEngine.Prompt; + +public sealed class BasicPromptTemplateTests +{ + private const string DateFormat = "M/d/yyyy"; + private readonly BasicPromptTemplateFactory _factory; + private readonly ContextVariables _variables; + private readonly Mock _functions; + private readonly ITestOutputHelper _logger; + private readonly Mock _kernel; + private readonly Mock _functionRunner; + private readonly Mock _serviceProvider; + private readonly Mock _serviceSelector; + + public BasicPromptTemplateTests(ITestOutputHelper testOutputHelper) + { + this._logger = testOutputHelper; + this._factory = new BasicPromptTemplateFactory(TestConsoleLogger.LoggerFactory); + this._variables = new ContextVariables(Guid.NewGuid().ToString("X")); + this._functions = new Mock(); + this._kernel = new Mock(); + this._functionRunner = new Mock(); + this._serviceProvider = new Mock(); + this._serviceSelector = new Mock(); + } + + [Fact] + public void ItRendersVariables() + { + // Arrange + var template = "{$x11} This {$a} is {$_a} a {{$x11}} test {{$x11}} " + + "template {{foo}}{{bar $a}}{{baz $_a}}{{yay $x11}}{{food a='b' c = $d}}"; + var target = (BasicPromptTemplate)this._factory.Create(template, new PromptTemplateConfig()); + + // Act + var blocks = target.ExtractBlocks(template); + var updatedBlocks = target.RenderVariables(blocks, this._variables); + + // Assert + Assert.Equal(10, blocks.Count); + Assert.Equal(10, updatedBlocks.Count); + + Assert.Equal("$x11", blocks[1].Content); + Assert.Equal("", updatedBlocks[1].Content); + Assert.Equal(BlockTypes.Variable, blocks[1].Type); + Assert.Equal(BlockTypes.Text, updatedBlocks[1].Type); + + Assert.Equal("$x11", blocks[3].Content); + Assert.Equal("", updatedBlocks[3].Content); + Assert.Equal(BlockTypes.Variable, blocks[3].Type); + Assert.Equal(BlockTypes.Text, updatedBlocks[3].Type); + + Assert.Equal("foo", blocks[5].Content); + Assert.Equal("foo", updatedBlocks[5].Content); + Assert.Equal(BlockTypes.Code, blocks[5].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[5].Type); + + Assert.Equal("bar $a", blocks[6].Content); + Assert.Equal("bar $a", updatedBlocks[6].Content); + Assert.Equal(BlockTypes.Code, blocks[6].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[6].Type); + + Assert.Equal("baz $_a", blocks[7].Content); + Assert.Equal("baz $_a", updatedBlocks[7].Content); + Assert.Equal(BlockTypes.Code, blocks[7].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[7].Type); + + Assert.Equal("yay $x11", blocks[8].Content); + Assert.Equal("yay $x11", updatedBlocks[8].Content); + Assert.Equal(BlockTypes.Code, blocks[8].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[8].Type); + + Assert.Equal("food a='b' c = $d", blocks[9].Content); + Assert.Equal("food a='b' c = $d", updatedBlocks[9].Content); + Assert.Equal(BlockTypes.Code, blocks[9].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[9].Type); + + // Arrange + this._variables.Set("x11", "x11 value"); + this._variables.Set("a", "a value"); + this._variables.Set("_a", "_a value"); + this._variables.Set("c", "c value"); + this._variables.Set("d", "d value"); + + // Act + blocks = target.ExtractBlocks(template); + updatedBlocks = target.RenderVariables(blocks, this._variables); + + // Assert + Assert.Equal(10, blocks.Count); + Assert.Equal(10, updatedBlocks.Count); + + Assert.Equal("$x11", blocks[1].Content); + Assert.Equal("x11 value", updatedBlocks[1].Content); + Assert.Equal(BlockTypes.Variable, blocks[1].Type); + Assert.Equal(BlockTypes.Text, updatedBlocks[1].Type); + + Assert.Equal("$x11", blocks[3].Content); + Assert.Equal("x11 value", updatedBlocks[3].Content); + Assert.Equal(BlockTypes.Variable, blocks[3].Type); + Assert.Equal(BlockTypes.Text, updatedBlocks[3].Type); + + Assert.Equal("foo", blocks[5].Content); + Assert.Equal("foo", updatedBlocks[5].Content); + Assert.Equal(BlockTypes.Code, blocks[5].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[5].Type); + + Assert.Equal("bar $a", blocks[6].Content); + Assert.Equal("bar $a", updatedBlocks[6].Content); + Assert.Equal(BlockTypes.Code, blocks[6].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[6].Type); + + Assert.Equal("baz $_a", blocks[7].Content); + Assert.Equal("baz $_a", updatedBlocks[7].Content); + Assert.Equal(BlockTypes.Code, blocks[7].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[7].Type); + + Assert.Equal("yay $x11", blocks[8].Content); + Assert.Equal("yay $x11", updatedBlocks[8].Content); + Assert.Equal(BlockTypes.Code, blocks[8].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[8].Type); + + Assert.Equal("food a='b' c = $d", blocks[9].Content); + Assert.Equal("food a='b' c = $d", updatedBlocks[9].Content); + Assert.Equal(BlockTypes.Code, blocks[9].Type); + Assert.Equal(BlockTypes.Code, updatedBlocks[9].Type); + } + + [Fact] + public async Task ItRendersCodeUsingInputAsync() + { + // Arrange + string MyFunctionAsync(SKContext context) + { + this._logger.WriteLine("MyFunction call received, input: {0}", context.Variables.Input); + return $"F({context.Variables.Input})"; + } + + List functions = new() + { + SKFunction.FromNativeMethod(Method(MyFunctionAsync), this), + }; + + Assert.NotNull(functions[0]); + + this._variables.Update("INPUT-BAR"); + var template = "foo-{{function}}-baz"; + var target = (BasicPromptTemplate)this._factory.Create(template, new PromptTemplateConfig()); + + this.MockFunctionRunner(functions[0]); + + var context = this.MockContext(); + + // Act + var result = await target.RenderAsync(context); + + // Assert + Assert.Equal("foo-F(INPUT-BAR)-baz", result); + } + + [Fact] + public async Task ItRendersCodeUsingVariablesAsync() + { + // Arrange + string MyFunctionAsync(SKContext context) + { + this._logger.WriteLine("MyFunction call received, input: {0}", context.Variables.Input); + return $"F({context.Variables.Input})"; + } + + var func = SKFunction.FromNativeMethod(Method(MyFunctionAsync), this); + + Assert.NotNull(func); + + this._variables.Set("myVar", "BAR"); + var template = "foo-{{function $myVar}}-baz"; + var target = (BasicPromptTemplate)this._factory.Create(template, new PromptTemplateConfig()); + + this.MockFunctionRunner(func); + var context = this.MockContext(); + + // Act + var result = await target.RenderAsync(context); + + // Assert + Assert.Equal("foo-F(BAR)-baz", result); + } + + [Fact] + public async Task ItRendersCodeUsingNamedVariablesAsync() + { + // Arrange + string MyFunctionAsync( + [Description("Name"), SKName("input")] string name, + [Description("Age"), SKName("age")] int age, + [Description("Slogan"), SKName("slogan")] string slogan, + [Description("Date"), SKName("date")] DateTime date) + { + var dateStr = date.ToString(BasicPromptTemplateTests.DateFormat, CultureInfo.InvariantCulture); + this._logger.WriteLine("MyFunction call received, name: {0}, age: {1}, slogan: {2}, date: {3}", name, age, slogan, date); + return $"[{dateStr}] {name} ({age}): \"{slogan}\""; + } + + var func = SKFunction.FromNativeMethod(Method(MyFunctionAsync), this); + + Assert.NotNull(func); + + this._variables.Set("input", "Mario"); + this._variables.Set("someDate", "2023-08-25T00:00:00"); + var template = "foo-{{function input=$input age='42' slogan='Let\\'s-a go!' date=$someDate}}-baz"; + var target = (BasicPromptTemplate)this._factory.Create(template, new PromptTemplateConfig()); + + this.MockFunctionRunner(func); + var context = this.MockContext(); + + // Act + var result = await target.RenderAsync(context); + + // Assert + Assert.Equal("foo-[8/25/2023] Mario (42): \"Let's-a go!\"-baz", result); + } + + [Fact] + public async Task ItHandlesSyntaxErrorsAsync() + { + // Arrange + string MyFunctionAsync( + [Description("Name"), SKName("input")] string name, + [Description("Age"), SKName("age")] int age, + [Description("Slogan"), SKName("slogan")] string slogan, + [Description("Date"), SKName("date")] DateTime date) + { + var dateStr = date.ToString(BasicPromptTemplateTests.DateFormat, CultureInfo.InvariantCulture); + this._logger.WriteLine("MyFunction call received, name: {0}, age: {1}, slogan: {2}, date: {3}", name, age, slogan, date); + return $"[{dateStr}] {name} ({age}): \"{slogan}\""; + } + + ISKFunction func = SKFunction.FromNativeMethod(Method(MyFunctionAsync), this); + Assert.NotNull(func); + + this._variables.Set("input", "Mario"); + this._variables.Set("someDate", "2023-08-25T00:00:00"); + var template = "foo-{{function input=$input age=42 slogan='Let\\'s-a go!' date=$someDate}}-baz"; + var target = (BasicPromptTemplate)this._factory.Create(template, new PromptTemplateConfig()); + var context = this.MockContext(); + + // Act + var result = await Assert.ThrowsAsync(() => target.RenderAsync(context)); + Assert.Equal($"Named argument values need to be prefixed with a quote or {Symbols.VarPrefix}.", result.Message); + } + + [Fact] + public async Task ItRendersCodeUsingImplicitInputAndNamedVariablesAsync() + { + // Arrange + string MyFunctionAsync( + [Description("Input"), SKName("input")] string name, + [Description("Age"), SKName("age")] int age, + [Description("Slogan"), SKName("slogan")] string slogan, + [Description("Date"), SKName("date")] DateTime date) + { + this._logger.WriteLine("MyFunction call received, name: {0}, age: {1}, slogan: {2}, date: {3}", name, age, slogan, date); + var dateStr = date.ToString(BasicPromptTemplateTests.DateFormat, CultureInfo.InvariantCulture); + return $"[{dateStr}] {name} ({age}): \"{slogan}\""; + } + + ISKFunction func = SKFunction.FromNativeMethod(Method(MyFunctionAsync), this); + + Assert.NotNull(func); + + this._variables.Set("input", "Mario"); + this._variables.Set("someDate", "2023-08-25T00:00:00"); + + var template = "foo-{{function $input age='42' slogan='Let\\'s-a go!' date=$someDate}}-baz"; + var target = (BasicPromptTemplate)this._factory.Create(template, new PromptTemplateConfig()); + + this.MockFunctionRunner(func); + + var context = this.MockContext(); + + // Act + var result = await target.RenderAsync(context); + + // Assert + Assert.Equal("foo-[8/25/2023] Mario (42): \"Let's-a go!\"-baz", result); + } + + [Fact] + public async Task ItRendersAsyncCodeUsingImmutableVariablesAsync() + { + // Arrange + var template = "{{func1}} {{func2}} {{func3 $myVar}}"; + var target = (BasicPromptTemplate)this._factory.Create(template, new PromptTemplateConfig()); + this._variables.Update("BAR"); + this._variables.Set("myVar", "BAZ"); + + string MyFunction1Async(SKContext context) + { + this._logger.WriteLine("MyFunction1 call received, input: {0}", context.Variables.Input); + context.Variables.Update("foo"); + return "F(OUTPUT-FOO)"; + } + string MyFunction2Async(SKContext context) + { + // Input value should be "BAR" because the variable $input is immutable in MyFunction1 + this._logger.WriteLine("MyFunction2 call received, input: {0}", context.Variables.Input); + context.Variables.Set("myVar", "bar"); + return context.Variables.Input; + } + string MyFunction3Async(SKContext context) + { + // Input value should be "BAZ" because the variable $myVar is immutable in MyFunction2 + this._logger.WriteLine("MyFunction3 call received, input: {0}", context.Variables.Input); + return context.Variables.TryGetValue("myVar", out string? value) ? value : ""; + } + + var functions = new List() + { + SKFunction.FromNativeMethod(Method(MyFunction1Async), this, "func1"), + SKFunction.FromNativeMethod(Method(MyFunction2Async), this, "func2"), + SKFunction.FromNativeMethod(Method(MyFunction3Async), this, "func3") + }; + + this.MockFunctionRunner(functions); + + // Act + var result = await target.RenderAsync(this.MockContext()); + + // Assert + Assert.Equal("F(OUTPUT-FOO) BAR BAZ", result); + } + + [Fact] + public async Task ItRendersAsyncCodeUsingVariablesAsync() + { + // Arrange + Task MyFunctionAsync(SKContext context) + { + // Input value should be "BAR" because the variable $myVar is passed in + this._logger.WriteLine("MyFunction call received, input: {0}", context.Variables.Input); + return Task.FromResult(context.Variables.Input); + } + + ISKFunction func = SKFunction.FromNativeMethod(Method(MyFunctionAsync), this); + Assert.NotNull(func); + + this._variables.Set("myVar", "BAR"); + + var template = "foo-{{function $myVar}}-baz"; + var target = (BasicPromptTemplate)this._factory.Create(template, new PromptTemplateConfig()); + var context = this.MockContext(); + + // Act + var result = await target.RenderAsync(context); + + // Assert + Assert.Equal("foo-BAR-baz", result); + } + + private static MethodInfo Method(Delegate method) + { + return method.Method; + } + + private void MockFunctionRunner(ISKFunction function) + { + this._functionRunner.Setup(r => r.RunAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((pluginName, functionName, variables, cancellationToken) => + { + var context = new SKContext(this._functionRunner.Object, this._serviceProvider.Object, this._serviceSelector.Object, variables); + return function.InvokeAsync(context, null, cancellationToken); + }); + } + + private void MockFunctionRunner(List functions) + { + this._functionRunner.Setup(r => r.RunAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((pluginName, functionName, variables, cancellationToken) => + { + var context = new SKContext(this._functionRunner.Object, this._serviceProvider.Object, this._serviceSelector.Object, variables); + var function = functions.First(f => f.PluginName == functionName); + + return function.InvokeAsync(context, null, cancellationToken); + }); + } + + private SKContext MockContext() + { + return new SKContext( + this._functionRunner.Object, + this._serviceProvider.Object, + this._serviceSelector.Object, + this._variables, + this._functions.Object); + } +} diff --git a/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/PromptTemplateEngineTests.cs b/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/PromptTemplateEngineTests.cs index c394a54d0d..c8d98220dd 100644 --- a/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/PromptTemplateEngineTests.cs +++ b/dotnet/src/Extensions/Extensions.UnitTests/TemplateEngine/Prompt/PromptTemplateEngineTests.cs @@ -21,6 +21,8 @@ using Xunit.Abstractions; namespace SemanticKernel.Extensions.UnitTests.TemplateEngine.Prompt; +[Obsolete("Use BasicPromptTemplateFactory instead. This will be removed in a future release.")] +[EditorBrowsable(EditorBrowsableState.Never)] public sealed class PromptTemplateEngineTests { private const string DateFormat = "M/d/yyyy"; diff --git a/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplate.cs b/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplate.cs new file mode 100644 index 0000000000..be24ecdc05 --- /dev/null +++ b/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplate.cs @@ -0,0 +1,167 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Orchestration; +using Microsoft.SemanticKernel.TemplateEngine.Basic.Blocks; + +namespace Microsoft.SemanticKernel.TemplateEngine.Basic; + +/// +/// Given a prompt, that might contain references to variables and functions: +/// - Get the list of references +/// - Resolve each reference +/// - Variable references are resolved using the context variables +/// - Function references are resolved invoking those functions +/// - Functions can be invoked passing in variables +/// - Functions do not receive the context variables, unless specified using a special variable +/// - Functions can be invoked in order and in parallel so the context variables must be immutable when invoked within the template +/// +public sealed class BasicPromptTemplate : IPromptTemplate +{ + /// + /// Constructor for PromptTemplate. + /// + /// Prompt template string. + /// Prompt template configuration + /// Logger factory + public BasicPromptTemplate(string templateString, PromptTemplateConfig promptTemplateConfig, ILoggerFactory? loggerFactory = null) + { + this._loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; + this._logger = this._loggerFactory.CreateLogger(typeof(BasicPromptTemplate)); + this._templateString = templateString; + this._promptTemplateConfig = promptTemplateConfig; + this._parameters = new(() => this.InitParameters()); + this._blocks = new(() => this.ExtractBlocks(this._templateString)); + this._tokenizer = new TemplateTokenizer(this._loggerFactory); + } + + /// + public IReadOnlyList Parameters => this._parameters.Value; + + /// + public async Task RenderAsync(SKContext executionContext, CancellationToken cancellationToken = default) + { + return await this.RenderAsync(this._blocks.Value, executionContext, cancellationToken).ConfigureAwait(false); + } + + #region private + private readonly ILoggerFactory _loggerFactory; + private readonly ILogger _logger; + private readonly string _templateString; + private readonly PromptTemplateConfig _promptTemplateConfig; + private readonly TemplateTokenizer _tokenizer; + private readonly Lazy> _parameters; + private readonly Lazy> _blocks; + + private List InitParameters() + { + // Parameters from prompt template configuration + Dictionary result = new(this._promptTemplateConfig.Input.Parameters.Count, StringComparer.OrdinalIgnoreCase); + foreach (var p in this._promptTemplateConfig.Input.Parameters) + { + result[p.Name] = new ParameterView(p.Name, p.Description, p.DefaultValue); + } + + // Parameters from the template + var variableNames = this._blocks.Value.Where(block => block.Type == BlockTypes.Variable).Select(block => ((VarBlock)block).Name).ToList(); + foreach (var variableName in variableNames) + { + if (!string.IsNullOrEmpty(variableName) && !result.ContainsKey(variableName!)) + { + result.Add(variableName!, new ParameterView(variableName!)); + } + } + + return result.Values.ToList(); + } + + /// + /// Given a prompt template string, extract all the blocks (text, variables, function calls) + /// + /// Prompt template (see skprompt.txt files) + /// Whether to validate the blocks syntax, or just return the blocks found, which could contain invalid code + /// A list of all the blocks, ie the template tokenized in text, variables and function calls + internal IList ExtractBlocks(string? templateText, bool validate = true) + { + this._logger.LogTrace("Extracting blocks from template: {0}", templateText); + var blocks = this._tokenizer.Tokenize(templateText); + + if (validate) + { + foreach (var block in blocks) + { + if (!block.IsValid(out var error)) + { + throw new SKException(error); + } + } + } + + return blocks; + } + + /// + /// Given a list of blocks render each block and compose the final result. + /// + /// Template blocks generated by ExtractBlocks. + /// Access into the current kernel execution context. + /// The to monitor for cancellation requests. The default is . + /// The prompt template ready to be used for an AI request. + internal async Task RenderAsync(IList blocks, SKContext context, CancellationToken cancellationToken = default) + { + this._logger.LogTrace("Rendering list of {0} blocks", blocks.Count); + var tasks = new List>(blocks.Count); + foreach (var block in blocks) + { + switch (block) + { + case ITextRendering staticBlock: + tasks.Add(Task.FromResult(staticBlock.Render(context.Variables))); + break; + + case ICodeRendering dynamicBlock: + tasks.Add(dynamicBlock.RenderCodeAsync(context, cancellationToken)); + break; + + default: + const string Error = "Unexpected block type, the block doesn't have a rendering method"; + this._logger.LogError(Error); + throw new SKException(Error); + } + } + + var result = new StringBuilder(); + foreach (Task t in tasks) + { + result.Append(await t.ConfigureAwait(false)); + } + + // Sensitive data, logging as trace, disabled by default + this._logger.LogTrace("Rendered prompt: {0}", result); + + return result.ToString(); + } + + /// + /// Given a list of blocks, render the Variable Blocks, replacing placeholders with the actual value in memory. + /// + /// List of blocks, typically all the blocks found in a template. + /// Container of all the temporary variables known to the kernel. + /// An updated list of blocks where Variable Blocks have rendered to Text Blocks. + internal IList RenderVariables(IList blocks, ContextVariables? variables) + { + this._logger.LogTrace("Rendering variables"); + return blocks.Select(block => block.Type != BlockTypes.Variable + ? block + : new TextBlock(((ITextRendering)block).Render(variables), this._loggerFactory)).ToList(); + } + #endregion +} diff --git a/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplateEngine.cs b/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplateEngine.cs index 2b6721f89b..1ef60d17c7 100644 --- a/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplateEngine.cs +++ b/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplateEngine.cs @@ -1,6 +1,8 @@ īģŋ// Copyright (c) Microsoft. All rights reserved. +using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; using System.Threading; @@ -23,6 +25,8 @@ namespace Microsoft.SemanticKernel.TemplateEngine.Basic; /// - Functions do not receive the context variables, unless specified using a special variable /// - Functions can be invoked in order and in parallel so the context variables must be immutable when invoked within the template /// +[Obsolete("Use BasicPromptTemplateFactory instead. This will be removed in a future release.")] +[EditorBrowsable(EditorBrowsableState.Never)] public class BasicPromptTemplateEngine : IPromptTemplateEngine { private readonly ILoggerFactory _loggerFactory; @@ -37,7 +41,7 @@ public class BasicPromptTemplateEngine : IPromptTemplateEngine { this._loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; this._logger = this._loggerFactory.CreateLogger(typeof(BasicPromptTemplateEngine)); - this._tokenizer = new TemplateTokenizer(loggerFactory); + this._tokenizer = new TemplateTokenizer(this._loggerFactory); } /// diff --git a/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplateFactory.cs b/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplateFactory.cs new file mode 100644 index 0000000000..fde8b92b62 --- /dev/null +++ b/dotnet/src/Extensions/TemplateEngine.Basic/BasicPromptTemplateFactory.cs @@ -0,0 +1,35 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.SemanticKernel.Diagnostics; + +namespace Microsoft.SemanticKernel.TemplateEngine.Basic; + +/// +/// Default implementation of for the semantic-kernel prompt template format. +/// +public sealed class BasicPromptTemplateFactory : IPromptTemplateFactory +{ + private readonly ILoggerFactory _loggerFactory; + + /// + /// Initializes a new instance of the class. + /// + /// The to use for logging. If null, no logging will be performed. + public BasicPromptTemplateFactory(ILoggerFactory? loggerFactory = null) + { + this._loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; + } + + /// + public IPromptTemplate Create(string templateString, PromptTemplateConfig promptTemplateConfig) + { + if (promptTemplateConfig.TemplateFormat.Equals(PromptTemplateConfig.SemanticKernelTemplateFormat, System.StringComparison.Ordinal)) + { + return new BasicPromptTemplate(templateString, promptTemplateConfig, this._loggerFactory); + } + + throw new SKException($"Prompt template format {promptTemplateConfig.TemplateFormat} is not supported."); + } +} diff --git a/dotnet/src/Extensions/TemplateEngine.Basic/Extensions/KernelBasicPromptTemplateExtensions.cs b/dotnet/src/Extensions/TemplateEngine.Basic/Extensions/KernelBasicPromptTemplateExtensions.cs new file mode 100644 index 0000000000..57cf40cc5b --- /dev/null +++ b/dotnet/src/Extensions/TemplateEngine.Basic/Extensions/KernelBasicPromptTemplateExtensions.cs @@ -0,0 +1,55 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.TemplateEngine; +using Microsoft.SemanticKernel.TemplateEngine.Basic; + +#pragma warning disable IDE0130 +// ReSharper disable once CheckNamespace - Using the namespace of IKernel +namespace Microsoft.SemanticKernel; +#pragma warning restore IDE0130 + +/// +/// Class for extensions methods to define semantic functions using the basic prompt template factory. +/// +public static class KernelBasicPromptTemplateExtensions +{ + /// + /// Build and register a function in the internal function collection, in a global generic plugin. + /// + /// Semantic Kernel instance + /// Name of the semantic function. The name can contain only alphanumeric chars + underscore. + /// Prompt template string. + /// Prompt template configuration. + /// A C# function wrapping AI logic, usually defined with natural language + public static ISKFunction RegisterSemanticFunction( + this IKernel kernel, + string functionName, + string templateString, + PromptTemplateConfig promptTemplateConfig) + { + var promptTemplateFactory = new BasicPromptTemplateFactory(loggerFactory: kernel.LoggerFactory); + var promptTemplate = promptTemplateFactory.Create(templateString, promptTemplateConfig); + return kernel.RegisterSemanticFunction(functionName, promptTemplateConfig, promptTemplate); + } + + /// + /// Build and register a function in the internal function collection, in a global generic plugin. + /// + /// Semantic Kernel instance + /// + /// Name of the semantic function. The name can contain only alphanumeric chars + underscore. + /// Prompt template string. + /// Prompt template configuration. + /// A C# function wrapping AI logic, usually defined with natural language + public static ISKFunction RegisterSemanticFunction( + this IKernel kernel, + string pluginName, + string functionName, + string templateString, + PromptTemplateConfig promptTemplateConfig) + { + var promptTemplateFactory = new BasicPromptTemplateFactory(loggerFactory: kernel.LoggerFactory); + var promptTemplate = promptTemplateFactory.Create(templateString, promptTemplateConfig); + return kernel.RegisterSemanticFunction(pluginName, functionName, promptTemplateConfig, promptTemplate); + } +} diff --git a/dotnet/src/Extensions/TemplateEngine.Basic/TemplateEngine.Basic.csproj b/dotnet/src/Extensions/TemplateEngine.Basic/TemplateEngine.Basic.csproj index defc4bf9a7..f07f24a23f 100644 --- a/dotnet/src/Extensions/TemplateEngine.Basic/TemplateEngine.Basic.csproj +++ b/dotnet/src/Extensions/TemplateEngine.Basic/TemplateEngine.Basic.csproj @@ -20,6 +20,6 @@ - + \ No newline at end of file diff --git a/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAICompletionTests.cs b/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAICompletionTests.cs index f0a6f607f5..b10406b712 100644 --- a/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAICompletionTests.cs +++ b/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAICompletionTests.cs @@ -12,6 +12,7 @@ using Microsoft.SemanticKernel.Diagnostics; using Microsoft.SemanticKernel.Orchestration; using Microsoft.SemanticKernel.Reliability.Basic; using Microsoft.SemanticKernel.TemplateEngine; +using Microsoft.SemanticKernel.TemplateEngine.Basic; using SemanticKernel.IntegrationTests.TestSettings; using Xunit; using Xunit.Abstractions; @@ -339,6 +340,7 @@ public sealed class OpenAICompletionTests : IDisposable { // Arrange var builder = this._kernelBuilder.WithLoggerFactory(this._logger); + var promptTemplateFactory = new BasicPromptTemplateFactory(); this.ConfigureAzureOpenAI(builder); this.ConfigureInvalidAzureOpenAI(builder); @@ -358,11 +360,11 @@ public sealed class OpenAICompletionTests : IDisposable var defaultFunc = target.RegisterSemanticFunction( "WherePlugin", "FishMarket1", defaultConfig, - new PromptTemplate(prompt, defaultConfig, target.PromptTemplateEngine)); + promptTemplateFactory.Create(prompt, defaultConfig)); var azureFunc = target.RegisterSemanticFunction( "WherePlugin", "FishMarket2", azureConfig, - new PromptTemplate(prompt, azureConfig, target.PromptTemplateEngine)); + promptTemplateFactory.Create(prompt, defaultConfig)); // Act await Assert.ThrowsAsync(() => target.RunAsync(defaultFunc)); diff --git a/dotnet/src/IntegrationTests/Extensions/KernelSemanticFunctionExtensionsTests.cs b/dotnet/src/IntegrationTests/Extensions/KernelSemanticFunctionExtensionsTests.cs index f118965bfa..8f4d4d22f2 100644 --- a/dotnet/src/IntegrationTests/Extensions/KernelSemanticFunctionExtensionsTests.cs +++ b/dotnet/src/IntegrationTests/Extensions/KernelSemanticFunctionExtensionsTests.cs @@ -9,7 +9,6 @@ using Microsoft.SemanticKernel.AI; using Microsoft.SemanticKernel.AI.TextCompletion; using Microsoft.SemanticKernel.Connectors.AI.OpenAI; using Microsoft.SemanticKernel.Orchestration; -using Microsoft.SemanticKernel.TemplateEngine.Basic; using SemanticKernel.IntegrationTests.Fakes; using Xunit; using Xunit.Abstractions; @@ -21,7 +20,6 @@ public sealed class KernelSemanticFunctionExtensionsTests : IDisposable public KernelSemanticFunctionExtensionsTests(ITestOutputHelper output) { this._logger = new RedirectOutput(output); - this._target = new BasicPromptTemplateEngine(); } [Fact] @@ -63,7 +61,6 @@ public sealed class KernelSemanticFunctionExtensionsTests : IDisposable } private readonly RedirectOutput _logger; - private readonly BasicPromptTemplateEngine _target; public void Dispose() { diff --git a/dotnet/src/IntegrationTests/TemplateLanguage/PromptTemplateEngineTests.cs b/dotnet/src/IntegrationTests/TemplateLanguage/PromptTemplateEngineTests.cs index 5c68ca4d34..0ee6981e4f 100644 --- a/dotnet/src/IntegrationTests/TemplateLanguage/PromptTemplateEngineTests.cs +++ b/dotnet/src/IntegrationTests/TemplateLanguage/PromptTemplateEngineTests.cs @@ -16,6 +16,8 @@ namespace SemanticKernel.IntegrationTests.TemplateLanguage; #pragma warning disable VSTHRD103 // ok to use WriteLine synchronously #pragma warning disable CA1849 // ok to use WriteLine synchronously +[Obsolete("Use BasicPromptTemplateFactory instead. This will be removed in a future release.")] +[EditorBrowsable(EditorBrowsableState.Never)] public sealed class PromptTemplateEngineTests : IDisposable { public PromptTemplateEngineTests(ITestOutputHelper output) diff --git a/dotnet/src/Planners/Planners.Core.UnitTests/Sequential/SequentialPlanParserTests.cs b/dotnet/src/Planners/Planners.Core.UnitTests/Sequential/SequentialPlanParserTests.cs index 232e0b6498..c19c3f8c9f 100644 --- a/dotnet/src/Planners/Planners.Core.UnitTests/Sequential/SequentialPlanParserTests.cs +++ b/dotnet/src/Planners/Planners.Core.UnitTests/Sequential/SequentialPlanParserTests.cs @@ -2,6 +2,7 @@ using System.Globalization; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.SemanticKernel.Diagnostics; using Microsoft.SemanticKernel.Orchestration; using Microsoft.SemanticKernel.Services; @@ -32,7 +33,7 @@ public class SequentialPlanParserTests var kernelMock = new Mock(); kernelMock.SetupGet(k => k.Functions).Returns(mockFunctionCollection.Object); - kernelMock.SetupGet(k => k.LoggerFactory).Returns(new Mock().Object); + kernelMock.SetupGet(k => k.LoggerFactory).Returns(NullLoggerFactory.Instance); return kernelMock; } diff --git a/dotnet/src/Planners/Planners.Core.UnitTests/Sequential/SequentialPlannerTests.cs b/dotnet/src/Planners/Planners.Core.UnitTests/Sequential/SequentialPlannerTests.cs index 2506fb1f27..b8d0117c50 100644 --- a/dotnet/src/Planners/Planners.Core.UnitTests/Sequential/SequentialPlannerTests.cs +++ b/dotnet/src/Planners/Planners.Core.UnitTests/Sequential/SequentialPlannerTests.cs @@ -2,6 +2,7 @@ using System.Globalization; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.SemanticKernel.AI; using Microsoft.SemanticKernel.Diagnostics; using Microsoft.SemanticKernel.Orchestration; @@ -20,8 +21,7 @@ public sealed class SequentialPlannerTests public async Task ItCanCreatePlanAsync(string goal) { // Arrange - var kernel = new Mock(); - kernel.Setup(x => x.LoggerFactory).Returns(new Mock().Object); + var kernel = CreateMockKernel(); kernel.Setup(x => x.RunAsync(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(async (vars, cancellationToken, functions) => { @@ -63,7 +63,6 @@ public sealed class SequentialPlannerTests var functionRunner = new Mock(); var serviceProvider = new Mock(); var serviceSelector = new Mock(); - kernel.Setup(x => x.LoggerFactory).Returns(new Mock().Object); var expectedFunctions = input.Select(x => x.name).ToList(); var expectedPlugins = input.Select(x => x.pluginName).ToList(); @@ -141,7 +140,7 @@ public sealed class SequentialPlannerTests public async Task EmptyGoalThrowsAsync() { // Arrange - var kernel = new Mock(); + var kernel = CreateMockKernel(); var planner = new SequentialPlanner(kernel.Object); @@ -200,7 +199,7 @@ public sealed class SequentialPlannerTests public void UsesPromptDelegateWhenProvided() { // Arrange - var kernel = new Mock(); + var kernel = CreateMockKernel(); var getPromptTemplateMock = new Mock>(); var config = new SequentialPlannerConfig() { @@ -223,4 +222,13 @@ public sealed class SequentialPlannerTests mockFunction.Setup(x => x.PluginName).Returns(functionView.PluginName); return mockFunction; } + + // Method to create Mock objects + private static Mock CreateMockKernel() + { + var kernel = new Mock(); + kernel.Setup(x => x.LoggerFactory).Returns(NullLoggerFactory.Instance); + + return kernel; + } } diff --git a/dotnet/src/Planners/Planners.Core/Stepwise/StepwisePlanner.cs b/dotnet/src/Planners/Planners.Core/Stepwise/StepwisePlanner.cs index 8adaf550b4..3d2b0174d2 100644 --- a/dotnet/src/Planners/Planners.Core/Stepwise/StepwisePlanner.cs +++ b/dotnet/src/Planners/Planners.Core/Stepwise/StepwisePlanner.cs @@ -61,7 +61,7 @@ public class StepwisePlanner : IStepwisePlanner this._promptConfig.SetMaxTokens(this.Config.MaxCompletionTokens); // Initialize prompt renderer - this._promptRenderer = new BasicPromptTemplateEngine(this._kernel.LoggerFactory); + this._promptTemplateFactory = new BasicPromptTemplateFactory(this._kernel.LoggerFactory); // Import native functions this._nativeFunctions = this._kernel.ImportFunctions(this, RestrictedPluginName); @@ -350,14 +350,15 @@ public class StepwisePlanner : IStepwisePlanner { var descriptions = await this._kernel.Functions.GetFunctionsManualAsync(this.Config, question, this._logger, cancellationToken).ConfigureAwait(false); context.Variables.Set("functionDescriptions", descriptions); - return await this._promptRenderer.RenderAsync(this._manualTemplate, context, cancellationToken).ConfigureAwait(false); + var promptTemplate = this._promptTemplateFactory.Create(this._manualTemplate, new PromptTemplateConfig()); + return await promptTemplate.RenderAsync(context, cancellationToken).ConfigureAwait(false); } private Task GetUserQuestionAsync(SKContext context, CancellationToken cancellationToken) - => this._promptRenderer.RenderAsync(this._questionTemplate, context, cancellationToken); + => this._promptTemplateFactory.Create(this._questionTemplate, new PromptTemplateConfig()).RenderAsync(context, cancellationToken); private Task GetSystemMessageAsync(SKContext context, CancellationToken cancellationToken) - => this._promptRenderer.RenderAsync(this._promptTemplate, context, cancellationToken); + => this._promptTemplateFactory.Create(this._promptTemplate, new PromptTemplateConfig()).RenderAsync(context, cancellationToken); #endregion setup helpers @@ -648,7 +649,7 @@ public class StepwisePlanner : IStepwisePlanner /// /// The prompt renderer to use for the system step /// - private readonly BasicPromptTemplateEngine _promptRenderer; + private readonly BasicPromptTemplateFactory _promptTemplateFactory; /// /// The prompt config to use for the system step diff --git a/dotnet/src/SemanticKernel.Abstractions/IKernel.cs b/dotnet/src/SemanticKernel.Abstractions/IKernel.cs index 29b10e9e1f..6dbd645141 100644 --- a/dotnet/src/SemanticKernel.Abstractions/IKernel.cs +++ b/dotnet/src/SemanticKernel.Abstractions/IKernel.cs @@ -26,11 +26,6 @@ public interface IKernel /// ILoggerFactory LoggerFactory { get; } - /// - /// Reference to the engine rendering prompt templates - /// - IPromptTemplateEngine PromptTemplateEngine { get; } - /// /// Reference to the read-only function collection containing all the imported functions /// @@ -96,6 +91,13 @@ public interface IKernel #region Obsolete + /// + /// Reference to the engine rendering prompt templates + /// + [Obsolete("PromptTemplateEngine has been replaced with PromptTemplateFactory and will be null. If you pass an PromptTemplateEngine instance when creating a Kernel it will be wrapped in an instance of IPromptTemplateFactory. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] + IPromptTemplateEngine? PromptTemplateEngine { get; } + /// /// Semantic memory instance /// diff --git a/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplate.cs b/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplate.cs index e0cc43e318..40d94be90e 100644 --- a/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplate.cs +++ b/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplate.cs @@ -20,7 +20,7 @@ public interface IPromptTemplate /// /// Render the template using the information in the context /// - /// Kernel execution context helpers + /// Kernel execution context /// The to monitor for cancellation requests. The default is . /// Prompt rendered to string public Task RenderAsync(SKContext executionContext, CancellationToken cancellationToken = default); diff --git a/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplateEngine.cs b/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplateEngine.cs index 2ae1f7b2c5..a9a223a294 100644 --- a/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplateEngine.cs +++ b/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplateEngine.cs @@ -1,5 +1,7 @@ īģŋ// Copyright (c) Microsoft. All rights reserved. +using System; +using System.ComponentModel; using System.Threading; using System.Threading.Tasks; using Microsoft.SemanticKernel.Orchestration; @@ -9,6 +11,8 @@ namespace Microsoft.SemanticKernel.TemplateEngine; /// /// Prompt template engine interface. /// +[Obsolete("PromptTemplateEngine has been replaced with PromptTemplateFactory and will be null. If you pass an PromptTemplateEngine instance when creating a Kernel it will be wrapped in an instance of IPromptTemplateFactory. This will be removed in a future release.")] +[EditorBrowsable(EditorBrowsableState.Never)] public interface IPromptTemplateEngine { /// diff --git a/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplateFactory.cs b/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplateFactory.cs new file mode 100644 index 0000000000..0936c291d3 --- /dev/null +++ b/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/IPromptTemplateFactory.cs @@ -0,0 +1,21 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.Diagnostics; + +namespace Microsoft.SemanticKernel.TemplateEngine; + +/// +/// Prompt template factory interface. +/// Implement this interface to provide support for a new prompt template format. +/// +public interface IPromptTemplateFactory +{ + /// + /// Create an instance of from a template string and a configuration. Return null if the specified template format is not supported. + /// + /// Template string using the format associated with this + /// Prompt template configuration + /// Instance of + /// if template format is not supported + IPromptTemplate Create(string templateString, PromptTemplateConfig promptTemplateConfig); +} diff --git a/dotnet/src/SemanticKernel.Core/TemplateEngine/PromptTemplateConfig.cs b/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/PromptTemplateConfig.cs similarity index 89% rename from dotnet/src/SemanticKernel.Core/TemplateEngine/PromptTemplateConfig.cs rename to dotnet/src/SemanticKernel.Abstractions/TemplateEngine/PromptTemplateConfig.cs index b3588903b4..af931093de 100644 --- a/dotnet/src/SemanticKernel.Core/TemplateEngine/PromptTemplateConfig.cs +++ b/dotnet/src/SemanticKernel.Abstractions/TemplateEngine/PromptTemplateConfig.cs @@ -14,6 +14,11 @@ namespace Microsoft.SemanticKernel.TemplateEngine; /// public class PromptTemplateConfig { + /// + /// Semantic Kernel template format. + /// + public const string SemanticKernelTemplateFormat = "semantic-kernel"; + /// /// Input parameter for semantic functions. /// @@ -57,11 +62,11 @@ public class PromptTemplateConfig } /// - /// Schema - Not currently used. + /// Format of the prompt template e.g. f-string, semantic-kernel, handlebars, ... /// - [JsonPropertyName("schema")] + [JsonPropertyName("template_format")] [JsonPropertyOrder(1)] - public int Schema { get; set; } = 1; + public string TemplateFormat { get; set; } = SemanticKernelTemplateFormat; /// /// Description @@ -96,20 +101,25 @@ public class PromptTemplateConfig } #region Obsolete + /// + /// Schema - Not currently used. + /// + [JsonPropertyName("schema")] + [Obsolete("Type property is no longer used. This will be removed in a future release.")] + public int Schema { get; set; } = 1; + /// /// Type, such as "completion", "embeddings", etc. /// /// TODO: use enum [JsonPropertyName("type")] - [JsonPropertyOrder(5)] - [Obsolete("Type property is no longer required. This will be removed in a future release.")] + [Obsolete("Type property is no longer used. This will be removed in a future release.")] public string Type { get; set; } = "completion"; /// /// Completion configuration parameters. /// [JsonPropertyName("completion")] - [JsonPropertyOrder(6)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [Obsolete("Completion is no longer no longer supported. Use PromptTemplateConfig.ModelSettings collection instead. This will be removed in a future release.")] public AIRequestSettings? Completion @@ -128,7 +138,6 @@ public class PromptTemplateConfig /// Default AI services to use. /// [JsonPropertyName("default_services")] - [JsonPropertyOrder(7)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [Obsolete("DefaultServices property is not being used. This will be removed in a future release.")] public List DefaultServices { get; set; } = new(); diff --git a/dotnet/src/SemanticKernel.Core/Extensions/KernelSemanticFunctionExtensions.cs b/dotnet/src/SemanticKernel.Core/Extensions/KernelSemanticFunctionExtensions.cs index 2bae6043c7..f247d7b39b 100644 --- a/dotnet/src/SemanticKernel.Core/Extensions/KernelSemanticFunctionExtensions.cs +++ b/dotnet/src/SemanticKernel.Core/Extensions/KernelSemanticFunctionExtensions.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; +using System.Linq; +using System.Reflection; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.SemanticKernel.AI; @@ -110,24 +112,27 @@ public static class KernelSemanticFunctionExtensions /// A name for the given function. The name can be referenced in templates and used by the pipeline planner. /// An optional plugin name, e.g. to namespace functions with the same name. When empty, /// the function is added to the global namespace, overwriting functions with the same name + /// Prompt template factory /// A function ready to use public static ISKFunction CreateSemanticFunction( this IKernel kernel, string promptTemplate, PromptTemplateConfig promptTemplateConfig, string? functionName = null, - string? pluginName = null) + string? pluginName = null, + IPromptTemplateFactory? promptTemplateFactory = null) { functionName ??= RandomFunctionName(); Verify.ValidFunctionName(functionName); if (!string.IsNullOrEmpty(pluginName)) { Verify.ValidPluginName(pluginName); } - var template = new PromptTemplate(promptTemplate, promptTemplateConfig, kernel.PromptTemplateEngine); + var factory = promptTemplateFactory ?? CreateDefaultPromptTemplateFactory(kernel); + IPromptTemplate promptTemplateInstance = factory.Create(promptTemplate, promptTemplateConfig); // TODO: manage overwrites, potentially error out return string.IsNullOrEmpty(pluginName) - ? kernel.RegisterSemanticFunction(functionName, promptTemplateConfig, template) - : kernel.RegisterSemanticFunction(pluginName!, functionName, promptTemplateConfig, template); + ? kernel.RegisterSemanticFunction(functionName, promptTemplateConfig, promptTemplateInstance) + : kernel.RegisterSemanticFunction(pluginName!, functionName, promptTemplateConfig, promptTemplateInstance); } /// @@ -168,6 +173,21 @@ public static class KernelSemanticFunctionExtensions } #pragma warning restore CS1591 + /// + /// Imports semantic functions, defined by prompt templates stored in the filesystem. + /// + /// + /// + /// + /// + public static IDictionary ImportSemanticFunctionsFromDirectory( + this IKernel kernel, + string parentDirectory, + params string[] pluginDirectoryNames) + { + return kernel.ImportSemanticFunctionsFromDirectory(parentDirectory, null, pluginDirectoryNames); + } + /// /// Imports semantic functions, defined by prompt templates stored in the filesystem. /// @@ -213,14 +233,20 @@ public static class KernelSemanticFunctionExtensions /// /// Semantic Kernel instance /// Directory containing the plugin directory, e.g. "d:\myAppPlugins" + /// Prompt template factory /// Name of the directories containing the selected plugins, e.g. "StrategyPlugin" /// A list of all the semantic functions found in the directory, indexed by plugin name. public static IDictionary ImportSemanticFunctionsFromDirectory( - this IKernel kernel, string parentDirectory, params string[] pluginDirectoryNames) + this IKernel kernel, + string parentDirectory, + IPromptTemplateFactory? promptTemplateFactory = null, + params string[] pluginDirectoryNames + ) { const string ConfigFile = "config.json"; const string PromptFile = "skprompt.txt"; + var factory = promptTemplateFactory ?? CreateDefaultPromptTemplateFactory(kernel); var functions = new Dictionary(); ILogger? logger = null; @@ -240,34 +266,34 @@ public static class KernelSemanticFunctionExtensions if (!File.Exists(promptPath)) { continue; } // Load prompt configuration. Note: the configuration is optional. - var config = new PromptTemplateConfig(); var configPath = Path.Combine(dir, ConfigFile); - if (File.Exists(configPath)) - { - config = PromptTemplateConfig.FromJson(File.ReadAllText(configPath)); - } + var promptTemplateConfig = File.Exists(configPath) ? + PromptTemplateConfig.FromJson(File.ReadAllText(configPath)) : + new PromptTemplateConfig(); logger ??= kernel.LoggerFactory.CreateLogger(typeof(IKernel)); if (logger.IsEnabled(LogLevel.Trace)) { - logger.LogTrace("Config {0}: {1}", functionName, Json.Serialize(config)); + logger.LogTrace("Config {0}: {1}", functionName, Json.Serialize(promptTemplateConfig)); } // Load prompt template - var template = new PromptTemplate(File.ReadAllText(promptPath), config, kernel.PromptTemplateEngine); + var promptTemplate = File.ReadAllText(promptPath); + IPromptTemplate? promptTemplateInstance = factory.Create(promptTemplate, promptTemplateConfig); if (logger.IsEnabled(LogLevel.Trace)) { logger.LogTrace("Registering function {0}.{1} loaded from {2}", pluginDirectoryName, functionName, dir); } - functions[functionName] = kernel.RegisterSemanticFunction(pluginDirectoryName, functionName, config, template); + functions[functionName] = kernel.RegisterSemanticFunction(pluginDirectoryName, functionName, promptTemplateConfig, promptTemplateInstance); } } return functions; } + #region private private static string RandomFunctionName() => "func" + Guid.NewGuid().ToString("N"); private static ISKFunction CreateSemanticFunction( @@ -285,4 +311,91 @@ public static class KernelSemanticFunctionExtensions kernel.LoggerFactory ); } + + private const string BasicTemplateFactoryAssemblyName = "Microsoft.SemanticKernel.TemplateEngine.Basic"; + private const string BasicTemplateFactoryTypeName = "BasicPromptTemplateFactory"; + private static bool s_promptTemplateFactoryInitialized = false; + private static Type? s_promptTemplateFactoryType = null; + + /// + /// Create a default prompt template factory. + /// + /// This is a temporary solution to avoid breaking existing clients. + /// There will be a separate task to add support for registering instances of IPromptTemplateEngine and obsoleting the current approach. + /// + /// + /// Kernel instance + /// Instance of . + private static IPromptTemplateFactory CreateDefaultPromptTemplateFactory(IKernel kernel) + { +#pragma warning disable CS0618 // Type or member is obsolete + if (kernel.PromptTemplateEngine is not null) + { + return new PromptTemplateFactory(kernel.PromptTemplateEngine); + } +#pragma warning restore CS0618 // Type or member is obsolete + + if (!s_promptTemplateFactoryInitialized) + { + s_promptTemplateFactoryType = GetPromptTemplateFactoryType(); + s_promptTemplateFactoryInitialized = true; + } + + if (s_promptTemplateFactoryType is not null) + { + var constructor = s_promptTemplateFactoryType.GetConstructor(new Type[] { typeof(ILoggerFactory) }); + if (constructor is not null) + { +#pragma warning disable CS8601 // Null logger factory is OK + var factory = (IPromptTemplateFactory)constructor.Invoke(new object[] { kernel.LoggerFactory }); + if (factory is not null) + { + return factory; + } +#pragma warning restore CS8601 + } + } + + throw new SKException($"Unable to create default prompt template factory. Please provide an implementation of IPromptTemplateFactory or depend on {BasicTemplateFactoryAssemblyName}"); + } + + /// + /// Get the prompt template engine type if available + /// + /// The type for the prompt template engine if available + private static Type? GetPromptTemplateFactoryType() + { + try + { + var assembly = Assembly.Load(BasicTemplateFactoryAssemblyName); + + return assembly.ExportedTypes.Single(type => + type.Name.Equals(BasicTemplateFactoryTypeName, StringComparison.Ordinal) && + type.GetInterface(nameof(IPromptTemplateFactory)) is not null); + } + catch (Exception ex) when (!ex.IsCriticalException()) + { + return null; + } + } + + #endregion + + #region Obsolete + [Obsolete("IPromptTemplateEngine is being replaced with IPromptTemplateFactory. This will be removed in a future release.")] + internal sealed class PromptTemplateFactory : IPromptTemplateFactory + { + private readonly IPromptTemplateEngine _promptTemplateEngine; + + public PromptTemplateFactory(IPromptTemplateEngine promptTemplateEngine) + { + this._promptTemplateEngine = promptTemplateEngine; + } + + public IPromptTemplate Create(string templateString, PromptTemplateConfig promptTemplateConfig) + { + return new PromptTemplate(templateString, promptTemplateConfig, this._promptTemplateEngine); + } + } + #endregion } diff --git a/dotnet/src/SemanticKernel.Core/Kernel.cs b/dotnet/src/SemanticKernel.Core/Kernel.cs index 5338bb25a8..f1b792978a 100644 --- a/dotnet/src/SemanticKernel.Core/Kernel.cs +++ b/dotnet/src/SemanticKernel.Core/Kernel.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; +using System.Linq; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -39,9 +41,6 @@ public sealed class Kernel : IKernel, IDisposable /// public IReadOnlyFunctionCollection Functions => this._functionCollection; - /// - public IPromptTemplateEngine PromptTemplateEngine { get; } - /// /// Return a new instance of the kernel builder, used to build and configure kernel instances. /// @@ -66,25 +65,44 @@ public sealed class Kernel : IKernel, IDisposable /// Semantic text Memory /// HTTP handler factory /// The to use for logging. If null, no logging will be performed. - /// AI service selector + /// AI Service selector + [Obsolete("Use IPromptTemplateFactory instead. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] public Kernel( IFunctionCollection functionCollection, IAIServiceProvider aiServiceProvider, - IPromptTemplateEngine promptTemplateEngine, + IPromptTemplateEngine? promptTemplateEngine, ISemanticTextMemory memory, IDelegatingHandlerFactory httpHandlerFactory, ILoggerFactory? loggerFactory, - IAIServiceSelector? serviceSelector = null - ) + IAIServiceSelector? serviceSelector = null) : this(functionCollection, aiServiceProvider, memory, httpHandlerFactory, loggerFactory, serviceSelector) + { + this.PromptTemplateEngine = promptTemplateEngine ?? this.CreateDefaultPromptTemplateEngine(loggerFactory); + } + + /// + /// Kernel constructor. See KernelBuilder for an easier and less error prone approach to create kernel instances. + /// + /// function collection + /// AI Service Provider + /// Semantic text Memory + /// HTTP handler factory + /// The to use for logging. If null, no logging will be performed. + /// AI Service selector + public Kernel( + IFunctionCollection functionCollection, + IAIServiceProvider aiServiceProvider, + ISemanticTextMemory memory, + IDelegatingHandlerFactory httpHandlerFactory, + ILoggerFactory? loggerFactory, + IAIServiceSelector? serviceSelector = null) { loggerFactory ??= NullLoggerFactory.Instance; this.LoggerFactory = loggerFactory; this.HttpHandlerFactory = httpHandlerFactory; - this.PromptTemplateEngine = promptTemplateEngine; this._memory = memory; this._aiServiceProvider = aiServiceProvider; - this._promptTemplateEngine = promptTemplateEngine; this._functionCollection = functionCollection; this._aiServiceSelector = serviceSelector ?? new OrderedIAIServiceSelector(); @@ -216,7 +234,6 @@ repeat: private readonly IFunctionCollection _functionCollection; private ISemanticTextMemory _memory; - private readonly IPromptTemplateEngine _promptTemplateEngine; private readonly IAIServiceProvider _aiServiceProvider; private readonly IAIServiceSelector _aiServiceSelector; private readonly ILogger _logger; @@ -263,6 +280,11 @@ repeat: #region Obsolete =============================================================================== + /// + [Obsolete("Use IPromptTemplateFactory instead. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public IPromptTemplateEngine? PromptTemplateEngine { get; } + /// [Obsolete("Memory functionality will be placed in separate Microsoft.SemanticKernel.Plugins.Memory package. This will be removed in a future release. See sample dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs in the semantic-kernel repository.")] [EditorBrowsable(EditorBrowsableState.Never)] @@ -300,4 +322,81 @@ repeat: #pragma warning restore CS1591 #endregion + + #region Private ==================================================================================== + + private static bool s_promptTemplateEngineInitialized = false; + private static Type? s_promptTemplateEngineType = null; + + /// + /// Create a default prompt template engine. + /// + /// This is a temporary solution to avoid breaking existing clients. + /// There will be a separate task to add support for registering instances of IPromptTemplateEngine and obsoleting the current approach. + /// + /// + /// Logger factory to be used by the template engine + /// Instance of . + [Obsolete("Provided for backward compatibility. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] + private IPromptTemplateEngine CreateDefaultPromptTemplateEngine(ILoggerFactory? loggerFactory = null) + { + if (!s_promptTemplateEngineInitialized) + { + s_promptTemplateEngineType = this.GetPromptTemplateEngineType(); + s_promptTemplateEngineInitialized = true; + } + + if (s_promptTemplateEngineType is not null) + { + var constructor = s_promptTemplateEngineType.GetConstructor(new Type[] { typeof(ILoggerFactory) }); + if (constructor is not null) + { +#pragma warning disable CS8601 // Null logger factory is OK + return (IPromptTemplateEngine)constructor.Invoke(new object[] { loggerFactory }); +#pragma warning restore CS8601 + } + } + + return new NullPromptTemplateEngine(); + } + + /// + /// Get the prompt template engine type if available + /// + /// The type for the prompt template engine if available + [Obsolete("Provided for backward compatibility. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] + private Type? GetPromptTemplateEngineType() + { + try + { + var assembly = Assembly.Load("Microsoft.SemanticKernel.TemplateEngine.Basic"); + + return assembly.ExportedTypes.Single(type => + type.Name.Equals("BasicPromptTemplateEngine", StringComparison.Ordinal) && + type.GetInterface(nameof(IPromptTemplateEngine)) is not null); + } + catch (Exception ex) when (!ex.IsCriticalException()) + { + return null; + } + } + + #endregion +} + +/// +/// No-operation IPromptTemplateEngine which performs no rendering of the template. +/// +/// This is a temporary solution to avoid breaking existing clients. +/// +[Obsolete("This is used for backward compatibility. This will be removed in a future release.")] +[EditorBrowsable(EditorBrowsableState.Never)] +internal sealed class NullPromptTemplateEngine : IPromptTemplateEngine +{ + public Task RenderAsync(string templateText, SKContext context, CancellationToken cancellationToken = default) + { + return Task.FromResult(templateText); + } } diff --git a/dotnet/src/SemanticKernel.Core/KernelBuilder.cs b/dotnet/src/SemanticKernel.Core/KernelBuilder.cs index 201397cf59..8c614c351d 100644 --- a/dotnet/src/SemanticKernel.Core/KernelBuilder.cs +++ b/dotnet/src/SemanticKernel.Core/KernelBuilder.cs @@ -2,16 +2,11 @@ using System; using System.ComponentModel; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.SemanticKernel.Diagnostics; using Microsoft.SemanticKernel.Http; using Microsoft.SemanticKernel.Memory; -using Microsoft.SemanticKernel.Orchestration; using Microsoft.SemanticKernel.Services; using Microsoft.SemanticKernel.TemplateEngine; @@ -26,13 +21,12 @@ public sealed class KernelBuilder private ILoggerFactory _loggerFactory = NullLoggerFactory.Instance; private Func? _memoryStorageFactory = null; private IDelegatingHandlerFactory _httpHandlerFactory = NullHttpHandlerFactory.Instance; + [Obsolete("Use IPromptTemplateFactory instead. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] private IPromptTemplateEngine? _promptTemplateEngine; private readonly AIServiceCollection _aiServices = new(); private IAIServiceSelector? _serviceSelector; - private static bool s_promptTemplateEngineInitialized = false; - private static Type? s_promptTemplateEngineType = null; - /// /// Create a new kernel instance /// @@ -49,15 +43,19 @@ public sealed class KernelBuilder /// Kernel instance public IKernel Build() { +#pragma warning disable CS8604 // Possible null reference argument. +#pragma warning disable CS0618 // Type or member is obsolete var instance = new Kernel( new FunctionCollection(), this._aiServices.Build(), - this._promptTemplateEngine ?? this.CreateDefaultPromptTemplateEngine(this._loggerFactory), + this._promptTemplateEngine, this._memoryFactory.Invoke(), this._httpHandlerFactory, this._loggerFactory, this._serviceSelector ); +#pragma warning restore CS0618 // Type or member is obsolete +#pragma warning restore CS8604 // Possible null reference argument. // TODO: decouple this from 'UseMemory' kernel extension if (this._memoryStorageFactory != null) @@ -157,6 +155,8 @@ public sealed class KernelBuilder /// /// Prompt template engine to add. /// Updated kernel builder including the prompt template engine. + [Obsolete("Use IPromptTemplateFactory instead. This will be removed in a future release.")] + [EditorBrowsable(EditorBrowsableState.Never)] public KernelBuilder WithPromptTemplateEngine(IPromptTemplateEngine promptTemplateEngine) { Verify.NotNull(promptTemplateEngine); @@ -260,68 +260,4 @@ public sealed class KernelBuilder this._serviceSelector = serviceSelector; return this; } - - /// - /// Create a default prompt template engine. - /// - /// This is a temporary solution to avoid breaking existing clients. - /// There will be a separate task to add support for registering instances of IPromptTemplateEngine and obsoleting the current approach. - /// - /// - /// Logger factory to be used by the template engine - /// Instance of . - private IPromptTemplateEngine CreateDefaultPromptTemplateEngine(ILoggerFactory? loggerFactory = null) - { - if (!s_promptTemplateEngineInitialized) - { - s_promptTemplateEngineType = this.GetPromptTemplateEngineType(); - s_promptTemplateEngineInitialized = true; - } - - if (s_promptTemplateEngineType is not null) - { - var constructor = s_promptTemplateEngineType.GetConstructor(new Type[] { typeof(ILoggerFactory) }); - if (constructor is not null) - { -#pragma warning disable CS8601 // Null logger factory is OK - return (IPromptTemplateEngine)constructor.Invoke(new object[] { loggerFactory }); -#pragma warning restore CS8601 - } - } - - return new NullPromptTemplateEngine(); - } - - /// - /// Get the prompt template engine type if available - /// - /// The type for the prompt template engine if available - private Type? GetPromptTemplateEngineType() - { - try - { - var assembly = Assembly.Load("Microsoft.SemanticKernel.TemplateEngine.Basic"); - - return assembly.ExportedTypes.Single(type => - type.Name.Equals("BasicPromptTemplateEngine", StringComparison.Ordinal) && - type.GetInterface(nameof(IPromptTemplateEngine)) is not null); - } - catch (Exception ex) when (!ex.IsCriticalException()) - { - return null; - } - } -} - -/// -/// No-operation IPromptTemplateEngine which performs no rendering of the template. -/// -/// This is a temporary solution to avoid breaking existing clients. -/// -internal sealed class NullPromptTemplateEngine : IPromptTemplateEngine -{ - public Task RenderAsync(string templateText, SKContext context, CancellationToken cancellationToken = default) - { - return Task.FromResult(templateText); - } } diff --git a/dotnet/src/SemanticKernel.Core/TemplateEngine/AggregatorPromptTemplateFactory.cs b/dotnet/src/SemanticKernel.Core/TemplateEngine/AggregatorPromptTemplateFactory.cs new file mode 100644 index 0000000000..7ac933c1ed --- /dev/null +++ b/dotnet/src/SemanticKernel.Core/TemplateEngine/AggregatorPromptTemplateFactory.cs @@ -0,0 +1,56 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.Diagnostics; + +namespace Microsoft.SemanticKernel.TemplateEngine; + +/// +/// Implementation of which aggregates multiple prompt template factories. +/// +public class AggregatorPromptTemplateFactory : IPromptTemplateFactory +{ + private readonly IPromptTemplateFactory[] _promptTemplateFactories; + + /// + /// Constructor for . + /// + /// List of instances + public AggregatorPromptTemplateFactory(params IPromptTemplateFactory[] promptTemplateFactories) + { + Verify.NotNull(promptTemplateFactories); + + if (promptTemplateFactories.Length == 0) + { + throw new SKException("At least one prompt template factory must be specified."); + } + + this._promptTemplateFactories = promptTemplateFactories; + } + + /// + /// Create an instance of from a template string and a configuration. Throws an if the specified template format is not supported. + /// + /// Template string using the format associated with this + /// Prompt template configuration + /// + public IPromptTemplate Create(string templateString, PromptTemplateConfig promptTemplateConfig) + { + foreach (var promptTemplateFactory in this._promptTemplateFactories) + { + try + { + var promptTemplate = promptTemplateFactory.Create(templateString, promptTemplateConfig); + if (promptTemplate != null) + { + return promptTemplate; + } + } + catch (SKException) + { + // Ignore the exception and try the next factory + } + } + + throw new SKException($"Prompt template format {promptTemplateConfig.TemplateFormat} is not supported."); + } +} diff --git a/dotnet/src/SemanticKernel.Core/TemplateEngine/PromptTemplate.cs b/dotnet/src/SemanticKernel.Core/TemplateEngine/PromptTemplate.cs index 74b9912c97..f91dc3572e 100644 --- a/dotnet/src/SemanticKernel.Core/TemplateEngine/PromptTemplate.cs +++ b/dotnet/src/SemanticKernel.Core/TemplateEngine/PromptTemplate.cs @@ -12,6 +12,7 @@ namespace Microsoft.SemanticKernel.TemplateEngine; /// /// Prompt template. /// +[Obsolete("IPromptTemplateEngine is being replaced with IPromptTemplateFactory. This will be removed in a future release.")] public sealed class PromptTemplate : IPromptTemplate { private readonly string _template; @@ -20,17 +21,6 @@ public sealed class PromptTemplate : IPromptTemplate // ReSharper disable once NotAccessedField.Local private readonly PromptTemplateConfig _promptConfig; - /// - /// Constructor for PromptTemplate. - /// - /// Template. - /// Prompt template configuration. - /// Kernel in which template is to take effect. - public PromptTemplate(string template, PromptTemplateConfig promptTemplateConfig, IKernel kernel) - : this(template, promptTemplateConfig, kernel.PromptTemplateEngine) - { - } - /// /// Constructor for PromptTemplate. /// diff --git a/dotnet/src/SemanticKernel.UnitTests/TemplateEngine/AggregatorPromptTemplateFactoryTests.cs b/dotnet/src/SemanticKernel.UnitTests/TemplateEngine/AggregatorPromptTemplateFactoryTests.cs new file mode 100644 index 0000000000..0533276062 --- /dev/null +++ b/dotnet/src/SemanticKernel.UnitTests/TemplateEngine/AggregatorPromptTemplateFactoryTests.cs @@ -0,0 +1,114 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Orchestration; +using Microsoft.SemanticKernel.TemplateEngine; +using Xunit; + +namespace SemanticKernel.UnitTests.TemplateEngine; +public sealed class AggregatorPromptTemplateFactoryTests +{ + [Fact] + public void ItCreatesMyPromptTemplates() + { + // Arrange + var templateString = "{{$input}}"; + var target = new AggregatorPromptTemplateFactory(new MyPromptTemplateFactory1(), new MyPromptTemplateFactory2()); + + // Act + var result1 = target.Create(templateString, new PromptTemplateConfig() { TemplateFormat = "my-format-1" }); + var result2 = target.Create(templateString, new PromptTemplateConfig() { TemplateFormat = "my-format-2" }); + + // Assert + Assert.NotNull(result1); + Assert.True(result1 is MyPromptTemplate1); + Assert.NotNull(result2); + Assert.True(result2 is MyPromptTemplate2); + } + + [Fact] + public void ItThrowsExceptionForUnknowPromptTemplateFormat() + { + // Arrange + var templateString = "{{$input}}"; + var target = new AggregatorPromptTemplateFactory(new MyPromptTemplateFactory1(), new MyPromptTemplateFactory2()); + + // Act + var result1 = target.Create(templateString, new PromptTemplateConfig() { TemplateFormat = "my-format-1" }); + var result2 = target.Create(templateString, new PromptTemplateConfig() { TemplateFormat = "my-format-2" }); + + // Assert + Assert.Throws(() => target.Create(templateString, new PromptTemplateConfig() { TemplateFormat = "unknown-format" })); + } + + #region private + private sealed class MyPromptTemplateFactory1 : IPromptTemplateFactory + { + public IPromptTemplate Create(string templateString, PromptTemplateConfig promptTemplateConfig) + { + if (promptTemplateConfig.TemplateFormat.Equals("my-format-1", System.StringComparison.Ordinal)) + { + return new MyPromptTemplate1(templateString, promptTemplateConfig); + } + + throw new SKException($"Prompt template format {promptTemplateConfig.TemplateFormat} is not supported."); + } + } + + private sealed class MyPromptTemplate1 : IPromptTemplate + { + private readonly string _templateString; + private readonly PromptTemplateConfig _promptTemplateConfig; + + public MyPromptTemplate1(string templateString, PromptTemplateConfig promptTemplateConfig) + { + this._templateString = templateString; + this._promptTemplateConfig = promptTemplateConfig; + } + + public IReadOnlyList Parameters => Array.Empty(); + + public Task RenderAsync(SKContext executionContext, CancellationToken cancellationToken = default) + { + return Task.FromResult(this._templateString); + } + } + + private sealed class MyPromptTemplateFactory2 : IPromptTemplateFactory + { + public IPromptTemplate Create(string templateString, PromptTemplateConfig promptTemplateConfig) + { + if (promptTemplateConfig.TemplateFormat.Equals("my-format-2", System.StringComparison.Ordinal)) + { + return new MyPromptTemplate2(templateString, promptTemplateConfig); + } + + throw new SKException($"Prompt template format {promptTemplateConfig.TemplateFormat} is not supported."); + } + } + + private sealed class MyPromptTemplate2 : IPromptTemplate + { + private readonly string _templateString; + private readonly PromptTemplateConfig _promptTemplateConfig; + + public MyPromptTemplate2(string templateString, PromptTemplateConfig promptTemplateConfig) + { + this._templateString = templateString; + this._promptTemplateConfig = promptTemplateConfig; + } + + public IReadOnlyList Parameters => Array.Empty(); + + public Task RenderAsync(SKContext executionContext, CancellationToken cancellationToken = default) + { + return Task.FromResult(this._templateString); + } + } + #endregion +} From 19815a7432e1414ce430df9208067aaf3a22a3c1 Mon Sep 17 00:00:00 2001 From: Lee Miller Date: Mon, 6 Nov 2023 12:27:15 -0800 Subject: [PATCH 005/576] .Net: Add Flow Orchestrator extension to Semantic Kernel (#3023) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary This pull request adds the Flow Orchestrator extension to the Semantic Kernel. The Flow Orchestrator extension provides a way to define and execute complex workflows using a YAML-based DSL. The extension includes several new classes and extension methods, as well as a new project file and several new files in the Extensions/Experimental/Orchestration.Flow directory. ## Changes - Added Experimental.Orchestration.Flow.csproj - Added ContextVariablesExtensions.cs - Added FlowExtensions.cs - Added SKContextExtensions.cs - Added new file SKContextExtensions.cs - Added new file FlowOrchestrator.cs - Added new file FlowOrchestratorConfig.cs - Added FlowOrchestratorConfig class to provide configuration options for the ReAct engine used by the Flow orchestrator - Added FlowOrchestrator class to provide a way to define and execute complex workflows using a YAML-based DSL - Added SKContextExtensions class to provide several extension methods for the SKContext class - Added FlowExtensions class to provide extension methods for the Flow class --- *Powered by [Microsoft Semantic Kernel](https://github.com/microsoft/semantic-kernel)* Fixes #2164 ![image](https://github.com/microsoft/semantic-kernel/assets/35783676/a065e637-c89f-4f2e-986e-629b71ccf81c) ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone :smile: - [x] Successful [Integration Tests](https://github.com/microsoft/semantic-kernel/actions/runs/6355696897/job/17264142726) [Integration Tests](https://github.com/microsoft/semantic-kernel/actions/runs/6551142172) @yan-li Co-authored-by: Yan Li [yan-li@users.noreply.github.com](mailto:yan-li@users.noreply.github.com) --------- Signed-off-by: dependabot[bot] Co-authored-by: Yan Li Co-authored-by: Yan Li Co-authored-by: Mark Karle Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Shawn Callegari <36091529+shawncal@users.noreply.github.com> Co-authored-by: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com> Co-authored-by: Eduard van Valkenburg Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Co-authored-by: Lisa Harrylock Co-authored-by: Shay Rojansky Co-authored-by: Anthony Puppo Co-authored-by: Weihan Li Co-authored-by: Jadyn Co-authored-by: Matthew BolaÃąos Co-authored-by: Abby Harrison <54643756+awharrison-28@users.noreply.github.com> Co-authored-by: Weihan Li Co-authored-by: Gina Triolo <51341242+gitri-ms@users.noreply.github.com> Co-authored-by: Jib --- dotnet/Directory.Packages.props | 1 + dotnet/SK-dotnet.sln | 31 + .../Example63_FlowOrchestrator.cs | 372 +++++++++ .../KernelSyntaxExamples.csproj | 1 + .../.editorconfig | 6 + .../CollectEmailPlugin.cs | 84 +++ ...Orchestration.Flow.IntegrationTests.csproj | 49 ++ .../FlowOrchestratorTests.cs | 146 ++++ .../README.md | 115 +++ .../RedirectOutput.cs | 55 ++ .../SendEmailPlugin.cs | 39 + .../TestSettings/AzureOpenAIConfiguration.cs | 29 + .../TestSettings/OpenAIConfiguration.cs | 23 + .../XunitLogger.cs | 43 ++ .../testsettings.json | 34 + .../.editorconfig | 6 + .../ChatHistorySerializerTest.cs | 48 ++ ...mental.Orchestration.Flow.UnitTests.csproj | 38 + .../FlowExtensionsTests.cs | 125 ++++ .../FlowSerializerTests.cs | 64 ++ .../FlowValidatorTests.cs | 113 +++ .../TestData/Flow/flow.json | 39 + .../TestData/Flow/flow.yml | 44 ++ .../XunitHelpers/TestConsoleLogger.cs | 31 + .../Abstractions/IFlowCatalog.cs | 32 + .../Abstractions/IFlowExecutor.cs | 22 + .../Abstractions/IFlowStatusProvider.cs | 63 ++ .../Abstractions/IFlowValidator.cs | 15 + .../Orchestration.Flow/EmbeddedResource.cs | 32 + .../Execution/ChatHistorySerializer.cs | 51 ++ .../Orchestration.Flow/Execution/Constants.cs | 67 ++ .../Execution/ExecutionState.cs | 87 +++ .../Execution/FlowExecutor.cs | 705 ++++++++++++++++++ .../Execution/FlowStatusProvider.cs | 169 +++++ .../Execution/ReActEngine.cs | 428 +++++++++++ .../Orchestration.Flow/Execution/ReActStep.cs | 51 ++ .../Experimental.Orchestration.Flow.csproj | 35 + .../Extensions/ContextVariablesExtensions.cs | 58 ++ .../Extensions/FlowExtensions.cs | 76 ++ .../PromptTemplateConfigExtensions.cs | 29 + .../Extensions/SKContextExtensions.cs | 92 +++ .../Orchestration.Flow/FlowOrchestrator.cs | 82 ++ .../FlowOrchestratorConfig.cs | 76 ++ .../Orchestration.Flow/FlowSerializer.cs | 119 +++ .../Orchestration.Flow/FlowValidator.cs | 102 +++ .../Model/CompletionType.cs | 31 + .../Orchestration.Flow/Model/Flow.cs | 85 +++ .../Orchestration.Flow/Model/FlowStep.cs | 236 ++++++ .../Model/ReferenceFlowStep.cs | 32 + .../Plugins/CheckRepeatStep/config.json | 32 + .../Plugins/CheckRepeatStep/skprompt.txt | 42 ++ .../Plugins/CheckStartStep/config.json | 32 + .../Plugins/CheckStartStep/skprompt.txt | 42 ++ .../Plugins/ReActEngine/config.json | 32 + .../Plugins/ReActEngine/gpt4/config.json | 32 + .../Plugins/ReActEngine/gpt4/skprompt.txt | 55 ++ .../Plugins/ReActEngine/skprompt.txt | 78 ++ .../Extensions.UnitTests.csproj | 6 +- .../src/Extensions/DictionaryExtensions.cs | 27 + 59 files changed, 4684 insertions(+), 5 deletions(-) create mode 100644 dotnet/samples/KernelSyntaxExamples/Example63_FlowOrchestrator.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/.editorconfig create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/CollectEmailPlugin.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/Experimental.Orchestration.Flow.IntegrationTests.csproj create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/FlowOrchestratorTests.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/README.md create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/RedirectOutput.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/SendEmailPlugin.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/TestSettings/AzureOpenAIConfiguration.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/TestSettings/OpenAIConfiguration.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/XunitLogger.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/testsettings.json create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/.editorconfig create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/ChatHistorySerializerTest.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/Experimental.Orchestration.Flow.UnitTests.csproj create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowExtensionsTests.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowSerializerTests.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowValidatorTests.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/TestData/Flow/flow.json create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/TestData/Flow/flow.yml create mode 100644 dotnet/src/Experimental/Orchestration.Flow.UnitTests/XunitHelpers/TestConsoleLogger.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowCatalog.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowExecutor.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowStatusProvider.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowValidator.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/EmbeddedResource.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Execution/ChatHistorySerializer.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Execution/Constants.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Execution/ExecutionState.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Execution/FlowExecutor.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Execution/FlowStatusProvider.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Execution/ReActEngine.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Execution/ReActStep.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Extensions/ContextVariablesExtensions.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Extensions/FlowExtensions.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Extensions/PromptTemplateConfigExtensions.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Extensions/SKContextExtensions.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/FlowOrchestrator.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/FlowOrchestratorConfig.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/FlowSerializer.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/FlowValidator.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Model/CompletionType.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Model/Flow.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Model/FlowStep.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Model/ReferenceFlowStep.cs create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckRepeatStep/config.json create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckRepeatStep/skprompt.txt create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckStartStep/config.json create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckStartStep/skprompt.txt create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/config.json create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/gpt4/config.json create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/gpt4/skprompt.txt create mode 100644 dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/skprompt.txt create mode 100644 dotnet/src/InternalUtilities/src/Extensions/DictionaryExtensions.cs diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index e58ac9af56..46af37f2c9 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -59,6 +59,7 @@ + diff --git a/dotnet/SK-dotnet.sln b/dotnet/SK-dotnet.sln index 86b0ceb3d3..fa0837075e 100644 --- a/dotnet/SK-dotnet.sln +++ b/dotnet/SK-dotnet.sln @@ -1,3 +1,4 @@ +īģŋ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.4.33213.308 @@ -164,6 +165,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.Memory.Milvus", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugins.Memory", "src\Plugins\Plugins.Memory\Plugins.Memory.csproj", "{E91365A1-8B01-4AB8-825F-67E3515EADCD}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "experimental", "experimental", "{A2357CF8-3BB9-45A1-93F1-B366C9B63658}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Experimental.Orchestration.Flow", "src\Experimental\Orchestration.Flow\Experimental.Orchestration.Flow.csproj", "{C8BFFC74-3050-4F63-9E9D-C4F600427DE9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Experimental.Orchestration.Flow.UnitTests", "src\Experimental\Orchestration.Flow.UnitTests\Experimental.Orchestration.Flow.UnitTests.csproj", "{CB6E74CD-3A25-459F-A578-DEF25A414335}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Experimental.Orchestration.Flow.IntegrationTests", "src\Experimental\Orchestration.Flow.IntegrationTests\Experimental.Orchestration.Flow.IntegrationTests.csproj", "{C17DD7E1-E588-46AF-A87E-DF8829A021DC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -405,6 +414,24 @@ Global {E91365A1-8B01-4AB8-825F-67E3515EADCD}.Publish|Any CPU.Build.0 = Debug|Any CPU {E91365A1-8B01-4AB8-825F-67E3515EADCD}.Release|Any CPU.ActiveCfg = Release|Any CPU {E91365A1-8B01-4AB8-825F-67E3515EADCD}.Release|Any CPU.Build.0 = Release|Any CPU + {C8BFFC74-3050-4F63-9E9D-C4F600427DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8BFFC74-3050-4F63-9E9D-C4F600427DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8BFFC74-3050-4F63-9E9D-C4F600427DE9}.Publish|Any CPU.ActiveCfg = Publish|Any CPU + {C8BFFC74-3050-4F63-9E9D-C4F600427DE9}.Publish|Any CPU.Build.0 = Publish|Any CPU + {C8BFFC74-3050-4F63-9E9D-C4F600427DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8BFFC74-3050-4F63-9E9D-C4F600427DE9}.Release|Any CPU.Build.0 = Release|Any CPU + {CB6E74CD-3A25-459F-A578-DEF25A414335}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB6E74CD-3A25-459F-A578-DEF25A414335}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB6E74CD-3A25-459F-A578-DEF25A414335}.Publish|Any CPU.ActiveCfg = Debug|Any CPU + {CB6E74CD-3A25-459F-A578-DEF25A414335}.Publish|Any CPU.Build.0 = Debug|Any CPU + {CB6E74CD-3A25-459F-A578-DEF25A414335}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB6E74CD-3A25-459F-A578-DEF25A414335}.Release|Any CPU.Build.0 = Release|Any CPU + {C17DD7E1-E588-46AF-A87E-DF8829A021DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C17DD7E1-E588-46AF-A87E-DF8829A021DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C17DD7E1-E588-46AF-A87E-DF8829A021DC}.Publish|Any CPU.ActiveCfg = Debug|Any CPU + {C17DD7E1-E588-46AF-A87E-DF8829A021DC}.Publish|Any CPU.Build.0 = Debug|Any CPU + {C17DD7E1-E588-46AF-A87E-DF8829A021DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C17DD7E1-E588-46AF-A87E-DF8829A021DC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -464,6 +491,10 @@ Global {CC77DCFA-A419-4202-A98A-868CDF457792} = {A21FAC7C-0C09-4EAD-843B-926ACEF73C80} {8B754E80-7A97-4585-8D7E-1D588FA5F727} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C} {E91365A1-8B01-4AB8-825F-67E3515EADCD} = {D6D598DF-C17C-46F4-B2B9-CDE82E2DE132} + {A2357CF8-3BB9-45A1-93F1-B366C9B63658} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0} + {C8BFFC74-3050-4F63-9E9D-C4F600427DE9} = {A2357CF8-3BB9-45A1-93F1-B366C9B63658} + {CB6E74CD-3A25-459F-A578-DEF25A414335} = {A2357CF8-3BB9-45A1-93F1-B366C9B63658} + {C17DD7E1-E588-46AF-A87E-DF8829A021DC} = {A2357CF8-3BB9-45A1-93F1-B366C9B63658} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FBDC56A3-86AD-4323-AA0F-201E59123B83} diff --git a/dotnet/samples/KernelSyntaxExamples/Example63_FlowOrchestrator.cs b/dotnet/samples/KernelSyntaxExamples/Example63_FlowOrchestrator.cs new file mode 100644 index 0000000000..cd6013d808 --- /dev/null +++ b/dotnet/samples/KernelSyntaxExamples/Example63_FlowOrchestrator.cs @@ -0,0 +1,372 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Text.Json; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.AI; +using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI; +using Microsoft.SemanticKernel.Experimental.Orchestration; +using Microsoft.SemanticKernel.Orchestration; +using Microsoft.SemanticKernel.Plugins.Core; +using Microsoft.SemanticKernel.Plugins.Memory; +using Microsoft.SemanticKernel.Plugins.Web; +using Microsoft.SemanticKernel.Plugins.Web.Bing; +using NCalcPlugins; + +/** + * This example shows how to use FlowOrchestrator to execute a given flow with interaction with client. + */ + +// ReSharper disable once InconsistentNaming +public static class Example63_FlowOrchestrator +{ + private static readonly Flow s_flow = FlowSerializer.DeserializeFromYaml(@" +name: FlowOrchestrator_Example_Flow +goal: answer question and send email +steps: + - goal: What is the tallest mountain on Earth? How tall is it divided by 2? + plugins: + - WebSearchEnginePlugin + - LanguageCalculatorPlugin + provides: + - answer + - goal: Collect email address + plugins: + - ChatPlugin + completionType: AtLeastOnce + transitionMessage: do you want to send it to another email address? + provides: + - email_addresses + + - goal: Send email + plugins: + - EmailPluginV2 + requires: + - email_addresses + - answer + provides: + - email + +provides: + - email +"); + + public static Task RunAsync() + { + // Load assemblies for external plugins + Console.WriteLine("Loading {0}", typeof(SimpleCalculatorPlugin).AssemblyQualifiedName); + + return RunExampleAsync(); + //return RunInteractiveAsync(); + } + + private static async Task RunInteractiveAsync() + { + var bingConnector = new BingConnector(TestConfiguration.Bing.ApiKey); + var webSearchEnginePlugin = new WebSearchEnginePlugin(bingConnector); + using var loggerFactory = LoggerFactory.Create(loggerBuilder => + loggerBuilder + .AddConsole() + .AddFilter(null, LogLevel.Error)); + Dictionary plugins = new() + { + { webSearchEnginePlugin, "WebSearch" }, + { new TimePlugin(), "Time" } + }; + + FlowOrchestrator orchestrator = new( + GetKernelBuilder(loggerFactory), + await FlowStatusProvider.ConnectAsync(new VolatileMemoryStore()).ConfigureAwait(false), + plugins, + config: GetOrchestratorConfig()); + var sessionId = Guid.NewGuid().ToString(); + + Console.WriteLine("*****************************************************"); + Console.WriteLine("Executing {0}", nameof(RunInteractiveAsync)); + Stopwatch sw = new(); + sw.Start(); + Console.WriteLine("Flow: " + s_flow.Name); + Console.WriteLine("Please type the question you'd like to ask"); + ContextVariables? result; + string? goal = null; + do + { + Console.WriteLine("User: "); + string input = Console.ReadLine() ?? string.Empty; + + if (string.IsNullOrEmpty(input)) + { + Console.WriteLine("No input, exiting"); + break; + } + + if (string.IsNullOrEmpty(goal)) + { + s_flow.Steps.First().Goal = input; + } + + result = await orchestrator.ExecuteFlowAsync(s_flow, sessionId, input); + Console.WriteLine("Assistant: " + result.ToString()); + + if (result.IsComplete(s_flow)) + { + Console.WriteLine("\tEmail Address: " + result["email_addresses"]); + Console.WriteLine("\tEmail Payload: " + result["email"]); + + Console.WriteLine("Flow completed, exiting"); + break; + } + } while (!string.IsNullOrEmpty(result.ToString()) && result.ToString() != "[]"); + + Console.WriteLine("Time Taken: " + sw.Elapsed); + Console.WriteLine("*****************************************************"); + } + + private static async Task RunExampleAsync() + { + var bingConnector = new BingConnector(TestConfiguration.Bing.ApiKey); + var webSearchEnginePlugin = new WebSearchEnginePlugin(bingConnector); + using var loggerFactory = LoggerFactory.Create(loggerBuilder => + loggerBuilder + .AddConsole() + .AddFilter(null, LogLevel.Error)); + + Dictionary plugins = new() + { + { webSearchEnginePlugin, "WebSearch" }, + { new TimePlugin(), "Time" } + }; + + FlowOrchestrator orchestrator = new( + GetKernelBuilder(loggerFactory), + await FlowStatusProvider.ConnectAsync(new VolatileMemoryStore()).ConfigureAwait(false), + plugins, + config: GetOrchestratorConfig()); + var sessionId = Guid.NewGuid().ToString(); + + Console.WriteLine("*****************************************************"); + Console.WriteLine("Executing {0}", nameof(RunExampleAsync)); + Stopwatch sw = new(); + sw.Start(); + Console.WriteLine("Flow: " + s_flow.Name); + var question = s_flow.Steps.First().Goal; + var result = await orchestrator.ExecuteFlowAsync(s_flow, sessionId, question).ConfigureAwait(false); + + Console.WriteLine("Question: " + question); + Console.WriteLine("Answer: " + result["answer"]); + Console.WriteLine("Assistant: " + result.ToString()); + + string[] userInputs = new[] + { + "my email is bad*email&address", + "my email is sample@xyz.com", + "yes", // confirm to add another email address + "I also want to notify foo@bar.com", + "no I don't need notify any more address", // end of collect emails + }; + + foreach (var t in userInputs) + { + Console.WriteLine($"User: {t}"); + result = await orchestrator.ExecuteFlowAsync(s_flow, sessionId, t).ConfigureAwait(false); + Console.WriteLine("Assistant: " + result.ToString()); + + if (result.IsComplete(s_flow)) + { + break; + } + } + + Console.WriteLine("\tEmail Address: " + result["email_addresses"]); + Console.WriteLine("\tEmail Payload: " + result["email"]); + + Console.WriteLine("Time Taken: " + sw.Elapsed); + Console.WriteLine("*****************************************************"); + } + + private static FlowOrchestratorConfig GetOrchestratorConfig() + { + var config = new FlowOrchestratorConfig + { + MaxStepIterations = 20 + }; + + return config; + } + + private static KernelBuilder GetKernelBuilder(ILoggerFactory loggerFactory) + { + var builder = new KernelBuilder(); + + return builder + .WithAzureChatCompletionService( + TestConfiguration.AzureOpenAI.ChatDeploymentName, + TestConfiguration.AzureOpenAI.Endpoint, + TestConfiguration.AzureOpenAI.ApiKey, + true, + setAsDefault: true) + .WithRetryBasic(new() + { + MaxRetryCount = 3, + UseExponentialBackoff = true, + MinRetryDelay = TimeSpan.FromSeconds(3), + }) + .WithLoggerFactory(loggerFactory); + } + + public sealed class ChatPlugin + { + private const string Goal = "Prompt user to provide a valid email address"; + + private const string EmailRegex = @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$"; + + private const string SystemPrompt = + $@"I am AI assistant and will only answer questions related to collect email. +The email should conform the regex: {EmailRegex} + +If I cannot answer, say that I don't know. +Do not expose the regex unless asked. +"; + + private readonly IChatCompletion _chat; + + private int MaxTokens { get; set; } = 256; + + private readonly AIRequestSettings _chatRequestSettings; + + public ChatPlugin(IKernel kernel) + { + this._chat = kernel.GetService(); + this._chatRequestSettings = new OpenAIRequestSettings + { + MaxTokens = this.MaxTokens, + StopSequences = new List() { "Observation:" }, + Temperature = 0 + }; + } + + [SKFunction] + [Description("Useful to assist in configuration of email address, must be called after email provided")] + [SKName("ConfigureEmailAddress")] + public async Task CollectEmailAsync( + [SKName("email_address")] + [Description("The email address provided by the user, pass no matter what the value is")] + string email, + SKContext context) + { + var chat = this._chat.CreateNewChat(SystemPrompt); + chat.AddUserMessage(Goal); + + ChatHistory? chatHistory = context.GetChatHistory(); + if (chatHistory?.Any() ?? false) + { + chat.Messages.AddRange(chatHistory); + } + + if (!string.IsNullOrEmpty(email) && IsValidEmail(email)) + { + context.Variables["email_addresses"] = email; + + return "Thanks for providing the info, the following email would be used in subsequent steps: " + email; + } + + context.Variables["email_addresses"] = string.Empty; + context.PromptInput(); + + return await this._chat.GenerateMessageAsync(chat, this._chatRequestSettings).ConfigureAwait(false); + } + + private static bool IsValidEmail(string email) + { + // check using regex + var regex = new Regex(EmailRegex); + return regex.IsMatch(email); + } + } + + public sealed class EmailPluginV2 + { + [SKFunction] + [Description("Send email")] + [SKName("SendEmail")] + public string SendEmail( + [SKName("email_addresses")][Description("target email addresses")] + string emailAddress, + [SKName("answer")][Description("answer, which is going to be the email content")] + string answer, + SKContext context) + { + var contract = new Email() + { + Address = emailAddress, + Content = answer, + }; + + // for demo purpose only + string emailPayload = JsonSerializer.Serialize(contract, new JsonSerializerOptions() { WriteIndented = true }); + context.Variables["email"] = emailPayload; + + return "Here's the API contract I will post to mail server: " + emailPayload; + } + + private sealed class Email + { + public string? Address { get; set; } + + public string? Content { get; set; } + } + } +} +//***************************************************** +//Executing RunExampleAsync +//Flow: FlowOrchestrator_Example_Flow +//Question: What is the tallest mountain on Earth? How tall is it divided by 2? +//Answer: The tallest mountain on Earth is Mount Everest, which is 29,031.69 feet (8,848.86 meters) above sea level. Half of its height is 14,515.845 feet (4,424.43 meters). +//Assistant: ["Please provide a valid email address."] +//User: my email is bad*email&address +//Assistant: ["I\u0027m sorry, but \u0022bad*email\u0026address\u0022 is not a valid email address. A valid email address should have the format \u0022example@example.com\u0022."] +//User: my email is sample@xyz.com +//Assistant: ["Do you want to send it to another email address?"] +//User: yes +//Assistant: ["Please provide a valid email address."] +//User: I also want to notify foo@bar.com +//Assistant: ["Do you want to send it to another email address?"] +//User: no I don't need notify any more address +//Assistant: [] +// Email Address: ["sample@xyz.com","foo@bar.com"] +// Email Payload: { +// "Address": "[\u0022sample@xyz.com\u0022,\u0022foo@bar.com\u0022]", +// "Content": "The tallest mountain on Earth is Mount Everest, which is 29,031.69 feet (8,848.86 meters) above sea level. Half of its height is 14,515.845 feet (4,424.43 meters)." +//} +//Time Taken: 00:00:24.2450785 +//***************************************************** + +//***************************************************** +//Executing RunInteractiveAsync +//Flow: FlowOrchestrator_Example_Flow +//Please type the question you'd like to ask +//User: +//What is the length of the longest river in ireland? +//Assistant: ["Please provide a valid email address."] +//User: +//foo@bar.com +//Assistant: ["Do you want to send it to another email address?"] +//User: +//no +//Assistant: [] +// Email Address: ["foo@bar.com"] +// Email Payload: { +// "Address": "[\u0022foo@bar.com\u0022]", +// "Content": "The longest river in Ireland is the River Shannon with a length of 360 km (223 miles)." +//} +//Flow completed, exiting +//Time Taken: 00:00:44.0215449 +//***************************************************** diff --git a/dotnet/samples/KernelSyntaxExamples/KernelSyntaxExamples.csproj b/dotnet/samples/KernelSyntaxExamples/KernelSyntaxExamples.csproj index 1b5eef6de7..bfcc801ec1 100644 --- a/dotnet/samples/KernelSyntaxExamples/KernelSyntaxExamples.csproj +++ b/dotnet/samples/KernelSyntaxExamples/KernelSyntaxExamples.csproj @@ -44,6 +44,7 @@ + diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/.editorconfig b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/.editorconfig new file mode 100644 index 0000000000..394eef685f --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/.editorconfig @@ -0,0 +1,6 @@ +# Suppressing errors for Test projects under dotnet folder +[*.cs] +dotnet_diagnostic.CA2007.severity = none # Do not directly await a Task +dotnet_diagnostic.VSTHRD111.severity = none # Use .ConfigureAwait(bool) is hidden by default, set to none to prevent IDE from changing on autosave +dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member +dotnet_diagnostic.IDE1006.severity = warning # Naming rule violations diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/CollectEmailPlugin.cs b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/CollectEmailPlugin.cs new file mode 100644 index 0000000000..5072e86796 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/CollectEmailPlugin.cs @@ -0,0 +1,84 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.AI; +using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Connectors.AI.OpenAI; +using Microsoft.SemanticKernel.Experimental.Orchestration; +using Microsoft.SemanticKernel.Orchestration; + +namespace SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests; + +public sealed class CollectEmailPlugin +{ + private const string Goal = "Collect email from user"; + + private const string EmailRegex = @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$"; + + private const string SystemPrompt = + $@"I am AI assistant and will only answer questions related to collect email. +The email should conform the regex: {EmailRegex} + +If I cannot answer, say that I don't know. +Do not expose the regex unless asked. +"; + + private readonly IChatCompletion _chat; + + private int MaxTokens { get; set; } = 256; + + private readonly AIRequestSettings _chatRequestSettings; + + public CollectEmailPlugin(IKernel kernel) + { + this._chat = kernel.GetService(); + this._chatRequestSettings = new OpenAIRequestSettings + { + MaxTokens = this.MaxTokens, + StopSequences = new List() { "Observation:" }, + Temperature = 0 + }; + } + + [SKFunction] + [Description("Useful to assist in configuration of email address, must be called after email provided")] + [SKName("ConfigureEmailAddress")] + public async Task CollectEmailAsync( + [SKName("email_address")] [Description("The email address provided by the user, pass no matter what the value is")] + string email, + SKContext context) + { + var chat = this._chat.CreateNewChat(SystemPrompt); + chat.AddUserMessage(Goal); + + ChatHistory? chatHistory = context.GetChatHistory(); + if (chatHistory?.Any() ?? false) + { + chat.Messages.AddRange(chatHistory); + } + + if (!string.IsNullOrEmpty(email) && IsValidEmail(email)) + { + context.Variables["email_address"] = email; + + return "Thanks for providing the info, the following email would be used in subsequent steps: " + email; + } + + // invalid email, prompt user to provide a valid email + context.Variables["email_address"] = string.Empty; + context.PromptInput(); + return await this._chat.GenerateMessageAsync(chat, this._chatRequestSettings).ConfigureAwait(false); + } + + private static bool IsValidEmail(string email) + { + // check using regex + var regex = new Regex(EmailRegex); + return regex.IsMatch(email); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/Experimental.Orchestration.Flow.IntegrationTests.csproj b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/Experimental.Orchestration.Flow.IntegrationTests.csproj new file mode 100644 index 0000000000..ca24e339f5 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/Experimental.Orchestration.Flow.IntegrationTests.csproj @@ -0,0 +1,49 @@ +īģŋ + + SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests + SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests + net6.0 + LatestMajor + true + false + CA2007,VSTHRD111 + b7762d10-e29b-4bb1-8b74-b6d69a667dd4 + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + + Always + + + Always + + + \ No newline at end of file diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/FlowOrchestratorTests.cs b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/FlowOrchestratorTests.cs new file mode 100644 index 0000000000..f2532a5cb1 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/FlowOrchestratorTests.cs @@ -0,0 +1,146 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Experimental.Orchestration; +using Microsoft.SemanticKernel.Plugins.Memory; +using Microsoft.SemanticKernel.Plugins.Web; +using Microsoft.SemanticKernel.Plugins.Web.Bing; +using SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests.TestSettings; +using xRetry; +using Xunit; +using Xunit.Abstractions; + +namespace SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests; + +public sealed class FlowOrchestratorTests : IDisposable +{ + private readonly string _bingApiKey; + + public FlowOrchestratorTests(ITestOutputHelper output) + { + this._logger = new XunitLogger(output); + this._testOutputHelper = new RedirectOutput(output); + + // Load configuration + this._configuration = new ConfigurationBuilder() + .AddJsonFile(path: "testsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile(path: "testsettings.development.json", optional: true, reloadOnChange: true) + .AddEnvironmentVariables() + .AddUserSecrets() + .Build(); + + string? bingApiKeyCandidate = this._configuration["Bing:ApiKey"]; + Assert.NotNull(bingApiKeyCandidate); + this._bingApiKey = bingApiKeyCandidate; + } + + [RetryFact(maxRetries: 3)] + public async Task CanExecuteFlowAsync() + { + // Arrange + KernelBuilder builder = this.InitializeKernelBuilder(); + var bingConnector = new BingConnector(this._bingApiKey); + var webSearchEnginePlugin = new WebSearchEnginePlugin(bingConnector); + var sessionId = Guid.NewGuid().ToString(); + string dummyAddress = "abc@xyz.com"; + + Dictionary plugins = new() + { + { webSearchEnginePlugin, "WebSearch" } + }; + + Microsoft.SemanticKernel.Experimental.Orchestration.Flow flow = FlowSerializer.DeserializeFromYaml(@" +goal: answer question and sent email +steps: + - goal: What is the tallest mountain on Earth? How tall is it divided by 2? + plugins: + - WebSearchEnginePlugin + provides: + - answer + - goal: Collect email address + plugins: + - CollectEmailPlugin + provides: + - email_address + - goal: Send email + plugins: + - SendEmailPlugin + requires: + - email_address + - answer + provides: + - email +"); + + var flowOrchestrator = new FlowOrchestrator( + builder, + await FlowStatusProvider.ConnectAsync(new VolatileMemoryStore()), + plugins, + config: new FlowOrchestratorConfig() { MaxStepIterations = 20 }); + + // Act + var result = await flowOrchestrator.ExecuteFlowAsync(flow, sessionId, "What is the tallest mountain on Earth? How tall is it divided by 2?"); + + // Assert + // Loose assertion -- make sure that the plan was executed and pause when it needs interact with user to get more input + Assert.Contains("email", result.ToString(), StringComparison.InvariantCultureIgnoreCase); + + // Act + result = await flowOrchestrator.ExecuteFlowAsync(flow, sessionId, $"my email is {dummyAddress}"); + + // Assert + var emailPayload = result["email"]; + Assert.Contains(dummyAddress, emailPayload, StringComparison.InvariantCultureIgnoreCase); + Assert.Contains("Everest", emailPayload, StringComparison.InvariantCultureIgnoreCase); + } + + private KernelBuilder InitializeKernelBuilder() + { + AzureOpenAIConfiguration? azureOpenAIConfiguration = this._configuration.GetSection("AzureOpenAI").Get(); + Assert.NotNull(azureOpenAIConfiguration); + + var builder = new KernelBuilder() + .WithLoggerFactory(this._logger) + .WithRetryBasic() + .WithAzureChatCompletionService( + deploymentName: azureOpenAIConfiguration.ChatDeploymentName!, + endpoint: azureOpenAIConfiguration.Endpoint, + apiKey: azureOpenAIConfiguration.ApiKey, + alsoAsTextCompletion: true); + + return builder; + } + + private readonly ILoggerFactory _logger; + private readonly RedirectOutput _testOutputHelper; + private readonly IConfigurationRoot _configuration; + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + ~FlowOrchestratorTests() + { + this.Dispose(false); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + if (this._logger is IDisposable ld) + { + ld.Dispose(); + } + + this._testOutputHelper.Dispose(); + } + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/README.md b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/README.md new file mode 100644 index 0000000000..fec79f00d9 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/README.md @@ -0,0 +1,115 @@ +īģŋ# Experimental Flow Orchestrator Integration Tests + +## Requirements + +1. **Azure OpenAI**: go to the [Azure OpenAI Quickstart](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart) + and deploy an instance of Azure OpenAI, deploy a model like "text-davinci-003" find your Endpoint and API key. +2. **OpenAI**: go to [OpenAI](https://openai.com/product/) to register and procure your API key. +3. **Azure Bing Web Search API**: go to [Bing Web Search API](https://www.microsoft.com/en-us/bing/apis/bing-web-search-api) + and select `Try Now` to get started. + +## Setup + +### Option 1: Use Secret Manager + +Integration tests will require secrets and credentials, to access OpenAI, Azure OpenAI, +Bing and other resources. + +We suggest using .NET [Secret Manager](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets) +to avoid the risk of leaking secrets into the repository, branches and pull requests. +You can also use environment variables if you prefer. + +To set your secrets with Secret Manager: + +``` +cd dotnet/src/IntegrationTests + +dotnet user-secrets init +dotnet user-secrets set "OpenAI:ServiceId" "text-davinci-003" +dotnet user-secrets set "OpenAI:ModelId" "text-davinci-003" +dotnet user-secrets set "OpenAI:ChatModelId" "gpt-4" +dotnet user-secrets set "OpenAI:ApiKey" "..." + +dotnet user-secrets set "AzureOpenAI:ServiceId" "azure-text-davinci-003" +dotnet user-secrets set "AzureOpenAI:DeploymentName" "text-davinci-003" +dotnet user-secrets set "AzureOpenAI:ChatDeploymentName" "gpt-4" +dotnet user-secrets set "AzureOpenAI:Endpoint" "https://contoso.openai.azure.com/" +dotnet user-secrets set "AzureOpenAI:ApiKey" "..." + +dotnet user-secrets set "AzureOpenAIEmbeddings:ServiceId" "azure-text-embedding-ada-002" +dotnet user-secrets set "AzureOpenAIEmbeddings:DeploymentName" "text-embedding-ada-002" +dotnet user-secrets set "AzureOpenAIEmbeddings:Endpoint" "https://contoso.openai.azure.com/" +dotnet user-secrets set "AzureOpenAIEmbeddings:ApiKey" "..." + +dotnet user-secrets set "Bing:ApiKey" "..." +``` + +### Option 2: Use Configuration File +1. Create a `testsettings.development.json` file next to `testsettings.json`. This file will be ignored by git, + the content will not end up in pull requests, so it's safe for personal settings. Keep the file safe. +2. Edit `testsettings.development.json` and + 1. set you Azure OpenAI and OpenAI keys and settings found in Azure portal and OpenAI website. + 2. set the `Bing:ApiKey` using the API key you can find in the Azure portal. + +For example: + +```json +{ + "OpenAI": { + "ServiceId": "text-davinci-003", + "ModelId": "text-davinci-003", + "ChatModelId": "gpt-4", + "ApiKey": "sk-...." + }, + "AzureOpenAI": { + "ServiceId": "azure-text-davinci-003", + "DeploymentName": "text-davinci-003", + "ChatDeploymentName": "gpt-4", + "Endpoint": "https://contoso.openai.azure.com/", + "ApiKey": "...." + }, + "OpenAIEmbeddings": { + "ServiceId": "text-embedding-ada-002", + "ModelId": "text-embedding-ada-002", + "ApiKey": "sk-...." + }, + "AzureOpenAIEmbeddings": { + "ServiceId": "azure-text-embedding-ada-002", + "DeploymentName": "text-embedding-ada-002", + "Endpoint": "https://contoso.openai.azure.com/", + "ApiKey": "...." + }, + "Bing": { + "ApiKey": "...." + } +} +``` + +### Option 3: Use Environment Variables +You may also set the test settings in your environment variables. The environment variables will override the settings in the `testsettings.development.json` file. + +When setting environment variables, use a double underscore (i.e. "\_\_") to delineate between parent and child properties. For example: + +- bash: + + ```bash + export OpenAI__ApiKey="sk-...." + export AzureOpenAI__ApiKey="...." + export AzureOpenAI__DeploymentName="azure-text-davinci-003" + export AzureOpenAI__ChatDeploymentName="gpt-4" + export AzureOpenAIEmbeddings__DeploymentName="azure-text-embedding-ada-002" + export AzureOpenAI__Endpoint="https://contoso.openai.azure.com/" + export Bing__ApiKey="...." + ``` + +- PowerShell: + + ```ps + $env:OpenAI__ApiKey = "sk-...." + $env:AzureOpenAI__ApiKey = "...." + $env:AzureOpenAI__DeploymentName = "azure-text-davinci-003" + $env:AzureOpenAI__ChatDeploymentName = "gpt-4" + $env:AzureOpenAIEmbeddings__DeploymentName = "azure-text-embedding-ada-002" + $env:AzureOpenAI__Endpoint = "https://contoso.openai.azure.com/" + $env:Bing__ApiKey = "...." + ``` diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/RedirectOutput.cs b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/RedirectOutput.cs new file mode 100644 index 0000000000..9f56e701bd --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/RedirectOutput.cs @@ -0,0 +1,55 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.IO; +using System.Text; +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests; + +public sealed class RedirectOutput : TextWriter, ILogger, ILoggerFactory +{ + private readonly ITestOutputHelper _output; + private readonly StringBuilder _logs; + + public RedirectOutput(ITestOutputHelper output) + { + this._output = output; + this._logs = new StringBuilder(); + } + + public override Encoding Encoding { get; } = Encoding.UTF8; + + public override void WriteLine(string? value) + { + this._output.WriteLine(value); + this._logs.AppendLine(value); + } + + IDisposable ILogger.BeginScope(TState state) + { + return null!; + } + + bool ILogger.IsEnabled(LogLevel logLevel) + { + return true; + } + + public string GetLogs() + { + return this._logs.ToString(); + } + + void ILogger.Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + { + var message = formatter(state, exception); + this._output?.WriteLine(message); + this._logs.AppendLine(message); + } + + ILogger ILoggerFactory.CreateLogger(string categoryName) => this; + + void ILoggerFactory.AddProvider(ILoggerProvider provider) => throw new NotSupportedException(); +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/SendEmailPlugin.cs b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/SendEmailPlugin.cs new file mode 100644 index 0000000000..b4b4aca6ed --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/SendEmailPlugin.cs @@ -0,0 +1,39 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.ComponentModel; +using System.Text.Json; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Orchestration; + +namespace SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests; + +public sealed class SendEmailPlugin +{ + [SKFunction] + [Description("Send email")] + [SKName("SendEmail")] + public string SendEmail( + [SKName("email_address")] string emailAddress, + [SKName("answer")] string answer, + SKContext context) + { + var contract = new Email() + { + Address = emailAddress, + Content = answer, + }; + + // for demo purpose only + string emailPayload = JsonSerializer.Serialize(contract, new JsonSerializerOptions() { WriteIndented = true }); + context.Variables["email"] = emailPayload; + + return "Here's the API contract I will post to mail server: " + emailPayload; + } + + private sealed class Email + { + public string? Address { get; set; } + + public string? Content { get; set; } + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/TestSettings/AzureOpenAIConfiguration.cs b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/TestSettings/AzureOpenAIConfiguration.cs new file mode 100644 index 0000000000..f67d8bd814 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/TestSettings/AzureOpenAIConfiguration.cs @@ -0,0 +1,29 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Diagnostics.CodeAnalysis; + +namespace SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests.TestSettings; + +[SuppressMessage("Performance", "CA1812:Internal class that is apparently never instantiated", + Justification = "Configuration classes are instantiated through IConfiguration.")] +internal sealed class AzureOpenAIConfiguration +{ + public string ServiceId { get; set; } + + public string DeploymentName { get; set; } + + public string? ChatDeploymentName { get; set; } + + public string Endpoint { get; set; } + + public string ApiKey { get; set; } + + public AzureOpenAIConfiguration(string serviceId, string deploymentName, string endpoint, string apiKey, string? chatDeploymentName = null) + { + this.ServiceId = serviceId; + this.DeploymentName = deploymentName; + this.ChatDeploymentName = chatDeploymentName; + this.Endpoint = endpoint; + this.ApiKey = apiKey; + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/TestSettings/OpenAIConfiguration.cs b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/TestSettings/OpenAIConfiguration.cs new file mode 100644 index 0000000000..a861d1a4ce --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/TestSettings/OpenAIConfiguration.cs @@ -0,0 +1,23 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Diagnostics.CodeAnalysis; + +namespace SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests.TestSettings; + +[SuppressMessage("Performance", "CA1812:Internal class that is apparently never instantiated", + Justification = "Configuration classes are instantiated through IConfiguration.")] +internal sealed class OpenAIConfiguration +{ + public string ServiceId { get; set; } + public string ModelId { get; set; } + public string? ChatModelId { get; set; } + public string ApiKey { get; set; } + + public OpenAIConfiguration(string serviceId, string modelId, string apiKey, string? chatModelId = null) + { + this.ServiceId = serviceId; + this.ModelId = modelId; + this.ChatModelId = chatModelId; + this.ApiKey = apiKey; + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/XunitLogger.cs b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/XunitLogger.cs new file mode 100644 index 0000000000..279ed17a73 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/XunitLogger.cs @@ -0,0 +1,43 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace SemanticKernel.Experimental.Orchestration.Flow.IntegrationTests; + +/// +/// A logger that writes to the Xunit test output +/// +internal sealed class XunitLogger : ILoggerFactory, ILogger, IDisposable +{ + private readonly ITestOutputHelper _output; + + public XunitLogger(ITestOutputHelper output) + { + this._output = output; + } + + /// + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + { + this._output.WriteLine(state?.ToString()); + } + + /// + public bool IsEnabled(LogLevel logLevel) => true; + + /// + IDisposable ILogger.BeginScope(TState state) => this; + + /// + public void Dispose() + { + // This class is marked as disposable to support the BeginScope method. + // However, there is no need to dispose anything. + } + + public ILogger CreateLogger(string categoryName) => this; + + public void AddProvider(ILoggerProvider provider) => throw new NotSupportedException(); +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/testsettings.json b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/testsettings.json new file mode 100644 index 0000000000..2b5e41c5cb --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/testsettings.json @@ -0,0 +1,34 @@ +īģŋ{ + "OpenAI": { + "ServiceId": "text-davinci-003", + "ModelId": "text-davinci-003", + "ApiKey": "" + }, + "AzureOpenAI": { + "ServiceId": "azure-text-davinci-003", + "DeploymentName": "text-davinci-003", + "ChatDeploymentName": "gpt-4", + "Endpoint": "", + "ApiKey": "" + }, + "OpenAIEmbeddings": { + "ServiceId": "text-embedding-ada-002", + "ModelId": "text-embedding-ada-002", + "ApiKey": "" + }, + "AzureOpenAIEmbeddings": { + "ServiceId": "azure-text-embedding-ada-002", + "DeploymentName": "text-embedding-ada-002", + "Endpoint": "", + "ApiKey": "" + }, + "HuggingFace": { + "ApiKey": "" + }, + "Bing": { + "ApiKey": "" + }, + "Postgres": { + "ConnectionString": "" + } +} \ No newline at end of file diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/.editorconfig b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/.editorconfig new file mode 100644 index 0000000000..394eef685f --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/.editorconfig @@ -0,0 +1,6 @@ +# Suppressing errors for Test projects under dotnet folder +[*.cs] +dotnet_diagnostic.CA2007.severity = none # Do not directly await a Task +dotnet_diagnostic.VSTHRD111.severity = none # Use .ConfigureAwait(bool) is hidden by default, set to none to prevent IDE from changing on autosave +dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member +dotnet_diagnostic.IDE1006.severity = warning # Naming rule violations diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/ChatHistorySerializerTest.cs b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/ChatHistorySerializerTest.cs new file mode 100644 index 0000000000..f44910a1e0 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/ChatHistorySerializerTest.cs @@ -0,0 +1,48 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Experimental.Orchestration.Execution; +using Xunit; + +namespace SemanticKernel.Experimental.Orchestration.Flow.UnitTests; + +public class ChatHistorySerializerTest +{ + [Fact] + public void CanDeserializeChatHistory() + { + string input = "[{\"Role\":\"assistant\",\"Content\":\"To configure the email notification, please provide the following information:\\n\\n1. Email address: (Enter the valid email address)\\n2. Notification time: (Enter the schedule of notification)\\n3. Email Content: (Enter the content expected from email notification)\\n\\nOnce you have provided this information, please type \\u0022confirmed\\u0022 to confirm the details.\"}]\r\n"; + var history = ChatHistorySerializer.Deserialize(input); + + Assert.NotNull(history); + Assert.Single(history); + Assert.Equal(AuthorRole.Assistant.Label, history[0].Role.Label); + } + + [Fact] + public void CanSerializeChatHistory() + { + var history = new ChatHistory(); + var systemMessage = "system"; + var userMessage = "user"; + var assistantMessage = "assistant"; + + history.AddSystemMessage(systemMessage); + history.AddUserMessage(userMessage); + history.AddAssistantMessage(assistantMessage); + + var serialized = ChatHistorySerializer.Serialize(history); + var deserialized = ChatHistorySerializer.Deserialize(serialized); + + Assert.NotNull(deserialized); + + Assert.Equal(deserialized[0].Role, AuthorRole.System); + Assert.Equal(deserialized[0].Content, systemMessage); + + Assert.Equal(deserialized[1].Role, AuthorRole.User); + Assert.Equal(deserialized[1].Content, userMessage); + + Assert.Equal(deserialized[2].Role, AuthorRole.Assistant); + Assert.Equal(deserialized[2].Content, assistantMessage); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/Experimental.Orchestration.Flow.UnitTests.csproj b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/Experimental.Orchestration.Flow.UnitTests.csproj new file mode 100644 index 0000000000..0cd6cd2fda --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/Experimental.Orchestration.Flow.UnitTests.csproj @@ -0,0 +1,38 @@ +īģŋ + + SemanticKernel.Experimental.Orchestration.Flow.UnitTests + SemanticKernel.Experimental.Orchestration.Flow.UnitTests + net6.0 + LatestMajor + true + enable + disable + false + CA2007,VSTHRD111 + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + Always + + + Always + + + \ No newline at end of file diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowExtensionsTests.cs b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowExtensionsTests.cs new file mode 100644 index 0000000000..85f4bd62ac --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowExtensionsTests.cs @@ -0,0 +1,125 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SemanticKernel.Experimental.Orchestration; +using Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; +using Xunit; + +namespace SemanticKernel.Experimental.Orchestration.Flow.UnitTests; + +public class FlowExtensionsTests +{ + [Fact] + public async Task TestBuildReferenceStepAsync() + { + // Arrange + var flow1 = CreateFlowWithReferenceStep("flow2"); + + var flow2 = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("flow2", "test flow goal 2"); + flow2.CompletionType = CompletionType.Optional; + var step5 = new FlowStep("step1"); + step5.AddRequires("a"); + step5.AddProvides("b"); + flow2.AddProvides("b"); + flow2.AddStep(step5); + + // Act + var catalog = new InMemoryFlowCatalog(new List { flow1, flow2 }); + var flow1InCatalog = await catalog.GetFlowAsync("flow1"); + Assert.NotNull(flow1InCatalog); + + // Assert + Assert.DoesNotContain(flow1InCatalog.Steps, step => step is ReferenceFlowStep); + var flow2Step = flow1InCatalog.Steps.OfType().SingleOrDefault(); + Assert.NotNull(flow2Step); + Assert.Equal("flow2", flow2Step.Name); + Assert.Equal(CompletionType.Optional, flow2Step.CompletionType); + Assert.Equal("a", flow2Step.Requires.SingleOrDefault()); + Assert.Equal("b", flow2Step.Provides.SingleOrDefault()); + } + + [Fact] + public void TestBuildNonExistReferenceStep() + { + // Arrange + var flow1 = CreateFlowWithReferenceStep("flow2"); + + var flow2 = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("flow3", "test flow goal 2"); + var step5 = new FlowStep("step1"); + step5.AddProvides("a"); + flow2.AddProvides("a"); + flow2.AddStep(step5); + + // Act and assert + Assert.Throws(() => new InMemoryFlowCatalog(new List { flow1, flow2 })); + } + + private static Microsoft.SemanticKernel.Experimental.Orchestration.Flow CreateFlowWithReferenceStep(string referenceFlowName) + { + var flow = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("flow1", "test flow goal"); + var step1 = new FlowStep("step1"); + step1.AddProvides("a"); + var step2 = new FlowStep("step2"); + step2.AddRequires("a"); + step2.AddProvides("b"); + var step3 = new FlowStep("step3"); + step3.AddRequires("a", "b"); + step3.AddProvides("c"); + var step4 = new ReferenceFlowStep(referenceFlowName) + { + CompletionType = CompletionType.Optional + }; + flow.AddStep(step1); + flow.AddStep(step2); + flow.AddStep(step3); + flow.AddStep(step4); + + return flow; + } + + private sealed class InMemoryFlowCatalog : IFlowCatalog + { + private readonly Dictionary _flows = new(); + + internal InMemoryFlowCatalog() + { + } + + internal InMemoryFlowCatalog(IReadOnlyList flows) + { + // phase 1: register original flows + foreach (var flow in flows) + { + this._flows.Add(flow.Name, flow); + } + + // phase 2: build references + foreach (var flow in flows) + { +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits + flow.BuildReferenceAsync(this).Wait(); +#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + } + } + + public Task> GetFlowsAsync() + { + return Task.FromResult(this._flows.Select(_ => _.Value)); + } + + public Task GetFlowAsync(string flowName) + { + return Task.FromResult(this._flows.TryGetValue(flowName, out var flow) ? flow : null); + } + + public Task RegisterFlowAsync(Microsoft.SemanticKernel.Experimental.Orchestration.Flow flow) + { + this._flows.Add(flow.Name, flow); + + return Task.FromResult(true); + } + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowSerializerTests.cs b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowSerializerTests.cs new file mode 100644 index 0000000000..40960f48dd --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowSerializerTests.cs @@ -0,0 +1,64 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.IO; +using System.Linq; +using Microsoft.SemanticKernel.Experimental.Orchestration; +using Xunit; + +namespace SemanticKernel.Experimental.Orchestration.Flow.UnitTests; + +public class FlowSerializerTests +{ + [Fact] + public void CanDeserializeFromYaml() + { + // Arrange + var yamlFile = "./TestData/Flow/flow.yml"; + var content = File.ReadAllText(yamlFile); + + // Act + var flow = FlowSerializer.DeserializeFromYaml(content); + + // Assert + this.ValidateFlow(flow); + } + + [Fact] + public void CanDeserializeFromJson() + { + // Arrange + var jsonFile = "./TestData/Flow/flow.json"; + var content = File.ReadAllText(jsonFile); + + // Act + var flow = FlowSerializer.DeserializeFromJson(content); + + // Assert + this.ValidateFlow(flow); + } + + private void ValidateFlow(Microsoft.SemanticKernel.Experimental.Orchestration.Flow? flow) + { + Assert.NotNull(flow); + Assert.NotEmpty(flow.Steps); + Assert.False(string.IsNullOrEmpty(flow.Goal)); + Assert.Contains("breakfast", flow.Provides); + Assert.Equal(5, flow.Steps.Count); + + var makeCoffeeStep = flow.Steps.First(step => step.Goal == "Make coffee"); + Assert.Equal("coffee_bean", makeCoffeeStep.Requires.Single()); + Assert.Equal("coffee", makeCoffeeStep.Provides.Single()); + Assert.NotNull(makeCoffeeStep.Plugins); + Assert.Single(makeCoffeeStep.Plugins); + Assert.Equal(CompletionType.Once, makeCoffeeStep.CompletionType); + + var recipeStep = flow.Steps.First(step => step.Goal == "Recipe"); + Assert.Equal("ingredients", recipeStep.Provides.Single()); + Assert.Equal(CompletionType.AtLeastOnce, recipeStep.CompletionType); + + var lunchStep = flow.Steps.First(step => step is ReferenceFlowStep) as ReferenceFlowStep; + Assert.NotNull(lunchStep); + Assert.Equal(CompletionType.Optional, lunchStep.CompletionType); + Assert.Equal("lunch_flow", lunchStep.FlowName); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowValidatorTests.cs b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowValidatorTests.cs new file mode 100644 index 0000000000..86acb272be --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/FlowValidatorTests.cs @@ -0,0 +1,113 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using Microsoft.SemanticKernel.Experimental.Orchestration; +using Xunit; + +namespace SemanticKernel.Experimental.Orchestration.Flow.UnitTests; + +public class FlowValidatorTests +{ + [Fact] + public void TestValidateFlowReturnsTrueForValidFlow() + { + // Arrange + var validator = new FlowValidator(); + var flow = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("test_flow", "test flow goal"); + var step1 = new FlowStep("step1"); + step1.AddProvides("a"); + var step2 = new FlowStep("step2"); + step2.AddRequires("a"); + step2.AddProvides("b"); + var step3 = new FlowStep("step3"); + step3.AddRequires("a", "b"); + step3.AddProvides("c"); + var step4 = new ReferenceFlowStep("another flow") + { + CompletionType = CompletionType.Optional, + StartingMessage = "Would you like to start another flow?" + }; + flow.AddStep(step1); + flow.AddStep(step2); + flow.AddStep(step3); + flow.AddStep(step4); + + // Act and assert + validator.Validate(flow); + } + + [Fact] + public void TestValidateFlowThrowForEmptyFlow() + { + // Arrange + var validator = new FlowValidator(); + var flow = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("empty flow", "empty flow"); + + // Act and assert + Assert.Throws(() => validator.Validate(flow)); + } + + [Fact] + public void TestValidateFlowThrowForFlowWithDependencyLoops() + { + // Arrange + var validator = new FlowValidator(); + var flow = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("test_flow", "test flow goal"); + var step1 = new FlowStep("step1"); + step1.AddRequires("a"); + step1.AddProvides("b"); + var step2 = new FlowStep("step2"); + step2.AddRequires("b"); + step2.AddProvides("a"); + flow.AddStep(step1); + flow.AddStep(step2); + + // Act and assert + Assert.Throws(() => validator.Validate(flow)); + } + + [Fact] + public void TestValidateFlowThrowForReferenceStepWithRequires() + { + // Arrange + var validator = new FlowValidator(); + var flow = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("test_flow", "test flow goal"); + var step1 = new ReferenceFlowStep("another flow"); + step1.AddRequires("a"); + + // Act and assert + Assert.Throws(() => validator.Validate(flow)); + } + + [Fact] + public void TestValidateFlowThrowForReferenceStepWithProvides() + { + // Arrange + var validator = new FlowValidator(); + var flow = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("test_flow", "test flow goal"); + var step1 = new ReferenceFlowStep("another flow"); + step1.AddProvides("a"); + + // Act and assert + Assert.Throws(() => validator.Validate(flow)); + } + + [Fact] + public void TestValidateFlowThrowForOptionalStepWithoutStartingMessage() + { + // Arrange + var validator = new FlowValidator(); + var flow = new Microsoft.SemanticKernel.Experimental.Orchestration.Flow("test_flow", "test flow goal"); + var step1 = new FlowStep("step1"); + step1.AddProvides("a"); + var step2 = new ReferenceFlowStep("another flow") + { + CompletionType = CompletionType.Optional + }; + flow.AddStep(step1); + flow.AddStep(step2); + + // Act and assert + Assert.Throws(() => validator.Validate(flow)); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/TestData/Flow/flow.json b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/TestData/Flow/flow.json new file mode 100644 index 0000000000..2dc16bb8e4 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/TestData/Flow/flow.json @@ -0,0 +1,39 @@ +{ + "name": "breakfast_flow", + "goal": "Make breakfast", + "steps": [ + { + "goal": "Make coffee", + "plugins": ["MakeCoffeePlugin"], + "requires": ["coffee_bean"], + "provides": ["coffee"] + }, + { + "goal": "Select coffee been", + "plugins": ["CoffeeRecommendationPlugin"], + "provides": ["coffee_bean"] + }, + { + "goal": "Recipe", + "plugins": [ + "WebSearchPlugin", + "CalorieCalculatorPlugin", + "HealthCheckPlugin" + ], + "provides": ["ingredients"], + "completionType": "AtLeastOnce" + }, + { + "goal": "Cook", + "plugins": ["CookPlugin", "WebSearchPlugin"], + "requires": ["coffee", "ingredients"], + "provides": ["breakfast"] + }, + { + "flowName": "lunch_flow", + "completionType": "Optional", + "startingMessage": "Would you like to prepare the lunch as well?" + } + ], + "provides": ["breakfast"] +} diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/TestData/Flow/flow.yml b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/TestData/Flow/flow.yml new file mode 100644 index 0000000000..f5f2ad539b --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/TestData/Flow/flow.yml @@ -0,0 +1,44 @@ +name: breakfast_flow +goal: Make breakfast +steps: + - goal: Make coffee + plugins: + - MakeCoffeePlugin + requires: + - coffee_bean + provides: + - coffee + + - goal: Select coffee been + plugins: + - CoffeeRecommendationPlugin + provides: + - coffee_bean + completionType: AtLeastOnce + + - goal: Recipe + plugins: + - WebSearchPlugin + - CalorieCalculatorPlugin + - HealthCheckPlugin + provides: + - ingredients + completionType: AtLeastOnce + transitionMessage: Do you want to add one more recipe? + + - goal: Cook + plugins: + - CookPlugin + - WebSearchPlugin + requires: + - coffee + - ingredients + provides: + - breakfast + + - flowName: lunch_flow + completionType: Optional + startingMessage: Would you like to prepare the lunch as well? + +provides: + - breakfast diff --git a/dotnet/src/Experimental/Orchestration.Flow.UnitTests/XunitHelpers/TestConsoleLogger.cs b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/XunitHelpers/TestConsoleLogger.cs new file mode 100644 index 0000000000..476f5b921b --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow.UnitTests/XunitHelpers/TestConsoleLogger.cs @@ -0,0 +1,31 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using Microsoft.Extensions.Logging; + +namespace SemanticKernel.Experimental.Orchestration.Flow.UnitTests.XunitHelpers; + +/// +/// Basic logger printing to console +/// +internal static class TestConsoleLogger +{ + internal static ILogger Log => LoggerFactory.CreateLogger(); + + internal static ILoggerFactory LoggerFactory => s_loggerFactory.Value; + private static readonly Lazy s_loggerFactory = new(LogBuilder); + + private static ILoggerFactory LogBuilder() + { + return Microsoft.Extensions.Logging.LoggerFactory.Create(builder => + { + builder.SetMinimumLevel(LogLevel.Trace); + // builder.AddFilter("Microsoft", LogLevel.Trace); + // builder.AddFilter("Microsoft", LogLevel.Debug); + // builder.AddFilter("Microsoft", LogLevel.Information); + // builder.AddFilter("Microsoft", LogLevel.Warning); + // builder.AddFilter("Microsoft", LogLevel.Error); + builder.AddConsole(); + }); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowCatalog.cs b/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowCatalog.cs new file mode 100644 index 0000000000..4765c1dbab --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowCatalog.cs @@ -0,0 +1,32 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; + +/// +/// Interface for flow catalog, which provides functionality of flow registration, enumeration and search. +/// +public interface IFlowCatalog +{ + /// + /// Get all instances from the repository + /// + /// flows + Task> GetFlowsAsync(); + + /// + /// Get by name + /// + /// the flow name + /// flow given the name + Task GetFlowAsync(string flowName); + + /// + /// Register flow in the catalog + /// + /// flow + /// + Task RegisterFlowAsync(Flow flow); +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowExecutor.cs b/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowExecutor.cs new file mode 100644 index 0000000000..c31090f394 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowExecutor.cs @@ -0,0 +1,22 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Threading.Tasks; +using Microsoft.SemanticKernel.Orchestration; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; + +/// +/// Flow executor interface +/// +public interface IFlowExecutor +{ + /// + /// Execute the + /// + /// Flow + /// Session id, which is used to track the execution status. + /// The input from client to continue the execution. + /// The request context variables + /// The execution context + Task ExecuteAsync(Flow flow, string sessionId, string input, ContextVariables contextVariables); +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowStatusProvider.cs b/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowStatusProvider.cs new file mode 100644 index 0000000000..1546b1fd38 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowStatusProvider.cs @@ -0,0 +1,63 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Experimental.Orchestration.Execution; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; + +/// +/// The flow status provider interface. +/// +public interface IFlowStatusProvider +{ + /// + /// Get the state of current execution session. + /// + /// The session id + /// The variables + Task GetExecutionStateAsync(string sessionId); + + /// + /// Save the state for current execution session. + /// + /// The session id + /// The execution state + /// Task + Task SaveExecutionStateAsync(string sessionId, ExecutionState state); + + /// + /// Get the chat history for current execution session. + /// + /// The session id + /// The step id + /// + Task GetChatHistoryAsync(string sessionId, string stepId); + + /// + /// Save the chat history for current execution session. + /// + /// The session id + /// The step id + /// The chat history + /// + Task SaveChatHistoryAsync(string sessionId, string stepId, ChatHistory history); + + /// + /// Get the ReAct history for current execution . + /// + /// The session id + /// The step id + /// The list of ReAct steps for current flow step. + Task> GetReActStepsAsync(string sessionId, string stepId); + + /// + /// Save the ReAct history for current execution step to . + /// + /// The session id + /// The step id + /// The executed steps + /// Task + Task SaveReActStepsAsync(string sessionId, string stepId, List steps); +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowValidator.cs b/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowValidator.cs new file mode 100644 index 0000000000..120ccd314a --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Abstractions/IFlowValidator.cs @@ -0,0 +1,15 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; + +/// +/// Flow validator interface +/// +public interface IFlowValidator +{ + /// + /// Validate if the is valid. + /// + /// + void Validate(Flow flow); +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/EmbeddedResource.cs b/dotnet/src/Experimental/Orchestration.Flow/EmbeddedResource.cs new file mode 100644 index 0000000000..f3a98717d5 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/EmbeddedResource.cs @@ -0,0 +1,32 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.IO; +using System.Reflection; +using Microsoft.SemanticKernel.Diagnostics; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration; + +internal static class EmbeddedResource +{ + private static readonly string? s_namespace = typeof(EmbeddedResource).Namespace; + + internal static string? Read(string name, bool throwIfNotFound = true) + { + var assembly = typeof(EmbeddedResource).GetTypeInfo().Assembly; + if (assembly is null) { throw new SKException($"[{s_namespace}] {name} assembly not found"); } + + using Stream? resource = assembly.GetManifestResourceStream($"{s_namespace}." + name); + if (resource is null) + { + if (!throwIfNotFound) + { + return null; + } + + throw new SKException($"[{s_namespace}] {name} resource not found"); + } + + using var reader = new StreamReader(resource); + return reader.ReadToEnd(); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Execution/ChatHistorySerializer.cs b/dotnet/src/Experimental/Orchestration.Flow/Execution/ChatHistorySerializer.cs new file mode 100644 index 0000000000..abaec49434 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Execution/ChatHistorySerializer.cs @@ -0,0 +1,51 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Linq; +using System.Text.Json; +using Microsoft.SemanticKernel.AI.ChatCompletion; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Execution; + +internal static class ChatHistorySerializer +{ + internal static ChatHistory? Deserialize(string input) + { + if (string.IsNullOrEmpty(input)) + { + return null; + } + + var messages = JsonSerializer.Deserialize(input) ?? Array.Empty(); + ChatHistory history = new(); + foreach (var message in messages) + { + history.AddMessage(new AuthorRole(message.Role!), message.Content!); + } + + return history; + } + + internal static string Serialize(ChatHistory? history) + { + if (history is null) + { + return string.Empty; + } + + var messages = history.Messages.Select(m => new SerializableChatMessage() + { + Role = m.Role.Label, + Content = m.Content, + }); + + return JsonSerializer.Serialize(messages); + } + + private class SerializableChatMessage + { + public string? Role { get; set; } + + public string? Content { get; set; } + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Execution/Constants.cs b/dotnet/src/Experimental/Orchestration.Flow/Execution/Constants.cs new file mode 100644 index 0000000000..c2c987de31 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Execution/Constants.cs @@ -0,0 +1,67 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Execution; + +internal static class Constants +{ + /// + /// The function name to indicate stop execution and prompt user + /// + public const string StopAndPromptFunctionName = "StopAndPrompt"; + + /// + /// The parameter name of StopAndPrompt function + /// + public const string StopAndPromptParameterName = "prompt"; + + internal static class ActionVariableNames + { + /// + /// Variable name for the chat history + /// + public const string ChatHistory = "_chatHistory"; + + /// + /// Variable name for the chat input + /// + public const string ChatInput = "_chatInput"; + + /// + /// All reserved variable names + /// + public static readonly string[] All = new[] { ChatHistory, ChatInput }; + } + + internal static class ChatPluginVariables + { + /// + /// Variable name to prompt input + /// + public const string PromptInputName = "PromptInput"; + + /// + /// Variable name to exit out the of AtLeastOnce or ZeroOrMore loop + /// + public const string ExitLoopName = "ExitLoop"; + + /// + /// Variable name to force the next iteration of the of AtLeastOnce or ZeroOrMore loop + /// + public const string ContinueLoopName = "ContinueLoop"; + + /// + /// Variable name to terminate the flow + /// + public const string StopFlowName = "StopFlow"; + + /// + /// Default variable value + /// + public const string DefaultValue = "True"; + + /// + /// The variables that change the default flow + /// + public static readonly string[] ControlVariables = new[] { PromptInputName, ExitLoopName, ContinueLoopName, StopFlowName }; + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Execution/ExecutionState.cs b/dotnet/src/Experimental/Orchestration.Flow/Execution/ExecutionState.cs new file mode 100644 index 0000000000..a9199aaa29 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Execution/ExecutionState.cs @@ -0,0 +1,87 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Execution; + +/// +/// Execution state +/// +public sealed class ExecutionState +{ + /// + /// Index of current step + /// + public int CurrentStepIndex { get; set; } = 0; + + /// + /// Execution state described by variables. + /// + public Dictionary Variables { get; set; } = new Dictionary(); + + /// + /// Execution state of each step + /// + public Dictionary StepStates { get; set; } = new Dictionary(); + + /// + /// Step execution state + /// + public class StepExecutionState + { + /// + /// The status of step execution + /// + public Status Status { get; set; } = Status.NotStarted; + + /// + /// The execution count of step. The value could be larger than one if the step allows repeatable execution. + /// + public int ExecutionCount { get; set; } + + /// + /// The output variables provided by the step + /// + public Dictionary> Output { get; set; } = new Dictionary>(); + + /// + /// Add or update variable for the step + /// + /// The execution index + /// The key of variable. + /// The value of variable. + public void AddOrUpdateVariable(int executionIndex, string key, string value) + { + var output = this.Output.GetOrAdd(key, new List()); + if (output!.Count <= executionIndex) + { + output.Add(value); + } + else + { + output[executionIndex] = value; + } + } + } + + /// + /// The execution status enum + /// + public enum Status + { + /// + /// Not started + /// + NotStarted, + + /// + /// In progress + /// + InProgress, + + /// + /// Completed + /// + Completed + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Execution/FlowExecutor.cs b/dotnet/src/Experimental/Orchestration.Flow/Execution/FlowExecutor.cs new file mode 100644 index 0000000000..2fa29c2277 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Execution/FlowExecutor.cs @@ -0,0 +1,705 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; +using Microsoft.SemanticKernel.Orchestration; +using Microsoft.SemanticKernel.TemplateEngine; +using Microsoft.SemanticKernel.TemplateEngine.Basic; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Execution; + +/// +/// This is a flow executor which iterates over the flow steps and executes them one by one. +/// +/// +/// For each step, it is executed in the ReAct (Reasoning-Act-Observe) style, which is similar as StepwisePlanner, with the following differences: +/// 1. It is implemented in a way so that the chat could be streamed for more effective reasoning, action and feedback loop. +/// 2. The user input would be part of observation for the engine to reason and determine next action. +/// 3. For each step, it is considered as complete by verifying all the outputs are provided in programmatic way, instead of LLM evaluation. +/// +/// Further consolidation can happen in the future so that flow executor becomes a generalization of StepwisePlanner. +/// And both chatMode and completionMode could be supported. +/// +internal class FlowExecutor : IFlowExecutor +{ + /// + /// The kernel builder + /// + private readonly KernelBuilder _kernelBuilder; + + /// + /// The logger + /// + private readonly ILogger _logger; + + /// + /// The global plugin collection + /// + private readonly Dictionary _globalPluginCollection; + + /// + /// The flow planner config + /// + private readonly FlowOrchestratorConfig _config; + + /// + /// The flow status provider + /// + private readonly IFlowStatusProvider _flowStatusProvider; + + /// + /// System kernel for flow execution + /// + private readonly IKernel _systemKernel; + + /// + /// Re-Act engine for flow execution + /// + private readonly ReActEngine _reActEngine; + + /// + /// Restricted plugin name + /// + private const string RestrictedPluginName = "FlowExecutor_Excluded"; + + /// + /// The regex for parsing the final answer response + /// + private static readonly Regex s_finalAnswerRegex = + new(@"\[FINAL.+\](?.+)", RegexOptions.Singleline); + + /// + /// The regex for parsing the question + /// + private static readonly Regex s_questionRegex = + new(@"\[QUESTION\](?.+)", RegexOptions.Singleline); + + /// + /// The regex for parsing the thought response + /// + private static readonly Regex s_thoughtRegex = + new(@"\[THOUGHT\](?.+)", RegexOptions.Singleline); + + /// + /// Check repeat step function + /// + private readonly ISKFunction _checkRepeatStepFunction; + + /// + /// Check start step function + /// + private readonly ISKFunction _checkStartStepFunction; + + internal FlowExecutor(KernelBuilder kernelBuilder, IFlowStatusProvider statusProvider, Dictionary globalPluginCollection, FlowOrchestratorConfig? config = null) + { + this._kernelBuilder = kernelBuilder; + this._systemKernel = kernelBuilder.Build(); + + this._logger = this._systemKernel.LoggerFactory.CreateLogger(); + this._config = config ?? new FlowOrchestratorConfig(); + + this._flowStatusProvider = statusProvider; + this._globalPluginCollection = globalPluginCollection; + + var checkRepeatStepPrompt = EmbeddedResource.Read("Plugins.CheckRepeatStep.skprompt.txt")!; + var checkRepeatStepConfig = PromptTemplateConfig.FromJson(EmbeddedResource.Read("Plugins.CheckRepeatStep.config.json")!); + this._checkRepeatStepFunction = this.ImportSemanticFunction(this._systemKernel, "CheckRepeatStep", checkRepeatStepPrompt, checkRepeatStepConfig); + + var checkStartStepPrompt = EmbeddedResource.Read("Plugins.CheckStartStep.skprompt.txt")!; + var checkStartStepConfig = PromptTemplateConfig.FromJson(EmbeddedResource.Read("Plugins.CheckStartStep.config.json")!); + this._checkStartStepFunction = this.ImportSemanticFunction(this._systemKernel, "CheckStartStep", checkStartStepPrompt, checkStartStepConfig); + + this._config.ExcludedPlugins.Add(RestrictedPluginName); + this._reActEngine = new ReActEngine(this._systemKernel, this._logger, this._config); + } + + public async Task ExecuteAsync(Flow flow, string sessionId, string input, ContextVariables contextVariables) + { + Verify.NotNull(flow, nameof(flow)); + + this._logger?.LogInformation("Executing flow {FlowName} with sessionId={SessionId}.", flow.Name, sessionId); + var sortedSteps = flow.SortSteps(); + + var rootContext = contextVariables.Clone(); + + // populate persisted state variables + ExecutionState executionState = await this._flowStatusProvider.GetExecutionStateAsync(sessionId).ConfigureAwait(false); + List outputs = new(); + + while (executionState.CurrentStepIndex < sortedSteps.Count) + { + int stepIndex = executionState.CurrentStepIndex; + FlowStep step = sortedSteps[stepIndex]; + + foreach (var kv in executionState.Variables) + { + rootContext.Set(kv.Key, kv.Value); + } + + this.ValidateStep(step, rootContext); + + // init step execution state + string stepKey = $"{stepIndex}_{step.Goal}"; + if (!executionState.StepStates.ContainsKey(stepKey)) + { + executionState.StepStates.Add(stepKey, new ExecutionState.StepExecutionState()); + } + + ExecutionState.StepExecutionState stepState = executionState.StepStates[stepKey]; + var stepId = $"{stepKey}_{stepState.ExecutionCount}"; + + var continueLoop = false; + var completed = step.Provides.All(_ => executionState.Variables.ContainsKey(_)); + if (!completed) + { + // On the first iteration of an Optional or ZeroOrMore step, we need to check whether the user wants to start the stepstep + if (step.CompletionType is CompletionType.Optional or CompletionType.ZeroOrMore && stepState.Status == ExecutionState.Status.NotStarted) + { + RepeatOrStartStepResult? startStep = await this.CheckStartStepAsync(rootContext, step, sessionId, stepId, input).ConfigureAwait(false); + if (startStep is null) + { + // Unknown error, try again + this._logger?.LogWarning("Unexpected error when checking whether to start the step, try again"); + continue; + } + else if (startStep.Execute is null) + { + // Unconfirmed, prompt user + outputs.Add(startStep.Prompt!); + await this._flowStatusProvider.SaveExecutionStateAsync(sessionId, executionState).ConfigureAwait(false); + break; + } + else if (startStep.Execute.Value) + { + stepState.Status = ExecutionState.Status.InProgress; + await this._flowStatusProvider.SaveExecutionStateAsync(sessionId, executionState).ConfigureAwait(false); + this._logger?.LogInformation("Need to start step {StepIndex} for iteration={Iteration}, goal={StepGoal}.", stepIndex, stepState.ExecutionCount, step.Goal); + } + else + { + // User doesn't want to run the step + foreach (var variable in step.Provides) + { + executionState.Variables[variable] = "[]"; + } + + await this.CompleteStepAsync(rootContext, sessionId, executionState, step, stepState).ConfigureAwait(false); + this._logger?.LogInformation("Completed step {StepIndex} with iteration={Iteration}, goal={StepGoal}.", stepIndex, stepState.ExecutionCount, step.Goal); + continue; + } + } + + // execute step + this._logger?.LogInformation( + "Executing step {StepIndex} for iteration={Iteration}, goal={StepGoal}, input={Input}.", stepIndex, + stepState.ExecutionCount, step.Goal, input); + + IKernel stepKernel = this._kernelBuilder.Build(); + var stepContext = stepKernel.CreateNewContext(); + foreach (var key in step.Requires) + { + stepContext.Variables.Set(key, rootContext[key]); + } + + foreach (var key in step.Passthrough) + { + if (rootContext.TryGetValue(key, out var val)) + { + stepContext.Variables.Set(key, val); + } + } + + ContextVariables? stepResult; + if (step is Flow flowStep) + { + stepResult = await this.ExecuteAsync(flowStep, $"{sessionId}_{stepId}", input, stepContext.Variables).ConfigureAwait(false); + } + else + { + var stepPlugins = step.LoadPlugins(stepKernel, this._globalPluginCollection); + foreach (var plugin in stepPlugins) + { + stepKernel.ImportFunctions(plugin, plugin.GetType().Name); + } + + stepResult = await this.ExecuteStepAsync(step, sessionId, stepId, input, stepKernel, stepContext).ConfigureAwait(false); + } + + if (!string.IsNullOrEmpty(stepResult.ToString()) && (stepResult.IsPromptInput() || stepResult.IsTerminateFlow())) + { + try + { + var stepOutputs = JsonSerializer.Deserialize(stepResult.ToString()); + outputs.AddRange(stepOutputs!); + } + catch (JsonException) + { + outputs.Add(stepResult.ToString()); + } + } + else if (stepResult.TryGetValue(Constants.ChatPluginVariables.ExitLoopName, out var exitResponse)) + { + stepState.Status = ExecutionState.Status.Completed; + foreach (var variable in step.Provides) + { + if (!stepResult.ContainsKey(variable)) + { + stepResult[variable] = string.Empty; + } + } + + if (!string.IsNullOrWhiteSpace(exitResponse)) + { + outputs.Add(exitResponse); + } + + this._logger?.LogInformation("Exiting loop for step {StepIndex} with iteration={Iteration}, goal={StepGoal}.", stepIndex, stepState.ExecutionCount, step.Goal); + } + else if (stepResult.IsContinueLoop()) + { + continueLoop = true; + this._logger?.LogInformation("Continuing to the next loop iteration for step {StepIndex} with iteration={Iteration}, goal={StepGoal}.", stepIndex, stepState.ExecutionCount, step.Goal); + } + + // check if current execution is complete by checking whether all variables are already provided + completed = true; + foreach (var variable in step.Provides) + { + if (!stepResult.ContainsKey(variable)) + { + completed = false; + } + else + { + executionState.Variables[variable] = stepResult[variable]; + stepState.AddOrUpdateVariable(stepState.ExecutionCount, variable, + stepResult[variable]); + } + } + + foreach (var variable in step.Passthrough) + { + if (stepResult.ContainsKey(variable)) + { + executionState.Variables[variable] = stepResult[variable]; + stepState.AddOrUpdateVariable(stepState.ExecutionCount, variable, + stepResult[variable]); + + // propagate variables to root context, needed if Flow itself is a step + this.PropagateVariable(rootContext, stepResult, variable); + } + } + + // propagate variables to root context, needed if Flow itself is a step + foreach (var variable in Constants.ChatPluginVariables.ControlVariables) + { + this.PropagateVariable(rootContext, stepResult, variable); + } + } + + if (completed) + { + this._logger?.LogInformation("Completed step {StepIndex} for iteration={Iteration}, goal={StepGoal}.", stepIndex, stepState.ExecutionCount, step.Goal); + + if (step.CompletionType is CompletionType.AtLeastOnce or CompletionType.ZeroOrMore && stepState.Status != ExecutionState.Status.Completed) + { + var nextStepId = $"{stepKey}_{stepState.ExecutionCount + 1}"; + var repeatStep = continueLoop + ? new RepeatOrStartStepResult(true, null) + : await this.CheckRepeatStepAsync(rootContext, step, sessionId, nextStepId, input).ConfigureAwait(false); + + if (repeatStep is null) + { + // unknown error, try again + this._logger?.LogWarning("Unexpected error when checking whether to repeat the step, try again"); + } + else if (repeatStep.Execute is null) + { + // unconfirmed, prompt user + outputs.Add(repeatStep.Prompt!); + this._logger?.LogInformation("Unclear intention, need follow up to check whether to repeat the step"); + await this._flowStatusProvider.SaveExecutionStateAsync(sessionId, executionState).ConfigureAwait(false); + break; + } + else if (repeatStep.Execute.Value) + { + // need repeat the step again + foreach (var variable in step.Provides) + { + executionState.Variables.Remove(variable); + } + + stepState.ExecutionCount++; + await this._flowStatusProvider.SaveExecutionStateAsync(sessionId, executionState).ConfigureAwait(false); + this._logger?.LogInformation("Need repeat step {StepIndex} for iteration={Iteration}, goal={StepGoal}.", stepIndex, stepState.ExecutionCount, step.Goal); + } + else + { + // completed + await this.CompleteStepAsync(rootContext, sessionId, executionState, step, stepState).ConfigureAwait(false); + this._logger?.LogInformation("Completed step {StepIndex} with iteration={Iteration}, goal={StepGoal}.", stepIndex, stepState.ExecutionCount, step.Goal); + } + } + else + { + await this.CompleteStepAsync(rootContext, sessionId, executionState, step, stepState).ConfigureAwait(false); + } + } + else + { + await this._flowStatusProvider.SaveExecutionStateAsync(sessionId, executionState).ConfigureAwait(false); + break; + } + } + + foreach (var output in outputs) + { + this._logger?.LogInformation("[Output] {Output}", output); + } + + rootContext.Update(JsonSerializer.Serialize(outputs)); + + return rootContext; + } + + private void PropagateVariable(ContextVariables rootContext, ContextVariables stepResult, string variableName) + { + if (stepResult.ContainsKey(variableName)) + { + rootContext[variableName] = stepResult[variableName]; + } + } + + private async Task CompleteStepAsync(ContextVariables context, string sessionId, ExecutionState state, FlowStep step, ExecutionState.StepExecutionState stepState) + { + stepState.Status = ExecutionState.Status.Completed; + state.CurrentStepIndex++; + + foreach (var kvp in stepState.Output) + { + if (step.CompletionType == CompletionType.Once) + { + state.Variables[kvp.Key] = kvp.Value.Single(); + } + else + { + // kvp.Value may contain empty strings when the loop was exited and the variables the step provides weren't set + state.Variables[kvp.Key] = JsonSerializer.Serialize(kvp.Value.Where(x => !string.IsNullOrWhiteSpace(x)).ToList()); + } + } + + foreach (var variable in step.Provides) + { + context[variable] = state.Variables[variable]; + } + + await this._flowStatusProvider.SaveExecutionStateAsync(sessionId, state).ConfigureAwait(false); + } + + private void ValidateStep(FlowStep step, ContextVariables context) + { + if (step.Requires.Any(p => !context.ContainsKey(p))) + { + throw new SKException($"Step {step.Goal} requires variables {string.Join(",", step.Requires.Where(p => !context.ContainsKey(p)))} that are not provided. "); + } + } + + private async Task CheckStartStepAsync(ContextVariables context, FlowStep step, string sessionId, string stepId, string input) + { + context = context.Clone(); + context.Set("goal", step.Goal); + context.Set("message", step.StartingMessage); + return await this.CheckRepeatOrStartStepAsync(context, this._checkStartStepFunction, sessionId, $"{stepId}_CheckStartStep", input).ConfigureAwait(false); + } + + private async Task CheckRepeatStepAsync(ContextVariables context, FlowStep step, string sessionId, string nextStepId, string input) + { + context = context.Clone(); + context.Set("goal", step.Goal); + context.Set("transitionMessage", step.TransitionMessage); + return await this.CheckRepeatOrStartStepAsync(context, this._checkRepeatStepFunction, sessionId, $"{nextStepId}_CheckRepeatStep", input).ConfigureAwait(false); + } + + private async Task CheckRepeatOrStartStepAsync(ContextVariables context, ISKFunction function, string sessionId, string checkRepeatOrStartStepId, string input) + { + var chatHistory = await this._flowStatusProvider.GetChatHistoryAsync(sessionId, checkRepeatOrStartStepId).ConfigureAwait(false); + if (chatHistory != null) + { + chatHistory.AddUserMessage(input); + } + else + { + chatHistory = new ChatHistory(); + } + + var scratchPad = this.CreateRepeatOrStartStepScratchPad(chatHistory); + context.Set("agentScratchPad", scratchPad); + this._logger?.LogInformation("Scratchpad: {ScratchPad}", scratchPad); + + var llmResponse = await this._systemKernel.RunAsync(context, function).ConfigureAwait(false); + + string llmResponseText = llmResponse.GetValue()?.Trim() ?? string.Empty; + this._logger?.LogInformation("Response from {Function} : {ActionText}", "CheckRepeatOrStartStep", llmResponseText); + + Match finalAnswerMatch = s_finalAnswerRegex.Match(llmResponseText); + if (finalAnswerMatch.Success) + { + string resultString = finalAnswerMatch.Groups[1].Value.Trim(); + if (bool.TryParse(resultString, out bool result)) + { + await this._flowStatusProvider.SaveChatHistoryAsync(sessionId, checkRepeatOrStartStepId, chatHistory).ConfigureAwait(false); + return new RepeatOrStartStepResult(result); + } + } + + // Extract thought + Match thoughtMatch = s_thoughtRegex.Match(llmResponseText); + if (thoughtMatch.Success) + { + string thoughtString = thoughtMatch.Groups[1].Value.Trim(); + chatHistory.AddSystemMessage(thoughtString); + } + + Match questionMatch = s_questionRegex.Match(llmResponseText); + if (questionMatch.Success) + { + string prompt = questionMatch.Groups[1].Value.Trim(); + chatHistory.AddAssistantMessage(prompt); + await this._flowStatusProvider.SaveChatHistoryAsync(sessionId, checkRepeatOrStartStepId, chatHistory).ConfigureAwait(false); + + return new RepeatOrStartStepResult(null, prompt); + } + + this._logger?.LogWarning("Missing result tag from {Function} : {ActionText}", "CheckRepeatOrStartStep", llmResponseText); + chatHistory.AddSystemMessage(llmResponseText + "\nI should provide either [QUESTION] or [FINAL_ANSWER]"); + await this._flowStatusProvider.SaveChatHistoryAsync(sessionId, checkRepeatOrStartStepId, chatHistory).ConfigureAwait(false); + return null; + } + + private string CreateRepeatOrStartStepScratchPad(ChatHistory chatHistory) + { + var scratchPadLines = new List(); + foreach (var message in chatHistory) + { + if (message.Role == AuthorRole.Assistant) + { + scratchPadLines.Add("[QUESTION]"); + } + else if (message.Role == AuthorRole.User) + { + scratchPadLines.Add("[RESPONSE]"); + } + else if (message.Role == AuthorRole.System) + { + scratchPadLines.Add("[THOUGHT]"); + } + + scratchPadLines.Add(message.Content); + } + + return string.Join("\n", scratchPadLines).Trim(); + } + + private async Task ExecuteStepAsync(FlowStep step, string sessionId, string stepId, string input, IKernel kernel, SKContext context) + { + var stepsTaken = await this._flowStatusProvider.GetReActStepsAsync(sessionId, stepId).ConfigureAwait(false); + var lastStep = stepsTaken.LastOrDefault(); + if (lastStep != null) + { + lastStep.Observation += $"{AuthorRole.User.Label}: {input}\n"; + await this._flowStatusProvider.SaveReActStepsAsync(sessionId, stepId, stepsTaken).ConfigureAwait(false); + } + + var question = step.Goal; + foreach (var variable in step.Requires) + { + if (!variable.StartsWith("_", StringComparison.InvariantCulture) && context.Variables[variable].Length <= this._config.MaxVariableLength) + { + question += $"\n - {variable}: {JsonSerializer.Serialize(context.Variables[variable])}"; + } + } + + for (int i = stepsTaken.Count; i < this._config.MaxStepIterations; i++) + { + var actionStep = await this._reActEngine.GetNextStepAsync(context, question, stepsTaken).ConfigureAwait(false); + + if (actionStep is null) + { + this._logger?.LogWarning("Failed to get action step given input=\"{Input}\"", input); + continue; + } + + stepsTaken.Add(actionStep); + + this._logger?.LogInformation("Thought: {Thought}", actionStep.Thought); + if (!string.IsNullOrEmpty(actionStep.Action!)) + { + if (actionStep.Action!.Contains(Constants.StopAndPromptFunctionName)) + { + string prompt = actionStep.ActionVariables![Constants.StopAndPromptParameterName]; + context.Variables.Update(prompt); + context.TerminateFlow(); + + return context.Variables; + } + + var actionContext = kernel.CreateNewContext(); + foreach (var kvp in context.Variables) + { + if (step.Requires.Contains(kvp.Key) || step.Passthrough.Contains(kvp.Key)) + { + actionContext.Variables[kvp.Key] = kvp.Value; + } + } + + // get chat history + var chatHistory = await this._flowStatusProvider.GetChatHistoryAsync(sessionId, stepId).ConfigureAwait(false); + if (chatHistory is null) + { + chatHistory = new ChatHistory(); + } + else + { + chatHistory.AddUserMessage(input); + } + + try + { + await Task.Delay(this._config.MinIterationTimeMs).ConfigureAwait(false); + var result = await this._reActEngine.InvokeActionAsync(actionStep, input, chatHistory, kernel, actionContext).ConfigureAwait(false); + + if (string.IsNullOrEmpty(result)) + { + actionStep.Observation = "Got no result from action"; + } + else + { + actionStep.Observation = $"{AuthorRole.Assistant.Label}: {result}\n"; + context.Variables.Update(result); + chatHistory.AddAssistantMessage(result); + await this._flowStatusProvider.SaveChatHistoryAsync(sessionId, stepId, chatHistory).ConfigureAwait(false); + + foreach (var passthroughParam in step.Passthrough) + { + if (actionContext.Variables.TryGetValue(passthroughParam, out string? paramValue) && !string.IsNullOrEmpty(paramValue)) + { + context.Variables.Set(passthroughParam, actionContext.Variables[passthroughParam]); + } + } + + foreach (var providedParam in step.Provides) + { + if (actionContext.Variables.TryGetValue(providedParam, out string? paramValue) && !string.IsNullOrEmpty(paramValue)) + { + context.Variables.Set(providedParam, actionContext.Variables[providedParam]); + } + } + + foreach (var variable in Constants.ChatPluginVariables.ControlVariables) + { + if (actionContext.Variables.TryGetValue(variable, out string? variableValue)) + { + context.Variables.Set(variable, variableValue); + } + } + } + } + catch (MissingMethodException ex) + { + actionStep.Observation = $"Error invoking action {actionStep.Action} : {ex.Message}. " + + "Use only the available functions listed in the [AVAILABLE FUNCTIONS] section. " + + "Do not attempt to use any other functions that are not specified.\n"; + + continue; + } + catch (Exception ex) when (!ex.IsCriticalException()) + { + actionStep.Observation = $"Error invoking action {actionStep.Action} : {ex.Message}"; + this._logger?.LogWarning(ex, "Error invoking action {Action}", actionStep.Action); + + continue; + } + + this._logger?.LogInformation("Observation: {Observation}", actionStep.Observation); + await this._flowStatusProvider.SaveReActStepsAsync(sessionId, stepId, stepsTaken).ConfigureAwait(false); + + if (!string.IsNullOrEmpty(context.Result)) + { + if (context.Variables.IsTerminateFlow()) + { + // Terminate the flow without another round of reasoning, to save the LLM reasoning calls. + // This is not suggested unless plugin has performance requirement and has explicitly set the control variable. + return context.Variables; + } + + foreach (var variable in Constants.ChatPluginVariables.ControlVariables) + { + if (context.Variables.ContainsKey(variable)) + { + // redirect control to client + return context.Variables; + } + } + + if (!step.Provides.Except(context.Variables.Where(v => !string.IsNullOrEmpty(v.Value)).Select(_ => _.Key)).Any()) + { + // step is complete + return context.Variables; + } + + // continue to next iteration + continue; + } + + this._logger?.LogInformation("Action: No result from action"); + } + else if (!string.IsNullOrEmpty(actionStep.FinalAnswer)) + { + if (step.Provides.Count() == 1) + { + context.Variables.Set(step.Provides.Single(), actionStep.FinalAnswer); + return context.Variables; + } + } + else + { + actionStep.Observation = "ACTION $JSON_BLOB must be provided as part of thought process."; + this._logger?.LogInformation("Action: No action to take"); + } + + // continue to next iteration + await Task.Delay(this._config.MinIterationTimeMs).ConfigureAwait(false); + } + + throw new SKException($"Failed to complete step {stepId} for session {sessionId}."); + } + + private ISKFunction ImportSemanticFunction(IKernel kernel, string functionName, string promptTemplate, PromptTemplateConfig config) + { + var factory = new BasicPromptTemplateFactory(kernel.LoggerFactory); + var template = factory.Create(promptTemplate, config); + + return kernel.RegisterSemanticFunction(RestrictedPluginName, functionName, config, template); + } + + private class RepeatOrStartStepResult + { + public RepeatOrStartStepResult(bool? execute, string? prompt = null) + { + this.Prompt = prompt; + this.Execute = execute; + } + + public bool? Execute { get; } + + public string? Prompt { get; } + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Execution/FlowStatusProvider.cs b/dotnet/src/Experimental/Orchestration.Flow/Execution/FlowStatusProvider.cs new file mode 100644 index 0000000000..99e5c1abd8 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Execution/FlowStatusProvider.cs @@ -0,0 +1,169 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; +using Microsoft.SemanticKernel.Experimental.Orchestration.Execution; +using Microsoft.SemanticKernel.Memory; + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// Default flow status provider implemented on top of +/// +public sealed class FlowStatusProvider : IFlowStatusProvider +{ + private readonly IMemoryStore _memoryStore; + + private readonly string _collectionName; + + /// + /// Initializes a new instance of the class. + /// + public static async Task ConnectAsync(IMemoryStore memoryStore, string? collectionName = null) + { + var provider = new FlowStatusProvider(memoryStore, collectionName); + return await InitializeProviderStoreAsync(provider).ConfigureAwait(false); + } + + /// + /// Initializes a new instance of the class. + /// + /// instance + /// Collection name in instance + private FlowStatusProvider(IMemoryStore memoryStore, string? collectionName = null) + { + this._memoryStore = memoryStore; + this._collectionName = collectionName ?? nameof(FlowStatusProvider); + } + + /// + public async Task GetExecutionStateAsync(string sessionId) + { + var result = await (this._memoryStore.GetAsync(this._collectionName, this.GetExecutionStateStorageKey(sessionId))).ConfigureAwait(false); + var text = result?.Metadata.Text ?? string.Empty; + + if (!string.IsNullOrEmpty(text)) + { + try + { + return JsonSerializer.Deserialize(text) ?? new ExecutionState(); + } + catch + { + throw new InvalidOperationException( + $"Failed to deserialize execution state for sessionId={sessionId}, data={text}"); + } + } + else + { + return new ExecutionState(); + } + } + + /// + public async Task SaveExecutionStateAsync(string sessionId, ExecutionState state) + { + var json = JsonSerializer.Serialize(state); + await this._memoryStore.UpsertAsync(this._collectionName, this.CreateMemoryRecord(this.GetExecutionStateStorageKey(sessionId), json)) + .ConfigureAwait(false); + } + + private string GetExecutionStateStorageKey(string sessionId) + { + return $"FlowStatus_{sessionId}"; + } + + /// + public async Task GetChatHistoryAsync(string sessionId, string stepId) + { + var result = await this._memoryStore.GetAsync(this._collectionName, this.GetChatHistoryStorageKey(sessionId, stepId)).ConfigureAwait(false); + var text = result?.Metadata.Text ?? string.Empty; + + if (!string.IsNullOrEmpty(text)) + { + try + { + return ChatHistorySerializer.Deserialize(text); + } + catch + { + throw new InvalidOperationException( + $"Failed to deserialize chat history for session {sessionId}, data={text}"); + } + } + else + { + return null; + } + } + + /// + public async Task SaveChatHistoryAsync(string sessionId, string stepId, ChatHistory history) + { + var json = ChatHistorySerializer.Serialize(history); + await this._memoryStore.UpsertAsync(this._collectionName, this.CreateMemoryRecord(this.GetChatHistoryStorageKey(sessionId, stepId), json)) + .ConfigureAwait(false); + } + + private string GetChatHistoryStorageKey(string sessionId, string stepId) + { + return $"ChatHistory_{sessionId}_{stepId}"; + } + + /// + public async Task> GetReActStepsAsync(string sessionId, string stepId) + { + var result = await this._memoryStore.GetAsync(this._collectionName, this.GetStepsStorageKey(sessionId, stepId)).ConfigureAwait(false); + var text = result?.Metadata.Text ?? string.Empty; + + if (!string.IsNullOrEmpty(text)) + { + try + { + return JsonSerializer.Deserialize>(text) ?? new List(); + } + catch + { + throw new InvalidOperationException( + $"Failed to deserialize steps for session {sessionId}, data={text}"); + } + } + + return new List(); + } + + /// + public async Task SaveReActStepsAsync(string sessionId, string stepId, List steps) + { + var json = JsonSerializer.Serialize(steps); + await this._memoryStore.UpsertAsync(this._collectionName, this.CreateMemoryRecord(this.GetStepsStorageKey(sessionId, stepId), json)) + .ConfigureAwait(false); + } + + private static async Task InitializeProviderStoreAsync(FlowStatusProvider flowProvider, CancellationToken cancellationToken = default) + { + if (!await flowProvider._memoryStore.DoesCollectionExistAsync(flowProvider._collectionName, cancellationToken).ConfigureAwait(false)) + { + await flowProvider._memoryStore.CreateCollectionAsync(flowProvider._collectionName, cancellationToken).ConfigureAwait(false); + } + + return flowProvider; + } + + private string GetStepsStorageKey(string sessionId, string stepId) + { + return $"Steps_{sessionId}_{stepId}"; + } + + private MemoryRecord CreateMemoryRecord(string key, string text) + { + return MemoryRecord.LocalRecord(key, text, null, ReadOnlyMemory.Empty); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Execution/ReActEngine.cs b/dotnet/src/Experimental/Orchestration.Flow/Execution/ReActEngine.cs new file mode 100644 index 0000000000..4081efbbba --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Execution/ReActEngine.cs @@ -0,0 +1,428 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Orchestration; +using Microsoft.SemanticKernel.TemplateEngine; +using Microsoft.SemanticKernel.TemplateEngine.Basic; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Execution; + +/// +/// Chat ReAct Engine +/// +internal sealed class ReActEngine +{ + /// + /// The logger + /// + private readonly ILogger _logger; + + /// + /// Re-Act function for flow execution + /// + private readonly ISKFunction _reActFunction; + + /// + /// The flow planner config + /// + private readonly FlowOrchestratorConfig _config; + + /// + /// The goal to use when creating semantic functions that are restricted from flow creation + /// + private const string RestrictedPluginName = "ReActEngine_Excluded"; + + /// + /// The Action tag + /// + private const string Action = "[ACTION]"; + + /// + /// The Thought tag + /// + private const string Thought = "[THOUGHT]"; + + /// + /// The Observation tag + /// + private const string Observation = "[OBSERVATION]"; + + /// + /// The prefix used for the scratch pad + /// + private const string ScratchPadPrefix = + "This was my previous work (but they haven't seen any of it! They only see what I return as final answer):"; + + /// + /// The regex for parsing the action response + /// + private static readonly Regex s_actionRegex = + new(@"(?<=\[ACTION\])[^{}]*(\{.*?\})(?=\n\[)", RegexOptions.Singleline); + + /// + /// The regex for parsing the final action response + /// + private static readonly Regex s_finalActionRegex = + new(@"\[FINAL.+\][^{}]*({(?:[^{}]*{[^{}]*})*[^{}]*})", RegexOptions.Singleline); + + /// + /// The regex for parsing the thought response + /// + private static readonly Regex s_thoughtRegex = + new(@"(\[THOUGHT\])?(?.+?)(?=\[ACTION\]|$)", RegexOptions.Singleline); + + /// + /// The regex for parsing the final answer response + /// + private static readonly Regex s_finalAnswerRegex = + new(@"\[FINAL.+\](?.+)", RegexOptions.Singleline); + + internal ReActEngine(IKernel systemKernel, ILogger logger, FlowOrchestratorConfig config) + { + this._logger = logger; + + this._config = config; + this._config.ExcludedPlugins.Add(RestrictedPluginName); + + var modelId = config.AIRequestSettings?.ModelId; + var promptConfig = config.ReActPromptTemplateConfig; + if (promptConfig is null) + { + promptConfig = new PromptTemplateConfig(); + + string promptConfigString = EmbeddedResource.Read("Plugins.ReActEngine.config.json")!; + if (!string.IsNullOrEmpty(modelId)) + { + var modelConfigString = EmbeddedResource.Read($"Plugins.ReActEngine.{modelId}.config.json", false); + promptConfigString = string.IsNullOrEmpty(modelConfigString) ? promptConfigString : modelConfigString!; + } + + if (!string.IsNullOrEmpty(promptConfigString)) + { + promptConfig = PromptTemplateConfig.FromJson(promptConfigString); + } + else + { + promptConfig.SetMaxTokens(config.MaxTokens); + } + } + + var promptTemplate = config.ReActPromptTemplate; + if (string.IsNullOrEmpty(promptTemplate)) + { + promptTemplate = EmbeddedResource.Read("Plugins.ReActEngine.skprompt.txt")!; + + if (!string.IsNullOrEmpty(promptTemplate)) + { + var modelPromptTemplate = EmbeddedResource.Read($"Plugins.ReActEngine.{modelId}.skprompt.txt", false); + promptTemplate = string.IsNullOrEmpty(modelPromptTemplate) ? promptTemplate : modelPromptTemplate!; + } + } + + this._reActFunction = this.ImportSemanticFunction(systemKernel, "ReActFunction", promptTemplate!, promptConfig); + } + + internal async Task GetNextStepAsync(SKContext context, string question, List previousSteps) + { + context.Variables.Set("question", question); + var scratchPad = this.CreateScratchPad(previousSteps); + context.Variables.Set("agentScratchPad", scratchPad); + + var availableFunctions = this.GetAvailableFunctions(context).ToArray(); + if (availableFunctions.Length == 1) + { + var firstActionFunction = availableFunctions.First(); + if (firstActionFunction.Parameters.Count == 0) + { + var action = $"{firstActionFunction.PluginName}.{firstActionFunction.Name}"; + this._logger?.LogDebug($"Auto selecting {Action} as it is the only function available and it has no parameters.", action); + return new ReActStep + { + Action = action + }; + } + } + + var functionDesc = this.GetFunctionDescriptions(availableFunctions); + context.Variables.Set("functionDescriptions", functionDesc); + + this._logger?.LogInformation("question: {Question}", question); + this._logger?.LogInformation("functionDescriptions: {FunctionDescriptions}", functionDesc); + this._logger?.LogInformation("Scratchpad: {ScratchPad}", scratchPad); + + var llmResponse = await this._reActFunction.InvokeAsync(context).ConfigureAwait(false); + + string llmResponseText = llmResponse.GetValue()!.Trim(); + this._logger?.LogDebug("Response : {ActionText}", llmResponseText); + + var actionStep = this.ParseResult(llmResponseText); + + if (!string.IsNullOrEmpty(actionStep.Action) || previousSteps.Count == 0) + { + return actionStep; + } + + actionStep.Observation = "Failed to parse valid action step, missing action or final answer."; + this._logger?.LogWarning("Failed to parse valid action step from llm response={LLMResponseText}", llmResponseText); + this._logger?.LogWarning("Scratchpad={ScratchPad}", scratchPad); + return actionStep; + } + + internal async Task InvokeActionAsync(ReActStep actionStep, string chatInput, ChatHistory chatHistory, IKernel kernel, SKContext context) + { + var variables = actionStep.ActionVariables ?? new Dictionary(); + + variables[Constants.ActionVariableNames.ChatInput] = chatInput; + variables[Constants.ActionVariableNames.ChatHistory] = ChatHistorySerializer.Serialize(chatHistory); + this._logger?.LogInformation("Action: {Action}({ActionVariables})", actionStep.Action, JsonSerializer.Serialize(variables)); + + var availableFunctions = this.GetAvailableFunctions(context); + var targetFunction = availableFunctions.FirstOrDefault(f => ToFullyQualifiedName(f) == actionStep.Action); + if (targetFunction is null) + { + throw new MissingMethodException($"The function '{actionStep.Action}' was not found."); + } + + var function = kernel.Functions.GetFunction(targetFunction.PluginName, targetFunction.Name); + var functionView = function.Describe(); + + var actionContext = this.CreateActionContext(variables, kernel, context); + foreach (var parameter in functionView.Parameters) + { + if (!actionContext.Variables.ContainsKey(parameter.Name)) + { + actionContext.Variables.Set(parameter.Name, parameter.DefaultValue ?? string.Empty); + } + } + + try + { + var result = await function.InvokeAsync(actionContext).ConfigureAwait(false); + + foreach (var variable in actionContext.Variables) + { + context.Variables.Set(variable.Key, variable.Value); + } + + this._logger?.LogDebug("Invoked {FunctionName}. Result: {Result}", targetFunction.Name, result.GetValue()); + + return result.GetValue() ?? string.Empty; + } + catch (Exception e) when (!e.IsCriticalException()) + { + this._logger?.LogError(e, "Something went wrong in action step: {0}.{1}. Error: {2}", targetFunction.PluginName, targetFunction.Name, e.Message); + return $"Something went wrong in action step: {targetFunction.PluginName}.{targetFunction.Name}. Error: {e.Message} {e.InnerException?.Message}"; + } + } + + private SKContext CreateActionContext(Dictionary actionVariables, IKernel kernel, SKContext context) + { + var actionContext = context.Clone(); + foreach (var kvp in actionVariables) + { + actionContext.Variables.Set(kvp.Key, kvp.Value); + } + + return actionContext; + } + + private ISKFunction ImportSemanticFunction(IKernel kernel, string functionName, string promptTemplate, PromptTemplateConfig config) + { + var factory = new BasicPromptTemplateFactory(kernel.LoggerFactory); + var template = factory.Create(promptTemplate, config); + + return kernel.RegisterSemanticFunction(RestrictedPluginName, functionName, config, template); + } + + private string CreateScratchPad(List stepsTaken) + { + if (stepsTaken.Count == 0) + { + return string.Empty; + } + + var scratchPadLines = new List + { + // Add the original first thought + ScratchPadPrefix, + $"{Thought} {stepsTaken[0].Thought}" + }; + + // Keep track of where to insert the next step + var insertPoint = scratchPadLines.Count; + + // Keep the most recent steps in the scratch pad. + for (var i = stepsTaken.Count - 1; i >= 0; i--) + { + if (scratchPadLines.Count / 4.0 > (this._config.MaxTokens * 0.75)) + { + this._logger.LogDebug("Scratchpad is too long, truncating. Skipping {CountSkipped} steps.", i + 1); + break; + } + + var s = stepsTaken[i]; + + if (!string.IsNullOrEmpty(s.Observation)) + { + scratchPadLines.Insert(insertPoint, $"{Observation} \n{s.Observation}"); + } + + if (!string.IsNullOrEmpty(s.Action)) + { + // ignore the built-in context variables + var variablesToPrint = s.ActionVariables?.Where(v => !Constants.ActionVariableNames.All.Contains(v.Key)).ToDictionary(_ => _.Key, _ => _.Value); + scratchPadLines.Insert(insertPoint, $"{Action} {{\"action\": \"{s.Action}\",\"action_variables\": {JsonSerializer.Serialize(variablesToPrint)}}}"); + } + + if (i != 0) + { + scratchPadLines.Insert(insertPoint, $"{Thought} {s.Thought}"); + } + } + + return string.Join("\n", scratchPadLines).Trim(); + } + + private ReActStep ParseResult(string input) + { + var result = new ReActStep + { + OriginalResponse = input + }; + + // Extract final answer + Match finalAnswerMatch = s_finalAnswerRegex.Match(input); + + if (finalAnswerMatch.Success) + { + result.FinalAnswer = finalAnswerMatch.Groups[1].Value.Trim(); + } + + // Extract thought + Match thoughtMatch = s_thoughtRegex.Match(input); + + if (thoughtMatch.Success) + { + result.Thought = thoughtMatch.Value.Trim(); + } + else if (!input.Contains(Action)) + { + result.Thought = input; + } + else + { + throw new InvalidOperationException("Unexpected input format"); + } + + result.Thought = result.Thought.Replace(Thought, string.Empty).Trim(); + + // Extract action + string actionStepJson = input; + Match actionMatch = s_actionRegex.Match(input + "\n["); + if (actionMatch.Success) + { + actionStepJson = actionMatch.Groups[1].Value.Trim(); + } + else + { + Match finalActionMatch = s_finalActionRegex.Match(input); + if (finalActionMatch.Success) + { + actionStepJson = finalActionMatch.Groups[1].Value.Trim(); + } + } + + try + { + var reActStep = JsonSerializer.Deserialize(actionStepJson); + if (reActStep is null) + { + result.Observation = $"Action step parsing error, empty JSON: {actionStepJson}"; + } + else + { + result.Action = reActStep.Action; + result.ActionVariables = reActStep.ActionVariables; + } + } + catch (JsonException) + { + result.Observation = $"Action step parsing error, invalid JSON: {actionStepJson}"; + } + + if (string.IsNullOrEmpty(result.Thought) && string.IsNullOrEmpty(result.Action)) + { + result.Observation = "Action step error, no thought or action found. Please give a valid thought and/or action."; + } + + return result; + } + + private string GetFunctionDescriptions(FunctionView[] functions) + { + return string.Join("\n", functions.Select(ToManualString)); + } + + private IEnumerable GetAvailableFunctions(SKContext context) + { + var functionViews = context.Functions!.GetFunctionViews(); + + var excludedPlugins = this._config.ExcludedPlugins ?? new HashSet(); + var excludedFunctions = this._config.ExcludedFunctions ?? new HashSet(); + + var availableFunctions = + functionViews + .Where(s => !excludedPlugins.Contains(s.PluginName) && !excludedFunctions.Contains(s.Name)) + .OrderBy(x => x.PluginName) + .ThenBy(x => x.Name); + + return this._config.EnableAutoTermination + ? availableFunctions.Append(GetStopAndPromptUserFunction()) + : availableFunctions; + } + + private static FunctionView GetStopAndPromptUserFunction() + { + ParameterView promptParameter = new( + Constants.StopAndPromptParameterName, + "The message to be shown to the user.", + string.Empty, + ParameterViewType.String); + + return new FunctionView( + Constants.StopAndPromptFunctionName, + "_REACT_ENGINE_", + "Terminate the session, only used when previous attempts failed with FATAL error and need notify user", + new[] { promptParameter }); + } + + private static string ToManualString(FunctionView function) + { + var inputs = string.Join("\n", function.Parameters.Select(parameter => + { + var defaultValueString = string.IsNullOrEmpty(parameter.DefaultValue) ? string.Empty : $"(default='{parameter.DefaultValue}')"; + return $" - {parameter.Name}: {parameter.Description} {defaultValueString}"; + })); + + var functionDescription = function.Description.Trim(); + + if (string.IsNullOrEmpty(inputs)) + { + return $"{ToFullyQualifiedName(function)}: {functionDescription}\n"; + } + + return $"{ToFullyQualifiedName(function)}: {functionDescription}\n{inputs}\n"; + } + + private static string ToFullyQualifiedName(FunctionView function) + { + return $"{function.PluginName}.{function.Name}"; + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Execution/ReActStep.cs b/dotnet/src/Experimental/Orchestration.Flow/Execution/ReActStep.cs new file mode 100644 index 0000000000..0e39452c7e --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Execution/ReActStep.cs @@ -0,0 +1,51 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Microsoft.SemanticKernel.Experimental.Orchestration.Execution; + +/// +/// An ReAct (Reasoning-Action-Observation) step in flow execution. +/// +/// +/// https://arxiv.org/pdf/2210.03629.pdf +/// +public class ReActStep +{ + /// + /// Gets or sets the step number. + /// + [JsonPropertyName("thought")] + public string? Thought { get; set; } + + /// + /// Gets or sets the action of the step + /// + [JsonPropertyName("action")] + public string? Action { get; set; } + + /// + /// Gets or sets the variables for the action + /// + [JsonPropertyName("action_variables")] + public Dictionary? ActionVariables { get; set; } + + /// + /// Gets or sets the output of the action + /// + [JsonPropertyName("observation")] + public string? Observation { get; set; } + + /// + /// Gets or sets the output of the system + /// + [JsonPropertyName("final_answer")] + public string? FinalAnswer { get; set; } + + /// + /// The raw response from the action + /// + [JsonPropertyName("original_response")] + public string? OriginalResponse { get; set; } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj b/dotnet/src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj new file mode 100644 index 0000000000..e5546957d9 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj @@ -0,0 +1,35 @@ +īģŋ + + + Microsoft.SemanticKernel.Experimental.Orchestration.Flow + Microsoft.SemanticKernel.Experimental.Orchestration + netstandard2.0 + Latest + + + + + + Semantic Kernel - Flow Orchestrator + Semantic Kernel Flow Orchestrator + + + + + Always + + + + + <_Parameter1>SemanticKernel.Experimental.Orchestration.Flow.UnitTests + + + + + + + + + + + \ No newline at end of file diff --git a/dotnet/src/Experimental/Orchestration.Flow/Extensions/ContextVariablesExtensions.cs b/dotnet/src/Experimental/Orchestration.Flow/Extensions/ContextVariablesExtensions.cs new file mode 100644 index 0000000000..8317f6b4da --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Extensions/ContextVariablesExtensions.cs @@ -0,0 +1,58 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Linq; +using Microsoft.SemanticKernel.Experimental.Orchestration.Execution; +using Microsoft.SemanticKernel.Orchestration; + +#pragma warning disable IDE0130 // Namespace does not match folder structure +// ReSharper disable once CheckNamespace +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 // Namespace does not match folder structure + +/// +/// Extension methods for +/// +// ReSharper disable once InconsistentNaming +public static class ContextVariablesExtensions +{ + /// + /// Check if we should prompt user for input based on current context. + /// + /// context + internal static bool IsPromptInput(this ContextVariables context) + { + return context.TryGetValue(Constants.ChatPluginVariables.PromptInputName, out string? promptInput) + && promptInput == Constants.ChatPluginVariables.DefaultValue; + } + + /// + /// Check if we should force the next iteration loop based on current context. + /// + /// context + internal static bool IsContinueLoop(this ContextVariables context) + { + return context.TryGetValue(Constants.ChatPluginVariables.ContinueLoopName, out string? continueLoop) + && continueLoop == Constants.ChatPluginVariables.DefaultValue; + } + + /// + /// Check if we should terminate flow based on current context. + /// + /// context + public static bool IsTerminateFlow(this ContextVariables context) + { + return context.TryGetValue(Constants.ChatPluginVariables.StopFlowName, out string? stopFlow) + && stopFlow == Constants.ChatPluginVariables.DefaultValue; + } + + /// + /// Check if all variables to be provided with the flow is available in the context + /// + /// context + /// flow + /// + public static bool IsComplete(this ContextVariables context, Flow flow) + { + return flow.Provides.All(context.ContainsKey); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Extensions/FlowExtensions.cs b/dotnet/src/Experimental/Orchestration.Flow/Extensions/FlowExtensions.cs new file mode 100644 index 0000000000..dabde277f6 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Extensions/FlowExtensions.cs @@ -0,0 +1,76 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; + +#pragma warning disable IDE0130 // Namespace does not match folder structure +// ReSharper disable once CheckNamespace +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 // Namespace does not match folder structure + +/// +/// Extension methods for . +/// +public static class FlowExtensions +{ + internal static List SortSteps(this Flow flow) + { + var sortedSteps = new List(); + var remainingSteps = new List(flow.Steps); + + while (remainingSteps.Count > 0) + { + var independentStep = remainingSteps.FirstOrDefault(step => !remainingSteps.Any(step.DependsOn)); + + if (independentStep is null) + { + throw new SKException("The plan contains circular dependencies."); + } + + sortedSteps.Add(independentStep); + remainingSteps.Remove(independentStep); + } + + return sortedSteps; + } + + /// + /// Hydrate the reference steps in the flow. + /// + /// the flow + /// the flow repository + /// The flow with hydrated steps + /// if referenced flow cannot be found in the repository + public static async Task BuildReferenceAsync(this Flow flow, IFlowCatalog flowRepository) + { + var referenceSteps = flow.Steps.OfType().ToList(); + + foreach (var step in referenceSteps) + { + flow.Steps.Remove(step); + var referencedFlow = await flowRepository.GetFlowAsync(step.FlowName).ConfigureAwait(false); + if (referencedFlow is null) + { + throw new ArgumentException($"Referenced flow {step.FlowName} is not found"); + } + + referencedFlow.CompletionType = step.CompletionType; + referencedFlow.AddPassthrough(step.Passthrough.ToArray()); + referencedFlow.StartingMessage = step.StartingMessage; + referencedFlow.TransitionMessage = step.TransitionMessage; + + foreach (var referencedFlowStep in referencedFlow.Steps) + { + referencedFlowStep.AddPassthrough(step.Passthrough.ToArray(), isReferencedFlow: true); + } + + flow.Steps.Add(referencedFlow); + } + + return flow; + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Extensions/PromptTemplateConfigExtensions.cs b/dotnet/src/Experimental/Orchestration.Flow/Extensions/PromptTemplateConfigExtensions.cs new file mode 100644 index 0000000000..336b4def3c --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Extensions/PromptTemplateConfigExtensions.cs @@ -0,0 +1,29 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.AI; +using Microsoft.SemanticKernel.TemplateEngine; + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// Extension methods for PromptTemplateConfig +/// +internal static class PromptTemplateConfigExtensions +{ + /// + /// Set the max_tokens request setting to be used by OpenAI models + /// + /// PromptTemplateConfig instance + /// Value of max tokens to set + internal static void SetMaxTokens(this PromptTemplateConfig config, int maxTokens) + { + AIRequestSettings requestSettings = config.GetDefaultRequestSettings() ?? new(); + if (config.ModelSettings.Count == 0) + { + config.ModelSettings.Add(requestSettings); + } + requestSettings.ExtensionData["max_tokens"] = maxTokens; + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Extensions/SKContextExtensions.cs b/dotnet/src/Experimental/Orchestration.Flow/Extensions/SKContextExtensions.cs new file mode 100644 index 0000000000..c268958469 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Extensions/SKContextExtensions.cs @@ -0,0 +1,92 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.AI.ChatCompletion; +using Microsoft.SemanticKernel.Experimental.Orchestration.Execution; +using Microsoft.SemanticKernel.Orchestration; + +#pragma warning disable IDE0130 // Namespace does not match folder structure +// ReSharper disable once CheckNamespace +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 // Namespace does not match folder structure + +/// +/// Extension methods for +/// +// ReSharper disable once InconsistentNaming +public static class SKContextExtensions +{ + /// + /// Get from context. + /// + /// context + /// The chat history + public static ChatHistory? GetChatHistory(this SKContext context) + { + if (context.Variables.TryGetValue(Constants.ActionVariableNames.ChatHistory, out string? chatHistoryText) && !string.IsNullOrEmpty(chatHistoryText)) + { + return ChatHistorySerializer.Deserialize(chatHistoryText); + } + + return null; + } + + /// + /// Get latest chat input from context. + /// + /// context + /// The latest chat input. + public static string GetChatInput(this SKContext context) + { + if (context.Variables.TryGetValue(Constants.ActionVariableNames.ChatInput, out string? chatInput)) + { + return chatInput; + } + + return string.Empty; + } + + /// + /// Signal the orchestrator to prompt user for input with current function response. + /// + /// context + public static void PromptInput(this SKContext context) + { + // Cant prompt the user for input and exit the execution at the same time + if (!context.Variables.ContainsKey(Constants.ChatPluginVariables.ExitLoopName)) + { + context.Variables.Set(Constants.ChatPluginVariables.PromptInputName, Constants.ChatPluginVariables.DefaultValue); + } + } + + /// + /// Signal the orchestrator to exit out of the AtLeastOnce or ZeroOrMore loop. If response is non-null, that value will be outputted to the user. + /// + /// context + /// context + public static void ExitLoop(this SKContext context, string? response = null) + { + // Cant prompt the user for input and exit the execution at the same time + if (!context.Variables.ContainsKey(Constants.ChatPluginVariables.PromptInputName)) + { + context.Variables.Set(Constants.ChatPluginVariables.ExitLoopName, response ?? string.Empty); + } + } + + /// + /// Signal the orchestrator to go to the next iteration of the loop in the AtLeastOnce or ZeroOrMore step. + /// + /// context + public static void ContinueLoop(this SKContext context) + { + context.Variables.Set(Constants.ChatPluginVariables.ContinueLoopName, Constants.ChatPluginVariables.DefaultValue); + } + + /// + /// Signal the orchestrator to terminate the flow. + /// + /// context + public static void TerminateFlow(this SKContext context) + { + context.Variables.Set(Constants.ChatPluginVariables.StopFlowName, Constants.ChatPluginVariables.DefaultValue); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/FlowOrchestrator.cs b/dotnet/src/Experimental/Orchestration.Flow/FlowOrchestrator.cs new file mode 100644 index 0000000000..a9d01da53e --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/FlowOrchestrator.cs @@ -0,0 +1,82 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Threading.Tasks; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; +using Microsoft.SemanticKernel.Experimental.Orchestration.Execution; +using Microsoft.SemanticKernel.Orchestration; + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// A flow orchestrator that using semantic kernel for execution. +/// +public class FlowOrchestrator +{ + private readonly KernelBuilder _kernelBuilder; + + private readonly IFlowStatusProvider _flowStatusProvider; + + private readonly Dictionary _globalPluginCollection; + + private readonly IFlowValidator _flowValidator; + + private readonly FlowOrchestratorConfig? _config; + + /// + /// Initialize a new instance of the class. + /// + /// The semantic kernel builder. + /// The flow status provider. + /// The global plugin collection + /// The flow validator. + /// Optional configuration object + public FlowOrchestrator( + KernelBuilder kernelBuilder, + IFlowStatusProvider flowStatusProvider, + Dictionary? globalPluginCollection = null, + IFlowValidator? validator = null, + FlowOrchestratorConfig? config = null) + { + Verify.NotNull(kernelBuilder); + + this._kernelBuilder = kernelBuilder; + this._flowStatusProvider = flowStatusProvider; + this._globalPluginCollection = globalPluginCollection ?? new Dictionary(); + this._flowValidator = validator ?? new FlowValidator(); + this._config = config; + } + + /// + /// Execute a given flow. + /// + /// goal to achieve + /// execution session id + /// current input + /// execution context variables + /// ContextVariables, which includes a json array of strings as output. The flow result is also exposed through the context when completes. + public async Task ExecuteFlowAsync( + [Description("The flow to execute")] Flow flow, + [Description("Execution session id")] string sessionId, + [Description("Current input")] string input, + [Description("Execution context variables")] + ContextVariables? contextVariables = null) + { + try + { + this._flowValidator.Validate(flow); + } + catch (Exception ex) + { + throw new SKException("Invalid flow", ex); + } + + var executor = new FlowExecutor(this._kernelBuilder, this._flowStatusProvider, this._globalPluginCollection, this._config); + return await executor.ExecuteAsync(flow, sessionId, input, contextVariables ?? new ContextVariables(null)).ConfigureAwait(false); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/FlowOrchestratorConfig.cs b/dotnet/src/Experimental/Orchestration.Flow/FlowOrchestratorConfig.cs new file mode 100644 index 0000000000..a20ca5dba5 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/FlowOrchestratorConfig.cs @@ -0,0 +1,76 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; +using Microsoft.SemanticKernel.AI; +using Microsoft.SemanticKernel.Experimental.Orchestration.Execution; +using Microsoft.SemanticKernel.TemplateEngine; + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// Configuration for flow planner instances. +/// +public sealed class FlowOrchestratorConfig +{ + /// + /// A list of plugins to exclude from the plan creation request. + /// + public HashSet ExcludedPlugins { get; } = new(); + + /// + /// A list of functions to exclude from the plan creation request. + /// + public HashSet ExcludedFunctions { get; } = new(); + + /// + /// The maximum number of tokens to allow in a plan. + /// + public int MaxTokens { get; set; } = 1024; + + /// + /// The maximum length of a string variable. + /// + /// + /// In most cases, the required variables are passed to ReAct engine to infer the next plugin and parameters to execute. + /// However when the variable is too long, it will either be truncated or decrease the robustness of value passing. + /// To mitigate that, the will avoid rendering the variables exceeding MaxVariableLength in the prompt. + /// And the variables should be accessed implicitly from SKContext instead of function parameters by the plugins. + /// + public int MaxVariableLength { get; set; } = 400; + + /// + /// The maximum number of iterations to allow for a step. + /// + public int MaxStepIterations { get; set; } = 10; + + /// + /// The minimum time to wait between iterations in milliseconds. + /// + public int MinIterationTimeMs { get; set; } = 0; + + /// + /// Optional. The prompt template override for ReAct engine. + /// + public string? ReActPromptTemplate { get; set; } = null; + + /// + /// Optional. The prompt template configuration override for the ReAct engine. + /// + public PromptTemplateConfig? ReActPromptTemplateConfig { get; set; } = null; + + /// + /// When this is enabled, the flow will be terminated automatically if ReAct engine has exhausted available plugins. + /// + public bool EnableAutoTermination { get; set; } = false; + + /// + /// Optional. The AI request settings for the ReAct engine. + /// + /// + /// Prompt used for reasoning may be different for different models, the prompt selection would be based on the AIRequestSettings. + /// if the built in prompt template does not work for your model, suggest to override it with . + /// + public AIRequestSettings? AIRequestSettings { get; set; } = null; +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/FlowSerializer.cs b/dotnet/src/Experimental/Orchestration.Flow/FlowSerializer.cs new file mode 100644 index 0000000000..2c85fb172b --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/FlowSerializer.cs @@ -0,0 +1,119 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Text.Json.Serialization; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// Serializer for +/// +public static class FlowSerializer +{ + /// + /// Deserialize flow from yaml + /// + /// the yaml string + /// the instance + public static Flow DeserializeFromYaml(string yaml) + { + var deserializer = new DeserializerBuilder() + .WithNamingConvention(CamelCaseNamingConvention.Instance) + .Build(); + + var flow = deserializer.Deserialize(new StringReader(yaml)); + + return UpCast(flow); + } + + /// + /// Deserialize flow from json + /// + /// the json string + /// the instance + public static Flow? DeserializeFromJson(string json) + { + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) } + }; + + var flow = JsonSerializer.Deserialize(json, options); + if (flow is null) + { + throw new JsonException("Failed to deserialize flow"); + } + + return UpCast(flow); + } + + private static Flow UpCast(FlowModel flow) + { + Flow result = new(flow.Name, flow.Goal); + + foreach (var step in flow.Steps) + { + result.AddStep(UpCast(step)); + } + + PopulateVariables(result, flow); + + return result; + } + + private static FlowStep UpCast(FlowStepModel step) + { + FlowStep result = string.IsNullOrEmpty(step.FlowName) ? new FlowStep(step.Goal) : new ReferenceFlowStep(step.FlowName!); + + result.CompletionType = step.CompletionType; + result.StartingMessage = step.StartingMessage; + result.TransitionMessage = step.TransitionMessage; + result.Plugins = step.Plugins; + + PopulateVariables(result, step); + + return result; + } + + private static void PopulateVariables(FlowStep step, FlowStepModel model) + { + step.AddProvides(model.Provides.ToArray()); + step.AddRequires(model.Requires.ToArray()); + step.AddPassthrough(model.Passthrough.ToArray()); + } + + private class FlowStepModel + { + public string Goal { get; set; } = string.Empty; + + public List Requires { get; set; } = new(); + + public List Provides { get; set; } = new(); + + public List Passthrough { get; set; } = new(); + + public CompletionType CompletionType { get; set; } = CompletionType.Once; + + public string? StartingMessage { get; set; } + + public string? TransitionMessage { get; set; } + + public List Plugins { get; set; } = new(); + + public string? FlowName { get; set; } + } + + private class FlowModel : FlowStepModel + { + public string Name { get; set; } = string.Empty; + + public List Steps { get; set; } = new(); + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/FlowValidator.cs b/dotnet/src/Experimental/Orchestration.Flow/FlowValidator.cs new file mode 100644 index 0000000000..d897f32f39 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/FlowValidator.cs @@ -0,0 +1,102 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Linq; +using Microsoft.SemanticKernel.Diagnostics; +using Microsoft.SemanticKernel.Experimental.Orchestration.Abstractions; + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// The flow validator +/// +public class FlowValidator : IFlowValidator +{ + /// + public void Validate(Flow flow) + { + Verify.NotNullOrWhiteSpace(flow.Goal, nameof(flow.Goal)); + + this.ValidateNonEmpty(flow); + this.ValidatePartialOrder(flow); + this.ValidateReferenceStep(flow); + this.ValidateStartingMessage(flow); + this.ValidatePassthroughVariables(flow); + } + + private void ValidateStartingMessage(Flow flow) + { + foreach (var step in flow.Steps) + { + if (step.CompletionType is CompletionType.Optional or CompletionType.ZeroOrMore + && string.IsNullOrEmpty(step.StartingMessage)) + { + throw new ArgumentException( + $"Missing starting message for step={step.Goal} with completion type={step.CompletionType}"); + } + } + } + + private void ValidateNonEmpty(Flow flow) + { + if (flow.Steps.Count == 0) + { + throw new ArgumentException("Flow must contain at least one flow step."); + } + } + + private void ValidatePartialOrder(Flow flow) + { + try + { + var sorted = flow.SortSteps(); + } + catch (Exception ex) + { + throw new ArgumentException("Flow steps must be a partial order set.", ex); + } + } + + private void ValidateReferenceStep(Flow flow) + { + var steps = flow.Steps + .Select(step => step as ReferenceFlowStep) + .Where(step => step != null); + + foreach (var step in steps) + { + Verify.NotNullOrWhiteSpace(step!.FlowName); + + if (step.Requires.Any()) + { + throw new ArgumentException("Reference flow step cannot have any direct requirements."); + } + + if (step.Provides.Any()) + { + throw new ArgumentException("Reference flow step cannot have any direct provides."); + } + + if (step.Plugins?.Count != 0) + { + throw new ArgumentException("Reference flow step cannot have any direct plugins."); + } + } + } + + private void ValidatePassthroughVariables(Flow flow) + { + foreach (var step in flow.Steps) + { + if (step.CompletionType != CompletionType.AtLeastOnce + && step.CompletionType != CompletionType.ZeroOrMore + && step.Passthrough.Any()) + { + throw new ArgumentException( + $"step={step.Goal} with completion type={step.CompletionType} cannot have passthrough variables as that is only applicable for the AtLeastOnce or ZeroOrMore completion types"); + } + } + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Model/CompletionType.cs b/dotnet/src/Experimental/Orchestration.Flow/Model/CompletionType.cs new file mode 100644 index 0000000000..e38848c2cc --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Model/CompletionType.cs @@ -0,0 +1,31 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// The completion type of step +/// +public enum CompletionType +{ + /// + /// Once + /// + Once, + + /// + /// Optional + /// + Optional, + + /// + /// At least once + /// + AtLeastOnce, + + /// + /// Optional or multiple times + /// + ZeroOrMore, +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Model/Flow.cs b/dotnet/src/Experimental/Orchestration.Flow/Model/Flow.cs new file mode 100644 index 0000000000..177a6cec85 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Model/Flow.cs @@ -0,0 +1,85 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; +using System.Linq; + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// Flow data model +/// +/// +/// Principles: +/// 1. The model should be decoupled from execution status +/// 2. The model is mutable to allow dynamic changes +/// 3. The model doesn't enforce any execution order as long as the dependencies are satisfied +/// +public sealed class Flow : FlowStep +{ + private List _steps; + + /// + /// Initializes a new instance of the class. + /// + /// The name of flow + /// The goal of flow + public Flow(string name, string goal) : base(goal, null) + { + this.Name = name; + this._steps = new List(); + } + + /// + /// Steps of the flow + /// + public List Steps + { + get => this._steps; + set => this._steps = value; + } + + /// + /// Friendly name and identifier of the flow + /// + public string Name { get; set; } + + /// + /// Adds a step to the flow + /// + /// the instance + public void AddStep(FlowStep step) + { + this._steps.Add(step); + } + + /// + /// Adds steps to the flow + /// + /// the array of instance to be add + public void AddSteps(params FlowStep[] steps) + { + this._steps.AddRange(steps); + } + + /// + public override IEnumerable Requires + { + get + { + var requires = new List(); + foreach (var step in this._steps) + { + requires.AddRange(step.Requires); + } + + foreach (var step in this._steps) + { + requires.RemoveAll(r => step.Provides.Contains(r)); + } + + return requires; + } + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Model/FlowStep.cs b/dotnet/src/Experimental/Orchestration.Flow/Model/FlowStep.cs new file mode 100644 index 0000000000..703a74c769 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Model/FlowStep.cs @@ -0,0 +1,236 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Microsoft.SemanticKernel.Experimental.Orchestration.Execution; + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// Step within a which defines the step goal, available plugins, required and provided variables. +/// +public class FlowStep +{ + private readonly List _requires = new(); + + private readonly List _provides = new(); + + private readonly List _passthrough = new(); + + private Dictionary _pluginTypes = new(); + + private Func, IEnumerable>? _pluginsFactory; + + /// + /// Initializes a new instance of the class. + /// + /// The goal of step + /// The factory to get plugins + public FlowStep(string goal, Func, IEnumerable>? pluginsFactory = null) + { + this.Goal = goal; + this._pluginsFactory = pluginsFactory; + } + + /// + /// Goal of the step + /// + public string Goal { get; set; } + + /// + /// of the step + /// + public CompletionType CompletionType { get; set; } = CompletionType.Once; + + /// + /// If the CompletionType is CompletionType.ZeroOrMore, this message will be used to ask the user if they want to execute the current step or skip it. + /// + public string? StartingMessage { get; set; } + + /// + /// If the CompletionType is CompletionType.AtLeastOnce or CompletionType.ZeroOrMore, this message will be used to ask the user if they want to try the step again. + /// + public string? TransitionMessage { get; set; } = "Did you want to try the previous step again?"; + + /// + /// Parameters required for executing the step + /// + public virtual IEnumerable Requires => this._requires; + + /// + /// Variables to be provided by the step + /// + public IEnumerable Provides => this._provides; + + /// + /// Variables to be passed through on iterations of the step + /// + public IEnumerable Passthrough => this._passthrough; + + /// + /// Gets or sets the plugin available for the current step + /// + public List? Plugins + { + get => this._pluginTypes.Keys.ToList(); + set + { + Dictionary plugins = GetPluginTypes(value); + + this._pluginTypes = plugins; + this._pluginsFactory = (kernel, globalPlugins) => this.GetPlugins(globalPlugins, kernel); + } + } + + private List GetPlugins(Dictionary globalPlugins, IKernel kernel) + { + return this._pluginTypes.Select(kvp => + { + var pluginName = kvp.Key; + var globalPlugin = globalPlugins.FirstOrDefault(_ => _.Key.GetType().Name.Contains(pluginName)).Key; + if (globalPlugin != null) + { + return globalPlugin; + } + + var type = kvp.Value; + if (type != null) + { + try + { + return Activator.CreateInstance(type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { kernel }, null); + } + catch (MissingMethodException) + { + try + { + return Activator.CreateInstance(type, true); + } + catch (MissingMethodException) + { + } + } + } + + return null; + }).Where(plugin => plugin != null).ToList()!; + } + + private static Dictionary GetPluginTypes(List? value) + { + Dictionary plugins = new(); + + if (value is not null) + { + var types = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !a.IsDynamic) + .SelectMany(a => a.GetTypes()) + .ToList(); + + foreach (var pluginName in value) + { + if (pluginName is null) + { + continue; + } + + var type = types.FirstOrDefault(predicate: t => t.FullName?.Equals(pluginName, StringComparison.OrdinalIgnoreCase) ?? false); + if (type is null) + { + type = types.FirstOrDefault(t => t.FullName?.Contains(pluginName) ?? false); + + if (type is null) + { + // If not found, assume the plugin would be loaded separately. + plugins.Add(pluginName, null); + continue; + } + } + + plugins.Add(pluginName, type); + } + } + + return plugins; + } + + /// + /// Register the required arguments for the step + /// + /// Array of required arguments + public void AddRequires(params string[] requiredArguments) + { + this.ValidateArguments(requiredArguments); + this._requires.AddRange(requiredArguments); + } + + /// + /// Register the arguments provided by the step + /// + /// Array of provided arguments + public void AddProvides(params string[] providedArguments) + { + this.ValidateArguments(providedArguments); + this._provides.AddRange(providedArguments); + } + + /// + /// Register the arguments passed through by the step + /// + /// Array of passthrough arguments + /// Is referenced flow + public void AddPassthrough(string[] passthroughArguments, bool isReferencedFlow = false) + { + // A referenced flow is allowed to have steps that have passthrough arguments even if the completion type is not AtLeastOnce or ZeroOrMore. This is so the step can pass arguments to the outer flow. + if (!isReferencedFlow + && passthroughArguments.Length != 0 + && this.CompletionType != CompletionType.AtLeastOnce + && this.CompletionType != CompletionType.ZeroOrMore) + { + throw new ArgumentException("Passthrough arguments can only be set for the AtLeastOnce or ZeroOrMore completion type"); + } + + this.ValidateArguments(passthroughArguments); + this._passthrough.AddRange(passthroughArguments); + } + + /// + /// Get the plugin instances registered with the step + /// + /// The semantic kernel + /// The global plugins available + /// + public IEnumerable LoadPlugins(IKernel kernel, Dictionary globalPlugins) + { + if (this._pluginsFactory != null) + { + return this._pluginsFactory(kernel, globalPlugins); + } + + return Enumerable.Empty(); + } + + /// + /// Check if the step depends on another step + /// + /// The other step + /// true if the step depends on the other step, false otherwise + public bool DependsOn(FlowStep otherStep) + { + return this.Requires.Intersect(otherStep.Provides).Any(); + } + + private void ValidateArguments(string[] arguments) + { + var invalidArguments = arguments.Intersect(Constants.ActionVariableNames.All).ToArray(); + + if (invalidArguments.Length != 0) + { + throw new ArgumentException($"Invalid arguments: {string.Join(",", invalidArguments)}"); + } + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Model/ReferenceFlowStep.cs b/dotnet/src/Experimental/Orchestration.Flow/Model/ReferenceFlowStep.cs new file mode 100644 index 0000000000..055c5c8b32 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Model/ReferenceFlowStep.cs @@ -0,0 +1,32 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +#pragma warning disable IDE0130 +namespace Microsoft.SemanticKernel.Experimental.Orchestration; +#pragma warning restore IDE0130 + +/// +/// The flow step which references another flow. +/// +public sealed class ReferenceFlowStep : FlowStep +{ + /// + /// Initializes a new instance of the class. + /// + /// The name of referenced flow + public ReferenceFlowStep(string flowName) : base(string.Empty) + { + this.FlowName = flowName; + } + + /// + /// Only for deserialization. + /// + public ReferenceFlowStep() : this(string.Empty) + { + } + + /// + /// Name of reference . + /// + public string FlowName { get; set; } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckRepeatStep/config.json b/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckRepeatStep/config.json new file mode 100644 index 0000000000..f92c8a1a96 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckRepeatStep/config.json @@ -0,0 +1,32 @@ +{ + "schema": 1, + "description": "Given the chat history, determine if user would like to execute the previous task for one more time. If not concluded, generate the next message for follow up.", + "type": "completion", + "completion": { + "max_tokens": 400, + "temperature": 0, + "top_p": 1, + "presence_penalty": 0, + "frequency_penalty": 0, + "stop_sequences": [ "[RESPONSE]", "[Goal]" ] + }, + "input": { + "parameters": [ + { + "name": "goal", + "description": "The goal of proposed step", + "defaultValue": "" + }, + { + "name": "transitionMessage", + "description": "The transition message", + "defaultValue": "Did you want to try the previous step again?" + }, + { + "name": "agentScratchPad", + "description": "The agent's scratch pad", + "defaultValue": "" + } + ] + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckRepeatStep/skprompt.txt b/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckRepeatStep/skprompt.txt new file mode 100644 index 0000000000..e293d88136 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckRepeatStep/skprompt.txt @@ -0,0 +1,42 @@ +[INSTRUCTION] +Work with user to determine if he or she would like to work on the previous step for one more time. + +[THOUGHT PROCESS] +[Goal] +The goal of proposed step. +[THOUGHT] +To solve this problem, I should carefully analyze the previous question and response to identify if user is willing to repeat the action again. +Any facts I discover earlier in my thought process should be repeated here to keep them readily available. +[QUESTION] +If there is any ambiguity in the chat history, ask the follow up question to the user to get clarification on whether the user wants to repeat the previous step. +The way you will check if the user wants to repeat the step is by asking the question "{{$transitionMessage}}". +IMPORTANT: Do NOT update the wording in the question stated above. If you need clarification, you will ask that question word for word. +If the user says something along the lines of "yes", "sure", "fine", "ok", then they are asking to repeat the step. +[RESPONSE] +The result of the action will be provided here. It could be result or error message of the action, or chat history between assistant and user to tackle the problem. +... (These THOUGHT/QUESTION/RESPONSE can repeat until the final answer is reached.) +[FINAL ANSWER] +Once I have gathered all the necessary observations and can reliably tell if user would like to repeat the step for one more time, output TRUE or FALSE. +[END THOUGHT PROCESS] + +Example: +[Goal] +{{$goal}} +[QUESTION] +{{$transitionMessage}} +[RESPONSE] +yes +[THOUGHT] +Based on the response, the user wants to try the previous step again. +[FINAL ANSWER] +TRUE + +IMPORTANT REMINDER: Your each response MUST contain one of [QUESTION] and [FINAL ANSWER]! +Let's break down the problem step by step and think about the best approach. + +Begin! + +[Goal] +{{$goal}} +{{$agentScratchPad}} +[THOUGHT] \ No newline at end of file diff --git a/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckStartStep/config.json b/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckStartStep/config.json new file mode 100644 index 0000000000..046da6bec2 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckStartStep/config.json @@ -0,0 +1,32 @@ +{ + "schema": 1, + "description": "Given the chat history, determine if user would like to begin executing the current task. If not concluded, generate the next message for follow up.", + "type": "completion", + "completion": { + "max_tokens": 400, + "temperature": 0, + "top_p": 1, + "presence_penalty": 0, + "frequency_penalty": 0, + "stop_sequences": ["[RESPONSE]"] + }, + "input": { + "parameters": [ + { + "name": "goal", + "description": "The goal of proposed step", + "defaultValue": "" + }, + { + "name": "message", + "description": "The message to display to the user", + "defaultValue": "" + }, + { + "name": "agentScratchPad", + "description": "The agent's scratch pad", + "defaultValue": "" + } + ] + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckStartStep/skprompt.txt b/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckStartStep/skprompt.txt new file mode 100644 index 0000000000..fa95c8b962 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Plugins/CheckStartStep/skprompt.txt @@ -0,0 +1,42 @@ +[INSTRUCTION] +Work with user to determine if he or she would like to execute the current step for the first time. + +[THOUGHT PROCESS] +[Goal] +The goal of proposed step. +[THOUGHT] +To solve this problem, I should carefully analyze the question and response to identify if user is willing to begin the current action. +Any facts I discover earlier in my thought process should be repeated here to keep them readily available. +[QUESTION] +If there is any ambiguity in the chat history, ask the follow up question to the user to get clarification on whether the user wants to repeat the previous step. +The way you will check if the user wants to execute the step is by asking the question "{{$message}}". +IMPORTANT: Do NOT update the wording in the question stated above. If you need clarification, you will ask that question word for word. +If the user says something along the lines of "yes", "sure", "fine", "ok", then they are asking to start the step. +[RESPONSE] +The result of the action will be provided here. It could be result or error message of the action, or chat history between assistant and user to tackle the problem. +... (These THOUGHT/QUESTION/RESPONSE can repeat until the final answer is reached.) +[FINAL ANSWER] +Once I have gathered all the necessary observations and can reliably tell if user would like to repeat the step for one more time, output TRUE or FALSE. +[END THOUGHT PROCESS] + +Example: +[Goal] +{{$goal}} +[QUESTION] +{{$message}} +[RESPONSE] +yes +[THOUGHT] +Based on the response, the user wants to execute the current step. +[FINAL ANSWER] +TRUE + +IMPORTANT REMINDER: your each response should contain at most one question. Do not provide more than one step. +Let's break down the problem step by step and think about the best approach. + +Begin! + +[Goal] +{{$goal}} +{{$agentScratchPad}} +[THOUGHT] \ No newline at end of file diff --git a/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/config.json b/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/config.json new file mode 100644 index 0000000000..a0a2bd3738 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/config.json @@ -0,0 +1,32 @@ +{ + "schema": 1, + "description": "Given a request or command or goal generate multi-step plan to reach the goal. After each step LLM is called to perform the reasoning for the next step.", + "type": "completion", + "completion": { + "max_tokens": 400, + "temperature": 0, + "top_p": 0.1, + "presence_penalty": 0, + "frequency_penalty": 0, + "stop_sequences": [ "[OBSERVATION]", "[Observation]", "[QUESTION]"] + }, + "input": { + "parameters": [ + { + "name": "question", + "description": "The question to answer", + "defaultValue": "" + }, + { + "name": "agentScratchPad", + "description": "The agent's scratch pad", + "defaultValue": "" + }, + { + "name": "functionDescriptions", + "description": "The manual of the agent's functions", + "defaultValue": "" + } + ] + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/gpt4/config.json b/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/gpt4/config.json new file mode 100644 index 0000000000..31eab1607d --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/gpt4/config.json @@ -0,0 +1,32 @@ +{ + "schema": 1, + "description": "Given a request or command or goal generate multi-step plan to reach the goal. After each step LLM is called to perform the reasoning for the next step.", + "type": "completion", + "completion": { + "max_tokens": 1024, + "temperature": 0, + "top_p": 1, + "presence_penalty": 0, + "frequency_penalty": 0, + "stop_sequences": ["[OBSERVATION]"] + }, + "input": { + "parameters": [ + { + "name": "question", + "description": "The question to answer", + "defaultValue": "" + }, + { + "name": "agentScratchPad", + "description": "The agent's scratch pad", + "defaultValue": "" + }, + { + "name": "functionDescriptions", + "description": "The manual of the agent's functions", + "defaultValue": "" + } + ] + } +} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/gpt4/skprompt.txt b/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/gpt4/skprompt.txt new file mode 100644 index 0000000000..4bd4b821b9 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/gpt4/skprompt.txt @@ -0,0 +1,55 @@ +[INSTRUCTION] +Answer the following questions as accurately as possible using the provided functions. + +[AVAILABLE FUNCTIONS] +The function definitions below are in the following format: +: + - : + - ... + +{{$functionDescriptions}} +[END AVAILABLE FUNCTIONS] + +[USAGE INSTRUCTIONS] +To use the functions, specify a JSON blob representing an action. The JSON blob should contain fully qualified name of the function to use, and an "action_variables" key with a JSON object of string values to use when calling the function. +Do not call functions directly; they must be invoked through an action. +The "action_variables" values should match the defined [PARAMETERS] of the named "action" in [AVAILABLE FUNCTIONS]. +Dictionary values in "action_variables" must be strings and represent the actual values to be passed to the function. +Ensure that the $JSON_BLOB contains only a SINGLE action; do NOT return multiple actions. +IMPORTANT: Use only the available functions listed in the [AVAILABLE FUNCTIONS] section. Do not attempt to use any other functions that are not specified. +The value of parameters should either by empty if the expectation is for the user to provide them and have not been provided yet, or derived from the agent scratchpad. +You are not allowed to ask user directly for more information. + +Here is an example of a valid $JSON_BLOB: +{ + "action": "FUNCTION.NAME", + "action_variables": {"INPUT": "some input", "PARAMETER_NAME": "some value", "PARAMETER_NAME_2": "42"} +} +[END USAGE INSTRUCTIONS] +[END INSTRUCTION] + +[THOUGHT PROCESS] +[QUESTION] +The input question I must answer +[THOUGHT] +To solve this problem, I should carefully analyze the given question and identify the necessary steps. Any facts I discover earlier in my thought process should be repeated here to keep them readily available. +If there is function which can be leveraged for validation, use it in ACTION before jumping into FINAL ANSWER. +[ACTION] +$JSON_BLOB +[OBSERVATION] +The result of the action will be provided here. It could be result or error message of the action, or chat history between assistant and user to tackle the problem. +... (These THOUGHT/ACTION/OBSERVATION can repeat until the final answer is reached.) +[FINAL ANSWER] +Once I have gathered all the necessary observations and performed any required actions, if there is a suitable function for validation, provide the final answer in JSON in the following format: +{ "action": "$(last_action_name)", "action_variables": {"INPUT": "some input", "PARAMETER_NAME": "some value", "PARAMETER_NAME_2": "42"}} +If there is not a fitting function available to validate the result, I can provide the final answer in a clear and human-readable format. +[END THOUGHT PROCESS] + +IMOPRTANT REMINDER: your each response should contain only one next step and only single one $JSON_BLOB. Do not provide more than one step. +Let's break down the problem step by step and think about the best approach. + +Begin! + +[Question] +{{$question}} +{{$agentScratchPad}} diff --git a/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/skprompt.txt b/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/skprompt.txt new file mode 100644 index 0000000000..eff7607278 --- /dev/null +++ b/dotnet/src/Experimental/Orchestration.Flow/Plugins/ReActEngine/skprompt.txt @@ -0,0 +1,78 @@ +[INSTRUCTION] +Answer the following questions as accurately as possible using the provided functions. + +[AVAILABLE FUNCTIONS] +The function definitions below are in the following format: +: + - : + - ... +[END AVAILABLE FUNCTIONS] + +[USAGE INSTRUCTIONS] +To use the functions, specify a JSON blob representing an action. The JSON blob should contain fully qualified name of the function to use, and an "action_variables" key with a JSON object of string values to use when calling the function. +Do not call functions directly; they must be invoked through an action. + +Here is an example of a valid $JSON_BLOB: +``` +{ + "action": "_Namespace_.FUNCTION.NAME", + "action_variables": {"PARAMETER_NAME_1": "some value", "PARAMETER_NAME_2": "42"} +} +``` +The keys of "action_variables" should match the defined [PARAMETERS] of the named "action" in [AVAILABLE FUNCTIONS]. +Dictionary values in "action_variables" must be strings and represent the actual values to be passed to the function. +Ensure that the $JSON_BLOB contains only a SINGLE action; do NOT return multiple actions. +IMPORTANT: +* Use only the available functions listed in the [AVAILABLE FUNCTIONS] section. +* Do not attempt to use any other functions that are not specified. +* The value of parameters should either by empty if the expectation is for the user to provide them and have not been provided yet, or derived from the agent scratchpad. +* You are not allowed to ask user directly for more information. +[END USAGE INSTRUCTIONS] +[END INSTRUCTION] + +[THOUGHT PROCESS] +[QUESTION] +The input question I must answer +[THOUGHT] +To solve this problem, I should carefully analyze the given question and identify the necessary steps. Any facts I discover earlier in my thought process should be repeated here to keep them readily available. +If there is function which can be leveraged for validation, use it in ACTION before jumping into FINAL ANSWER. +[ACTION] +$JSON_BLOB +[OBSERVATION] +The result of the action will be provided here. It could be result or error message of the action, or chat history between assistant and user to tackle the problem. +... (These THOUGHT/ACTION/OBSERVATION can repeat until the final answer is reached.) +[FINAL ANSWER] +Once I have gathered all the necessary observations and performed any required actions, provide the final answer in a clear and human-readable format. +[END THOUGHT PROCESS] + +Example: +[AVAILABLE FUNCTIONS] +AuthorPlugin.WritePoem: useful to write poem given a style and input + - input: input for the poem + - style: style of the poem, leave empty if not specified +[END AVAILABLE FUNCTIONS] +[Question] +Write a poem about sun in Whitman's style. +[THOUGHT] +I should use WritePoem function for it. +[ACTION] +{ + "action": "AuthorPlugin.WritePoem", + "action_variables": { + "input": "sun", + "stype": "Whitman", + } +} + +IMPORTANT REMINDER: your each response should contain only one next step and only single one [ACTION] part. Do not provide more than one step. +Let's break down the problem step by step and think about the best approach. + +Begin! + +[AVAILABLE FUNCTIONS] +{{$functionDescriptions}} +[END AVAILABLE FUNCTIONS] +[Question] +{{$question}} +{{$agentScratchPad}} +[THOUGHT] \ No newline at end of file diff --git a/dotnet/src/Extensions/Extensions.UnitTests/Extensions.UnitTests.csproj b/dotnet/src/Extensions/Extensions.UnitTests/Extensions.UnitTests.csproj index 5724cc90ff..58aed333d3 100644 --- a/dotnet/src/Extensions/Extensions.UnitTests/Extensions.UnitTests.csproj +++ b/dotnet/src/Extensions/Extensions.UnitTests/Extensions.UnitTests.csproj @@ -1,5 +1,4 @@ īģŋ - SemanticKernel.Extensions.UnitTests SemanticKernel.Extensions.UnitTests @@ -11,7 +10,6 @@ false CA2007,VSTHRD111 - @@ -26,11 +24,9 @@ - - - + \ No newline at end of file diff --git a/dotnet/src/InternalUtilities/src/Extensions/DictionaryExtensions.cs b/dotnet/src/InternalUtilities/src/Extensions/DictionaryExtensions.cs new file mode 100644 index 0000000000..1fc442fb48 --- /dev/null +++ b/dotnet/src/InternalUtilities/src/Extensions/DictionaryExtensions.cs @@ -0,0 +1,27 @@ +īģŋ// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Generic; + +/// +/// Dictionary extension methods. +/// +internal static class DictionaryExtensions +{ + /// Gets or adds a value to the dictionary. + /// The type of the name. + /// The type of the value. + /// The dictionary. + /// The name. + /// The value. + /// The final value. + public static TValue? GetOrAdd(this IDictionary dictionary, TKey key, TValue value) + { + if (dictionary.TryGetValue(key, out TValue? foundValue)) + { + return foundValue; + } + + dictionary[key] = value; + return value; + } +} From b3299aa05a34fead64ab24441474dd512955faf2 Mon Sep 17 00:00:00 2001 From: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Date: Mon, 6 Nov 2023 20:40:06 +0000 Subject: [PATCH 006/576] .Net: Version 1.0.0-beta5 (#3395) ### Motivation and Context Update version for release 1.0.0-beta5 ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone :smile: --- dotnet/nuget/nuget-package.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/nuget/nuget-package.props b/dotnet/nuget/nuget-package.props index 1b1145588e..537851767a 100644 --- a/dotnet/nuget/nuget-package.props +++ b/dotnet/nuget/nuget-package.props @@ -1,7 +1,7 @@ - 1.0.0-beta4 + 1.0.0-beta5 Debug;Release;Publish true From 31760c5998a3eab3993756ef162ad3e95b4a9a7a Mon Sep 17 00:00:00 2001 From: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:22:22 +0000 Subject: [PATCH 007/576] Java: Fixed invalid links in documentation (#3397) ### Motivation and Context Updated OpenAI invalid links in Java documentation from `https://openai.com/api/` to `https://openai.com/product/`. ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone :smile: --- java/README.md | 2 +- java/samples/sample-code/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/README.md b/java/README.md index 83f312fb4c..abd935626e 100644 --- a/java/README.md +++ b/java/README.md @@ -13,7 +13,7 @@ and frameworks. ## Get started To run the LLM prompts and semantic functions in this kernel, make sure you have -an [Open AI API Key](https://openai.com/api/) +an [Open AI API Key](https://openai.com/product/) or [Azure Open AI service key](https://learn.microsoft.com/azure/cognitive-services/openai/). ### Requirements diff --git a/java/samples/sample-code/README.md b/java/samples/sample-code/README.md index 56c951268b..ccf92af48a 100644 --- a/java/samples/sample-code/README.md +++ b/java/samples/sample-code/README.md @@ -35,7 +35,7 @@ They can then be run by: # Configuration You can define the provider of Open AI by setting the `OPENAI_CLIENT_TYPE` -property or environment variable to either [`OPENAI`](https://openai.com/api/) +property or environment variable to either [`OPENAI`](https://openai.com/product/) or [`AZURE_OPEN_AI`](https://learn.microsoft.com/azure/cognitive-services/openai/). By default, the samples will use the Open AI client. From 164a7ec19c8e0ba9dd3550c2a114ca47705f0096 Mon Sep 17 00:00:00 2001 From: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:24:25 +0000 Subject: [PATCH 008/576] .Net: Fix use of InternalsVisibleTo (#3398) ### Motivation and Context Fix release build failure ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone :smile: --- .../Orchestration.Flow/Experimental.Orchestration.Flow.csproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dotnet/src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj b/dotnet/src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj index e5546957d9..e77d18b73b 100644 --- a/dotnet/src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj +++ b/dotnet/src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj @@ -20,9 +20,7 @@ - - <_Parameter1>SemanticKernel.Experimental.Orchestration.Flow.UnitTests - + From 8da1cb7ffc594463c512d98e70edc50a2a308656 Mon Sep 17 00:00:00 2001 From: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com> Date: Tue, 7 Nov 2023 10:20:07 +0000 Subject: [PATCH 009/576] .Net: Renamed Azure* classes and methods to AzureOpenAI* (#3399) ### Motivation and Context Resolves: https://github.com/microsoft/semantic-kernel/issues/3155 This PR contains changes to rename `Azure*` classes and methods to `AzureOpenAI*` to make it clear that they work with OpenAI models. Note: `AzureTextCompletion` class and related extension methods remain the same, as they are marked as obsolete in this PR: https://github.com/microsoft/semantic-kernel/pull/3396 ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone - this is breaking change, as some public classes and methods were renamed. Co-authored-by: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> --- .../ApplicationInsightsExample/Program.cs | 2 +- .../Example12_SequentialPlanner.cs | 10 +++--- .../Example13_ConversationSummaryPlugin.cs | 2 +- .../KernelSyntaxExamples/Example17_ChatGPT.cs | 4 +-- .../KernelSyntaxExamples/Example18_DallE.cs | 2 +- .../KernelSyntaxExamples/Example26_AADAuth.cs | 4 +-- ...Example27_SemanticFunctionsUsingChatGPT.cs | 2 +- .../Example28_ActionPlanner.cs | 2 +- .../Example31_CustomPlanner.cs | 6 ++-- .../Example33_StreamingChat.cs | 4 +-- .../Example36_MultiCompletion.cs | 2 +- .../Example37_MultiStreamingCompletion.cs | 2 +- .../Example42_KernelBuilder.cs | 6 ++-- .../Example44_MultiChatCompletion.cs | 4 +-- .../Example45_MultiStreamingChatCompletion.cs | 4 +-- .../Example48_GroundednessChecks.cs | 4 +-- .../Example51_StepwisePlanner.cs | 2 +- .../Example52_ApimAuth.cs | 2 +- .../Example54_AzureChatCompletionWithData.cs | 10 +++--- ...ateNativeFunctionsWithMultipleArguments.cs | 4 +-- .../Example58_ConfigureRequestSettings.cs | 4 +-- .../Example59_OpenAIFunctionCalling.cs | 2 +- .../Example61_MultipleLLMs.cs | 4 +-- .../Example62_CustomAIServiceSelector.cs | 4 +-- .../Example63_FlowOrchestrator.cs | 2 +- ...letion.cs => AzureOpenAIChatCompletion.cs} | 14 ++++---- ...s => AzureOpenAIChatCompletionWithData.cs} | 14 ++++---- ...zureOpenAIChatCompletionWithDataConfig.cs} | 2 +- .../AzureOpenAIImageGeneration.cs | 18 +++++----- ... => AzureOpenAIImageGenerationResponse.cs} | 2 +- ....cs => AzureOpenAIImageOperationStatus.cs} | 4 +-- .../OpenAIKernelBuilderExtensions.cs | 36 +++++++++---------- .../OpenAIMemoryBuilderExtensions.cs | 8 ++--- ... => AzureOpenAITextEmbeddingGeneration.cs} | 10 +++--- .../TextEmbedding/TextEmbeddingRequest.cs | 2 +- .../PineconeKernelBuilderExtensionsTests.cs | 2 +- .../QdrantKernelBuilderExtensionsTests.cs | 2 +- .../WeaviateKernelBuilderExtensionsTests.cs | 2 +- .../OpenAI/AIServicesOpenAIExtensionsTests.cs | 12 +++---- ...AzureOpenAIChatCompletionWithDataTests.cs} | 16 ++++----- .../FlowOrchestratorTests.cs | 2 +- .../OpenAI/AzureOpenAICompletionTests.cs | 4 +-- .../OpenAI/OpenAICompletionTests.cs | 2 +- .../OpenAI/OpenAITextEmbeddingTests.cs | 2 +- .../IntegrationTests/Planners/PlanTests.cs | 4 +-- .../SequentialPlannerTests.cs | 4 +-- .../StepwisePlanner/StepwisePlannerTests.cs | 4 +-- 47 files changed, 130 insertions(+), 130 deletions(-) rename dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletion/{AzureChatCompletion.cs => AzureOpenAIChatCompletion.cs} (89%) rename dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/{AzureChatCompletionWithData.cs => AzureOpenAIChatCompletionWithData.cs} (95%) rename dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/{AzureChatCompletionWithDataConfig.cs => AzureOpenAIChatCompletionWithDataConfig.cs} (97%) rename dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/{AzureImageGenerationResponse.cs => AzureOpenAIImageGenerationResponse.cs} (95%) rename dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/{AzureImageOperationStatus.cs => AzureOpenAIImageOperationStatus.cs} (90%) rename dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/{AzureTextEmbeddingGeneration.cs => AzureOpenAITextEmbeddingGeneration.cs} (88%) rename dotnet/src/Connectors/Connectors.UnitTests/OpenAI/ChatCompletionWithData/{AzureChatCompletionWithDataTests.cs => AzureOpenAIChatCompletionWithDataTests.cs} (83%) diff --git a/dotnet/samples/ApplicationInsightsExample/Program.cs b/dotnet/samples/ApplicationInsightsExample/Program.cs index 0432ef34cb..9df95a0ccc 100644 --- a/dotnet/samples/ApplicationInsightsExample/Program.cs +++ b/dotnet/samples/ApplicationInsightsExample/Program.cs @@ -112,7 +112,7 @@ public sealed class Program var kernel = new KernelBuilder() .WithLoggerFactory(loggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( Env.Var("AzureOpenAI__ChatDeploymentName"), Env.Var("AzureOpenAI__Endpoint"), Env.Var("AzureOpenAI__ApiKey")) diff --git a/dotnet/samples/KernelSyntaxExamples/Example12_SequentialPlanner.cs b/dotnet/samples/KernelSyntaxExamples/Example12_SequentialPlanner.cs index d74748c38b..d72b9e5f34 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example12_SequentialPlanner.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example12_SequentialPlanner.cs @@ -73,7 +73,7 @@ internal static class Example12_SequentialPlanner Console.WriteLine("======== Sequential Planner - Create and Execute Poetry Plan ========"); var kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) @@ -265,7 +265,7 @@ internal static class Example12_SequentialPlanner { var kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) @@ -282,11 +282,11 @@ internal static class Example12_SequentialPlanner // use these to generate and store embeddings for the function descriptions. var kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) - .WithAzureTextEmbeddingGenerationService( + .WithAzureOpenAITextEmbeddingGenerationService( TestConfiguration.AzureOpenAIEmbeddings.DeploymentName, TestConfiguration.AzureOpenAIEmbeddings.Endpoint, TestConfiguration.AzureOpenAIEmbeddings.ApiKey) @@ -299,7 +299,7 @@ internal static class Example12_SequentialPlanner { var memoryStorage = new VolatileMemoryStore(); - var textEmbeddingGenerator = new AzureTextEmbeddingGeneration( + var textEmbeddingGenerator = new AzureOpenAITextEmbeddingGeneration( modelId: TestConfiguration.AzureOpenAIEmbeddings.DeploymentName, endpoint: TestConfiguration.AzureOpenAIEmbeddings.Endpoint, apiKey: TestConfiguration.AzureOpenAIEmbeddings.ApiKey); diff --git a/dotnet/samples/KernelSyntaxExamples/Example13_ConversationSummaryPlugin.cs b/dotnet/samples/KernelSyntaxExamples/Example13_ConversationSummaryPlugin.cs index 7dc25a40f9..3877065f80 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example13_ConversationSummaryPlugin.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example13_ConversationSummaryPlugin.cs @@ -179,7 +179,7 @@ Jane: Goodbye! { IKernel kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) diff --git a/dotnet/samples/KernelSyntaxExamples/Example17_ChatGPT.cs b/dotnet/samples/KernelSyntaxExamples/Example17_ChatGPT.cs index b583f9f858..a08e309f6f 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example17_ChatGPT.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example17_ChatGPT.cs @@ -59,12 +59,12 @@ public static class Example17_ChatGPT { Console.WriteLine("======== Azure Open AI - ChatGPT ========"); - AzureChatCompletion azureChatCompletion = new( + AzureOpenAIChatCompletion azureOpenAIChatCompletion = new( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey); - await StartChatAsync(azureChatCompletion); + await StartChatAsync(azureOpenAIChatCompletion); } private static async Task StartChatAsync(IChatCompletion chatGPT) diff --git a/dotnet/samples/KernelSyntaxExamples/Example18_DallE.cs b/dotnet/samples/KernelSyntaxExamples/Example18_DallE.cs index 26bf8c1196..058f9bc1cf 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example18_DallE.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example18_DallE.cs @@ -99,7 +99,7 @@ public static class Example18_DallE // Add your image generation service .WithAzureOpenAIImageGenerationService(TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) // Add your chat completion service - .WithAzureChatCompletionService(TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) + .WithAzureOpenAIChatCompletionService(TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) .Build(); IImageGeneration dallE = kernel.GetService(); diff --git a/dotnet/samples/KernelSyntaxExamples/Example26_AADAuth.cs b/dotnet/samples/KernelSyntaxExamples/Example26_AADAuth.cs index 3bd2c22d44..bbc5763d00 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example26_AADAuth.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example26_AADAuth.cs @@ -44,8 +44,8 @@ public static class Example26_AADAuth IKernel kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - // Add Azure chat completion service using DefaultAzureCredential AAD auth - .WithAzureChatCompletionService( + // Add Azure OpenAI chat completion service using DefaultAzureCredential AAD auth + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, new DefaultAzureCredential(authOptions)) diff --git a/dotnet/samples/KernelSyntaxExamples/Example27_SemanticFunctionsUsingChatGPT.cs b/dotnet/samples/KernelSyntaxExamples/Example27_SemanticFunctionsUsingChatGPT.cs index 5d8bda833f..263704b92f 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example27_SemanticFunctionsUsingChatGPT.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example27_SemanticFunctionsUsingChatGPT.cs @@ -17,7 +17,7 @@ public static class Example27_SemanticFunctionsUsingChatGPT IKernel kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService(TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) + .WithAzureOpenAIChatCompletionService(TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) .Build(); var func = kernel.CreateSemanticFunction( diff --git a/dotnet/samples/KernelSyntaxExamples/Example28_ActionPlanner.cs b/dotnet/samples/KernelSyntaxExamples/Example28_ActionPlanner.cs index 2944164eb1..b00b388e29 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example28_ActionPlanner.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example28_ActionPlanner.cs @@ -14,7 +14,7 @@ public static class Example28_ActionPlanner Console.WriteLine("======== Action Planner ========"); var kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) diff --git a/dotnet/samples/KernelSyntaxExamples/Example31_CustomPlanner.cs b/dotnet/samples/KernelSyntaxExamples/Example31_CustomPlanner.cs index 8dd94d0786..06b01baed0 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example31_CustomPlanner.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example31_CustomPlanner.cs @@ -131,11 +131,11 @@ internal static class Example31_CustomPlanner { return new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) - .WithAzureTextEmbeddingGenerationService( + .WithAzureOpenAITextEmbeddingGenerationService( TestConfiguration.AzureOpenAIEmbeddings.DeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) @@ -146,7 +146,7 @@ internal static class Example31_CustomPlanner { return new MemoryBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureTextEmbeddingGenerationService( + .WithAzureOpenAITextEmbeddingGenerationService( TestConfiguration.AzureOpenAIEmbeddings.DeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) diff --git a/dotnet/samples/KernelSyntaxExamples/Example33_StreamingChat.cs b/dotnet/samples/KernelSyntaxExamples/Example33_StreamingChat.cs index c577838105..ede79b94ae 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example33_StreamingChat.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example33_StreamingChat.cs @@ -31,12 +31,12 @@ public static class Example33_StreamingChat { Console.WriteLine("======== Azure Open AI - ChatGPT Streaming ========"); - AzureChatCompletion azureChatCompletion = new( + AzureOpenAIChatCompletion azureOpenAIChatCompletion = new( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey); - await StartStreamingChatAsync(azureChatCompletion); + await StartStreamingChatAsync(azureOpenAIChatCompletion); } private static async Task StartStreamingChatAsync(IChatCompletion chatCompletion) diff --git a/dotnet/samples/KernelSyntaxExamples/Example36_MultiCompletion.cs b/dotnet/samples/KernelSyntaxExamples/Example36_MultiCompletion.cs index 8fdeca2feb..50a5b795f6 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example36_MultiCompletion.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example36_MultiCompletion.cs @@ -22,7 +22,7 @@ public static class Example36_MultiCompletion { Console.WriteLine("======== Azure OpenAI - Multiple Chat Completion ========"); - var chatCompletion = new AzureChatCompletion( + var chatCompletion = new AzureOpenAIChatCompletion( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey); diff --git a/dotnet/samples/KernelSyntaxExamples/Example37_MultiStreamingCompletion.cs b/dotnet/samples/KernelSyntaxExamples/Example37_MultiStreamingCompletion.cs index 4cb9e4b0d4..69687824f4 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example37_MultiStreamingCompletion.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example37_MultiStreamingCompletion.cs @@ -22,7 +22,7 @@ public static class Example37_MultiStreamingCompletion { Console.WriteLine("======== Azure OpenAI - Multiple Chat Completion - Raw Streaming ========"); - var chatCompletion = new AzureChatCompletion( + var chatCompletion = new AzureOpenAIChatCompletion( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey); diff --git a/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs b/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs index 868de3b2a6..9ca201e6f3 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example42_KernelBuilder.cs @@ -72,7 +72,7 @@ public static class Example42_KernelBuilder // Manually setup all the dependencies to be used by the kernel var loggerFactory = NullLoggerFactory.Instance; var memoryStorage = new VolatileMemoryStore(); - var textEmbeddingGenerator = new AzureTextEmbeddingGeneration( + var textEmbeddingGenerator = new AzureOpenAITextEmbeddingGeneration( modelId: azureOpenAIEmbeddingDeployment, endpoint: azureOpenAIEndpoint, apiKey: azureOpenAIKey, @@ -87,7 +87,7 @@ public static class Example42_KernelBuilder using var httpHandler = httpHandlerFactory.Create(loggerFactory); using var httpClient = new HttpClient(httpHandler); var aiServices = new AIServiceCollection(); - ITextCompletion Factory() => new AzureChatCompletion( + ITextCompletion Factory() => new AzureOpenAIChatCompletion( modelId: azureOpenAIChatCompletionDeployment, endpoint: azureOpenAIEndpoint, apiKey: azureOpenAIKey, @@ -107,7 +107,7 @@ public static class Example42_KernelBuilder // The AI services are defined with the builder var kernel7 = new KernelBuilder() - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( deploymentName: azureOpenAIChatCompletionDeployment, endpoint: azureOpenAIEndpoint, apiKey: azureOpenAIKey, diff --git a/dotnet/samples/KernelSyntaxExamples/Example44_MultiChatCompletion.cs b/dotnet/samples/KernelSyntaxExamples/Example44_MultiChatCompletion.cs index f31482ebb6..ee93c79770 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example44_MultiChatCompletion.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example44_MultiChatCompletion.cs @@ -23,12 +23,12 @@ public static class Example44_MultiChatCompletion { Console.WriteLine("======== Azure OpenAI - Multiple Chat Completion ========"); - AzureChatCompletion azureChatCompletion = new( + AzureOpenAIChatCompletion azureOpenAIChatCompletion = new( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey); - await RunChatAsync(azureChatCompletion); + await RunChatAsync(azureOpenAIChatCompletion); } private static async Task OpenAIMultiChatCompletionAsync() diff --git a/dotnet/samples/KernelSyntaxExamples/Example45_MultiStreamingChatCompletion.cs b/dotnet/samples/KernelSyntaxExamples/Example45_MultiStreamingChatCompletion.cs index c9c4611231..7a9376cc57 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example45_MultiStreamingChatCompletion.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example45_MultiStreamingChatCompletion.cs @@ -27,12 +27,12 @@ public static class Example45_MultiStreamingChatCompletion { Console.WriteLine("======== Azure OpenAI - Multiple Chat Completion - Raw Streaming ========"); - AzureChatCompletion azureChatCompletion = new( + AzureOpenAIChatCompletion azureOpenAIChatCompletion = new( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey); - await StreamingChatCompletionAsync(azureChatCompletion); + await StreamingChatCompletionAsync(azureOpenAIChatCompletion); } private static async Task OpenAIMultiStreamingChatCompletionAsync() diff --git a/dotnet/samples/KernelSyntaxExamples/Example48_GroundednessChecks.cs b/dotnet/samples/KernelSyntaxExamples/Example48_GroundednessChecks.cs index 80603a5d2f..99788133dd 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example48_GroundednessChecks.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example48_GroundednessChecks.cs @@ -59,7 +59,7 @@ after this event Caroline became his wife."""; Console.WriteLine("======== Groundedness Checks ========"); var kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) @@ -124,7 +124,7 @@ which are not grounded in the original. var kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey) diff --git a/dotnet/samples/KernelSyntaxExamples/Example51_StepwisePlanner.cs b/dotnet/samples/KernelSyntaxExamples/Example51_StepwisePlanner.cs index c4e3b199e8..51a9186d08 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example51_StepwisePlanner.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example51_StepwisePlanner.cs @@ -202,7 +202,7 @@ public static class Example51_StepwisePlanner var maxTokens = 0; if (useChat) { - builder.WithAzureChatCompletionService( + builder.WithAzureOpenAIChatCompletionService( model ?? ChatModelOverride ?? TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey, diff --git a/dotnet/samples/KernelSyntaxExamples/Example52_ApimAuth.cs b/dotnet/samples/KernelSyntaxExamples/Example52_ApimAuth.cs index 2bc4ecfe8f..9d414c2c59 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example52_ApimAuth.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example52_ApimAuth.cs @@ -62,7 +62,7 @@ public static class Example52_ApimAuth var kernel = new KernelBuilder() .WithLoggerFactory(loggerFactory) .WithAIService(TestConfiguration.AzureOpenAI.ChatDeploymentName, (loggerFactory) => - new AzureChatCompletion(TestConfiguration.AzureOpenAI.ChatDeploymentName, openAIClient, loggerFactory)) + new AzureOpenAIChatCompletion(TestConfiguration.AzureOpenAI.ChatDeploymentName, openAIClient, loggerFactory)) .Build(); // Load semantic plugin defined with prompt templates diff --git a/dotnet/samples/KernelSyntaxExamples/Example54_AzureChatCompletionWithData.cs b/dotnet/samples/KernelSyntaxExamples/Example54_AzureChatCompletionWithData.cs index a28ef71f98..aa705da8a4 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example54_AzureChatCompletionWithData.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example54_AzureChatCompletionWithData.cs @@ -30,7 +30,7 @@ public static class Example54_AzureChatCompletionWithData { Console.WriteLine("=== Example with Chat Completion ==="); - var chatCompletion = new AzureChatCompletionWithData(GetCompletionWithDataConfig()); + var chatCompletion = new AzureOpenAIChatCompletionWithData(GetCompletionWithDataConfig()); var chatHistory = chatCompletion.CreateNewChat(); // First question without previous context based on uploaded content. @@ -91,7 +91,7 @@ public static class Example54_AzureChatCompletionWithData var completionWithDataConfig = GetCompletionWithDataConfig(); IKernel kernel = new KernelBuilder() - .WithAzureChatCompletionService(config: completionWithDataConfig) + .WithAzureOpenAIChatCompletionService(config: completionWithDataConfig) .Build(); var semanticFunction = kernel.CreateSemanticFunction("Question: {{$input}}"); @@ -120,11 +120,11 @@ public static class Example54_AzureChatCompletionWithData } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - private static AzureChatCompletionWithDataConfig GetCompletionWithDataConfig() + private static AzureOpenAIChatCompletionWithDataConfig GetCompletionWithDataConfig() { - return new AzureChatCompletionWithDataConfig + return new AzureOpenAIChatCompletionWithDataConfig { CompletionModelId = TestConfiguration.AzureOpenAI.ChatDeploymentName, CompletionEndpoint = TestConfiguration.AzureOpenAI.Endpoint, diff --git a/dotnet/samples/KernelSyntaxExamples/Example56_TemplateNativeFunctionsWithMultipleArguments.cs b/dotnet/samples/KernelSyntaxExamples/Example56_TemplateNativeFunctionsWithMultipleArguments.cs index de40d06b3b..0de886e67e 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example56_TemplateNativeFunctionsWithMultipleArguments.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example56_TemplateNativeFunctionsWithMultipleArguments.cs @@ -27,13 +27,13 @@ public static class Example56_TemplateNativeFunctionsWithMultipleArguments if (serviceId == null || apiKey == null || deploymentName == null || endpoint == null) { - Console.WriteLine("Azure serviceId, endpoint, apiKey, or deploymentName not found. Skipping example."); + Console.WriteLine("AzureOpenAI serviceId, endpoint, apiKey, or deploymentName not found. Skipping example."); return; } IKernel kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( deploymentName: deploymentName, endpoint: endpoint, serviceId: serviceId, diff --git a/dotnet/samples/KernelSyntaxExamples/Example58_ConfigureRequestSettings.cs b/dotnet/samples/KernelSyntaxExamples/Example58_ConfigureRequestSettings.cs index 8afb3b10f4..4024086778 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example58_ConfigureRequestSettings.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example58_ConfigureRequestSettings.cs @@ -25,13 +25,13 @@ public static class Example58_ConfigureRequestSettings if (serviceId == null || apiKey == null || chatDeploymentName == null || endpoint == null) { - Console.WriteLine("Azure serviceId, endpoint, apiKey, or deploymentName not found. Skipping example."); + Console.WriteLine("AzureOpenAI serviceId, endpoint, apiKey, or deploymentName not found. Skipping example."); return; } IKernel kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( deploymentName: chatDeploymentName, endpoint: endpoint, serviceId: serviceId, diff --git a/dotnet/samples/KernelSyntaxExamples/Example59_OpenAIFunctionCalling.cs b/dotnet/samples/KernelSyntaxExamples/Example59_OpenAIFunctionCalling.cs index 89edc73f28..a71dada104 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example59_OpenAIFunctionCalling.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example59_OpenAIFunctionCalling.cs @@ -51,7 +51,7 @@ public static class Example59_OpenAIFunctionCalling IKernel kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) .WithOpenAIChatCompletionService(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey, serviceId: "chat") - //.WithAzureChatCompletionService(TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey, serviceId: "chat") + //.WithAzureOpenAIChatCompletionService(TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey, serviceId: "chat") .Build(); // Load functions to kernel diff --git a/dotnet/samples/KernelSyntaxExamples/Example61_MultipleLLMs.cs b/dotnet/samples/KernelSyntaxExamples/Example61_MultipleLLMs.cs index 66de8ae939..6415d4b62c 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example61_MultipleLLMs.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example61_MultipleLLMs.cs @@ -22,7 +22,7 @@ public static class Example61_MultipleLLMs if (apiKey == null || chatDeploymentName == null || endpoint == null) { - Console.WriteLine("Azure endpoint, apiKey, or deploymentName not found. Skipping example."); + Console.WriteLine("AzureOpenAI endpoint, apiKey, or deploymentName not found. Skipping example."); return; } @@ -37,7 +37,7 @@ public static class Example61_MultipleLLMs IKernel kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( deploymentName: chatDeploymentName, endpoint: endpoint, serviceId: "AzureOpenAIChat", diff --git a/dotnet/samples/KernelSyntaxExamples/Example62_CustomAIServiceSelector.cs b/dotnet/samples/KernelSyntaxExamples/Example62_CustomAIServiceSelector.cs index 74096cd6fd..82ce2a8e65 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example62_CustomAIServiceSelector.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example62_CustomAIServiceSelector.cs @@ -28,7 +28,7 @@ public static class Example62_CustomAIServiceSelector if (apiKey == null || chatDeploymentName == null || endpoint == null) { - Console.WriteLine("Azure endpoint, apiKey, or deploymentName not found. Skipping example."); + Console.WriteLine("AzureOpenAI endpoint, apiKey, or deploymentName not found. Skipping example."); return; } @@ -43,7 +43,7 @@ public static class Example62_CustomAIServiceSelector IKernel kernel = new KernelBuilder() .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( deploymentName: chatDeploymentName, endpoint: endpoint, serviceId: "AzureOpenAIChat", diff --git a/dotnet/samples/KernelSyntaxExamples/Example63_FlowOrchestrator.cs b/dotnet/samples/KernelSyntaxExamples/Example63_FlowOrchestrator.cs index cd6013d808..2062ca3e6c 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example63_FlowOrchestrator.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example63_FlowOrchestrator.cs @@ -207,7 +207,7 @@ provides: var builder = new KernelBuilder(); return builder - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( TestConfiguration.AzureOpenAI.ChatDeploymentName, TestConfiguration.AzureOpenAI.Endpoint, TestConfiguration.AzureOpenAI.ApiKey, diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletion/AzureChatCompletion.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletion/AzureOpenAIChatCompletion.cs similarity index 89% rename from dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletion/AzureChatCompletion.cs rename to dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletion/AzureOpenAIChatCompletion.cs index dc4d7ed845..e79e226ab1 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletion/AzureChatCompletion.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletion/AzureOpenAIChatCompletion.cs @@ -18,17 +18,17 @@ namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI.ChatCompletion; /// Azure OpenAI chat completion client. /// TODO: forward ETW logging to ILogger, see https://learn.microsoft.com/en-us/dotnet/azure/sdk/logging /// -public sealed class AzureChatCompletion : AzureOpenAIClientBase, IChatCompletion, ITextCompletion +public sealed class AzureOpenAIChatCompletion : AzureOpenAIClientBase, IChatCompletion, ITextCompletion { /// - /// Create an instance of the Azure OpenAI chat completion connector with API key auth + /// Create an instance of the connector with API key auth. /// /// Azure OpenAI model ID or deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource /// Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart /// Azure OpenAI API key, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart /// Custom for HTTP requests. /// The to use for logging. If null, no logging will be performed. - public AzureChatCompletion( + public AzureOpenAIChatCompletion( string modelId, string endpoint, string apiKey, @@ -38,14 +38,14 @@ public sealed class AzureChatCompletion : AzureOpenAIClientBase, IChatCompletion } /// - /// Create an instance of the Azure OpenAI chat completion connector with AAD auth + /// Create an instance of the connector with AAD auth. /// /// Azure OpenAI model ID or deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource /// Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart /// Token credentials, e.g. DefaultAzureCredential, ManagedIdentityCredential, EnvironmentCredential, etc. /// Custom for HTTP requests. /// The to use for logging. If null, no logging will be performed. - public AzureChatCompletion( + public AzureOpenAIChatCompletion( string modelId, string endpoint, TokenCredential credentials, @@ -55,12 +55,12 @@ public sealed class AzureChatCompletion : AzureOpenAIClientBase, IChatCompletion } /// - /// Creates a new AzureChatCompletion client instance using the specified OpenAIClient + /// Creates a new client instance using the specified . /// /// Azure OpenAI model ID or deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource /// Custom . /// The to use for logging. If null, no logging will be performed. - public AzureChatCompletion( + public AzureOpenAIChatCompletion( string modelId, OpenAIClient openAIClient, ILoggerFactory? loggerFactory = null) : base(modelId, openAIClient, loggerFactory) diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureChatCompletionWithData.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithData.cs similarity index 95% rename from dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureChatCompletionWithData.cs rename to dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithData.cs index 6ad5b79901..2c561d3aed 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureChatCompletionWithData.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithData.cs @@ -24,16 +24,16 @@ namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI.ChatCompletionWithData; /// Azure OpenAI Chat Completion with data client. /// More information: /// -public sealed class AzureChatCompletionWithData : IChatCompletion, ITextCompletion +public sealed class AzureOpenAIChatCompletionWithData : IChatCompletion, ITextCompletion { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Instance of class with completion configuration. + /// Instance of class with completion configuration. /// Custom for HTTP requests. /// Instance of to use for logging. - public AzureChatCompletionWithData( - AzureChatCompletionWithDataConfig config, + public AzureOpenAIChatCompletionWithData( + AzureOpenAIChatCompletionWithDataConfig config, HttpClient? httpClient = null, ILoggerFactory? loggerFactory = null) { @@ -117,12 +117,12 @@ public sealed class AzureChatCompletionWithData : IChatCompletion, ITextCompleti private const string DefaultApiVersion = "2023-06-01-preview"; - private readonly AzureChatCompletionWithDataConfig _config; + private readonly AzureOpenAIChatCompletionWithDataConfig _config; private readonly HttpClient _httpClient; private readonly ILogger _logger; - private void ValidateConfig(AzureChatCompletionWithDataConfig config) + private void ValidateConfig(AzureOpenAIChatCompletionWithDataConfig config) { Verify.NotNull(config); diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureChatCompletionWithDataConfig.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithDataConfig.cs similarity index 97% rename from dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureChatCompletionWithDataConfig.cs rename to dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithDataConfig.cs index dc4d58bb50..3f5d67d6fa 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureChatCompletionWithDataConfig.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithDataConfig.cs @@ -6,7 +6,7 @@ namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI.ChatCompletionWithData; /// Required configuration for Azure OpenAI chat completion with data. /// More information: /// -public class AzureChatCompletionWithDataConfig +public class AzureOpenAIChatCompletionWithDataConfig { /// /// Azure OpenAI model ID or deployment name, see diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageGeneration.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageGeneration.cs index b0f110c657..dc167ae052 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageGeneration.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageGeneration.cs @@ -106,12 +106,12 @@ public class AzureOpenAIImageGeneration : OpenAIClientBase, IImageGeneration if (result.Result is null) { - throw new SKException("Azure Image Generation null response"); + throw new SKException("Azure OpenAI Image Generation null response"); } if (result.Result.Images.Count == 0) { - throw new SKException("Azure Image Generation result not found"); + throw new SKException("Azure OpenAI Image Generation result not found"); } return result.Result.Images.First().Url; @@ -141,7 +141,7 @@ public class AzureOpenAIImageGeneration : OpenAIClientBase, IImageGeneration }); var uri = this.GetUri(GenerationImageOperation); - var result = await this.ExecutePostRequestAsync(uri, requestBody, cancellationToken).ConfigureAwait(false); + var result = await this.ExecutePostRequestAsync(uri, requestBody, cancellationToken).ConfigureAwait(false); if (result == null || string.IsNullOrWhiteSpace(result.Id)) { @@ -157,7 +157,7 @@ public class AzureOpenAIImageGeneration : OpenAIClientBase, IImageGeneration /// The operationId that identifies the original image generation request. /// The to monitor for cancellation requests. The default is . /// - private async Task GetImageGenerationResultAsync(string operationId, CancellationToken cancellationToken = default) + private async Task GetImageGenerationResultAsync(string operationId, CancellationToken cancellationToken = default) { var operationLocation = this.GetUri(GetImageOperation, operationId); @@ -172,9 +172,9 @@ public class AzureOpenAIImageGeneration : OpenAIClientBase, IImageGeneration using var response = await this.ExecuteRequestAsync(operationLocation, HttpMethod.Get, null, cancellationToken).ConfigureAwait(false); var responseJson = await response.Content.ReadAsStringWithExceptionMappingAsync().ConfigureAwait(false); - var result = this.JsonDeserialize(responseJson); + var result = this.JsonDeserialize(responseJson); - if (result.Status.Equals(AzureImageOperationStatus.Succeeded, StringComparison.OrdinalIgnoreCase)) + if (result.Status.Equals(AzureOpenAIImageOperationStatus.Succeeded, StringComparison.OrdinalIgnoreCase)) { return result; } @@ -208,9 +208,9 @@ public class AzureOpenAIImageGeneration : OpenAIClientBase, IImageGeneration private bool IsFailedOrCancelled(string status) { - return status.Equals(AzureImageOperationStatus.Failed, StringComparison.OrdinalIgnoreCase) - || status.Equals(AzureImageOperationStatus.Cancelled, StringComparison.OrdinalIgnoreCase) - || status.Equals(AzureImageOperationStatus.Deleted, StringComparison.OrdinalIgnoreCase); + return status.Equals(AzureOpenAIImageOperationStatus.Failed, StringComparison.OrdinalIgnoreCase) + || status.Equals(AzureOpenAIImageOperationStatus.Cancelled, StringComparison.OrdinalIgnoreCase) + || status.Equals(AzureOpenAIImageOperationStatus.Deleted, StringComparison.OrdinalIgnoreCase); } /// Adds headers to use for Azure OpenAI HTTP requests. diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureImageGenerationResponse.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageGenerationResponse.cs similarity index 95% rename from dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureImageGenerationResponse.cs rename to dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageGenerationResponse.cs index 961a5aa361..e22b1e7829 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureImageGenerationResponse.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageGenerationResponse.cs @@ -7,7 +7,7 @@ namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI.ImageGeneration; /// /// Image generation response /// -public class AzureImageGenerationResponse +public class AzureOpenAIImageGenerationResponse { /// /// Image generation result diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureImageOperationStatus.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageOperationStatus.cs similarity index 90% rename from dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureImageOperationStatus.cs rename to dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageOperationStatus.cs index 1abe033b27..4264949856 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureImageOperationStatus.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/ImageGeneration/AzureOpenAIImageOperationStatus.cs @@ -3,10 +3,10 @@ namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI.ImageGeneration; /// -/// Azure image generation response status +/// Azure OpenAI image generation response status /// /// -public static class AzureImageOperationStatus +public static class AzureOpenAIImageOperationStatus { /// /// Image generation Succeeded diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIKernelBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIKernelBuilderExtensions.cs index 8f39afe34b..adb93afed2 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIKernelBuilderExtensions.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIKernelBuilderExtensions.cs @@ -161,7 +161,7 @@ public static class OpenAIKernelBuilderExtensions /// Whether the service should be the default for its type. /// Custom for HTTP requests. /// Self instance - public static KernelBuilder WithAzureTextEmbeddingGenerationService(this KernelBuilder builder, + public static KernelBuilder WithAzureOpenAITextEmbeddingGenerationService(this KernelBuilder builder, string deploymentName, string endpoint, string apiKey, @@ -170,7 +170,7 @@ public static class OpenAIKernelBuilderExtensions HttpClient? httpClient = null) { builder.WithAIService(serviceId, (loggerFactory, httpHandlerFactory) => - new AzureTextEmbeddingGeneration( + new AzureOpenAITextEmbeddingGeneration( deploymentName, endpoint, apiKey, @@ -192,7 +192,7 @@ public static class OpenAIKernelBuilderExtensions /// Whether the service should be the default for its type. /// Custom for HTTP requests. /// Self instance - public static KernelBuilder WithAzureTextEmbeddingGenerationService(this KernelBuilder builder, + public static KernelBuilder WithAzureOpenAITextEmbeddingGenerationService(this KernelBuilder builder, string deploymentName, string endpoint, TokenCredential credential, @@ -201,7 +201,7 @@ public static class OpenAIKernelBuilderExtensions HttpClient? httpClient = null) { builder.WithAIService(serviceId, (loggerFactory, httpHandlerFactory) => - new AzureTextEmbeddingGeneration( + new AzureOpenAITextEmbeddingGeneration( deploymentName, endpoint, credential, @@ -259,7 +259,7 @@ public static class OpenAIKernelBuilderExtensions /// Whether the service should be the default for its type. /// Custom for HTTP requests. /// Self instance - public static KernelBuilder WithAzureChatCompletionService(this KernelBuilder builder, + public static KernelBuilder WithAzureOpenAIChatCompletionService(this KernelBuilder builder, string deploymentName, string endpoint, string apiKey, @@ -268,7 +268,7 @@ public static class OpenAIKernelBuilderExtensions bool setAsDefault = false, HttpClient? httpClient = null) { - AzureChatCompletion Factory(ILoggerFactory loggerFactory, IDelegatingHandlerFactory httpHandlerFactory) + AzureOpenAIChatCompletion Factory(ILoggerFactory loggerFactory, IDelegatingHandlerFactory httpHandlerFactory) { OpenAIClient client = CreateAzureOpenAIClient(loggerFactory, httpHandlerFactory, deploymentName, endpoint, new AzureKeyCredential(apiKey), httpClient); @@ -278,7 +278,7 @@ public static class OpenAIKernelBuilderExtensions builder.WithAIService(serviceId, Factory, setAsDefault); // If the class implements the text completion interface, allow to use it also for semantic functions - if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureChatCompletion))) + if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureOpenAIChatCompletion))) { builder.WithAIService(serviceId, Factory, setAsDefault); } @@ -299,7 +299,7 @@ public static class OpenAIKernelBuilderExtensions /// Whether the service should be the default for its type. /// Custom for HTTP requests. /// Self instance - public static KernelBuilder WithAzureChatCompletionService(this KernelBuilder builder, + public static KernelBuilder WithAzureOpenAIChatCompletionService(this KernelBuilder builder, string deploymentName, string endpoint, TokenCredential credentials, @@ -308,7 +308,7 @@ public static class OpenAIKernelBuilderExtensions bool setAsDefault = false, HttpClient? httpClient = null) { - AzureChatCompletion Factory(ILoggerFactory loggerFactory, IDelegatingHandlerFactory httpHandlerFactory) + AzureOpenAIChatCompletion Factory(ILoggerFactory loggerFactory, IDelegatingHandlerFactory httpHandlerFactory) { OpenAIClient client = CreateAzureOpenAIClient(loggerFactory, httpHandlerFactory, deploymentName, endpoint, credentials, httpClient); @@ -318,7 +318,7 @@ public static class OpenAIKernelBuilderExtensions builder.WithAIService(serviceId, Factory, setAsDefault); // If the class implements the text completion interface, allow to use it also for semantic functions - if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureChatCompletion))) + if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureOpenAIChatCompletion))) { builder.WithAIService(serviceId, Factory, setAsDefault); } @@ -337,21 +337,21 @@ public static class OpenAIKernelBuilderExtensions /// Whether the service should be the default for its type. /// Custom for HTTP requests. /// Self instance - public static KernelBuilder WithAzureChatCompletionService(this KernelBuilder builder, - AzureChatCompletionWithDataConfig config, + public static KernelBuilder WithAzureOpenAIChatCompletionService(this KernelBuilder builder, + AzureOpenAIChatCompletionWithDataConfig config, bool alsoAsTextCompletion = true, string? serviceId = null, bool setAsDefault = false, HttpClient? httpClient = null) { - AzureChatCompletionWithData Factory(ILoggerFactory loggerFactory, IDelegatingHandlerFactory httpHandlerFactory) => new( + AzureOpenAIChatCompletionWithData Factory(ILoggerFactory loggerFactory, IDelegatingHandlerFactory httpHandlerFactory) => new( config, HttpClientProvider.GetHttpClient(httpHandlerFactory, httpClient, loggerFactory), loggerFactory); builder.WithAIService(serviceId, Factory, setAsDefault); - if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureChatCompletionWithData))) + if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureOpenAIChatCompletionWithData))) { builder.WithAIService(serviceId, Factory, setAsDefault); } @@ -410,14 +410,14 @@ public static class OpenAIKernelBuilderExtensions /// A local identifier for the given AI service /// Whether the service should be the default for its type. /// Self instance - public static KernelBuilder WithAzureChatCompletionService(this KernelBuilder builder, + public static KernelBuilder WithAzureOpenAIChatCompletionService(this KernelBuilder builder, string deploymentName, OpenAIClient openAIClient, bool alsoAsTextCompletion = true, string? serviceId = null, bool setAsDefault = false) { - AzureChatCompletion Factory(ILoggerFactory loggerFactory) + AzureOpenAIChatCompletion Factory(ILoggerFactory loggerFactory) { return new(deploymentName, openAIClient, loggerFactory); }; @@ -425,7 +425,7 @@ public static class OpenAIKernelBuilderExtensions builder.WithAIService(serviceId, Factory, setAsDefault); // If the class implements the text completion interface, allow to use it also for semantic functions - if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureChatCompletion))) + if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureOpenAIChatCompletion))) { builder.WithAIService(serviceId, Factory, setAsDefault); } @@ -459,7 +459,7 @@ public static class OpenAIKernelBuilderExtensions builder.WithAIService(serviceId, Factory, setAsDefault); // If the class implements the text completion interface, allow to use it also for semantic functions - if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureChatCompletion))) + if (alsoAsTextCompletion && typeof(ITextCompletion).IsAssignableFrom(typeof(AzureOpenAIChatCompletion))) { builder.WithAIService(serviceId, Factory, setAsDefault); } diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIMemoryBuilderExtensions.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIMemoryBuilderExtensions.cs index 4d351c5d77..f993831b8e 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIMemoryBuilderExtensions.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/OpenAIMemoryBuilderExtensions.cs @@ -24,7 +24,7 @@ public static class OpenAIMemoryBuilderExtensions /// Whether the service should be the default for its type. /// Custom for HTTP requests. /// Self instance - public static MemoryBuilder WithAzureTextEmbeddingGenerationService( + public static MemoryBuilder WithAzureOpenAITextEmbeddingGenerationService( this MemoryBuilder builder, string deploymentName, string endpoint, @@ -34,7 +34,7 @@ public static class OpenAIMemoryBuilderExtensions HttpClient? httpClient = null) { builder.WithTextEmbeddingGeneration((loggerFactory, httpHandlerFactory) => - new AzureTextEmbeddingGeneration( + new AzureOpenAITextEmbeddingGeneration( deploymentName, endpoint, apiKey, @@ -56,7 +56,7 @@ public static class OpenAIMemoryBuilderExtensions /// Whether the service should be the default for its type. /// Custom for HTTP requests. /// Self instance - public static MemoryBuilder WithAzureTextEmbeddingGenerationService( + public static MemoryBuilder WithAzureOpenAITextEmbeddingGenerationService( this MemoryBuilder builder, string deploymentName, string endpoint, @@ -66,7 +66,7 @@ public static class OpenAIMemoryBuilderExtensions HttpClient? httpClient = null) { builder.WithTextEmbeddingGeneration((loggerFactory, httpHandlerFactory) => - new AzureTextEmbeddingGeneration( + new AzureOpenAITextEmbeddingGeneration( deploymentName, endpoint, credential, diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/AzureTextEmbeddingGeneration.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/AzureOpenAITextEmbeddingGeneration.cs similarity index 88% rename from dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/AzureTextEmbeddingGeneration.cs rename to dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/AzureOpenAITextEmbeddingGeneration.cs index ceed977b10..c3ca536c8a 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/AzureTextEmbeddingGeneration.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/AzureOpenAITextEmbeddingGeneration.cs @@ -15,17 +15,17 @@ namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI.TextEmbedding; /// /// Azure OpenAI text embedding service. /// -public sealed class AzureTextEmbeddingGeneration : AzureOpenAIClientBase, ITextEmbeddingGeneration +public sealed class AzureOpenAITextEmbeddingGeneration : AzureOpenAIClientBase, ITextEmbeddingGeneration { /// - /// Creates a new AzureTextCompletion client instance using API Key auth + /// Creates a new client instance using API Key auth. /// /// Azure OpenAI model ID or deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource /// Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart /// Azure OpenAI API key, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart /// Custom for HTTP requests. /// The to use for logging. If null, no logging will be performed. - public AzureTextEmbeddingGeneration( + public AzureOpenAITextEmbeddingGeneration( string modelId, string endpoint, string apiKey, @@ -35,14 +35,14 @@ public sealed class AzureTextEmbeddingGeneration : AzureOpenAIClientBase, ITextE } /// - /// Creates a new AzureTextCompletion client instance supporting AAD auth + /// Creates a new client instance supporting AAD auth. /// /// Azure OpenAI model ID or deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource /// Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart /// Token credentials, e.g. DefaultAzureCredential, ManagedIdentityCredential, EnvironmentCredential, etc. /// Custom for HTTP requests. /// The to use for logging. If null, no logging will be performed. - public AzureTextEmbeddingGeneration( + public AzureOpenAITextEmbeddingGeneration( string modelId, string endpoint, TokenCredential credential, diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/TextEmbeddingRequest.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/TextEmbeddingRequest.cs index 8abff22677..007a1d0e0a 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/TextEmbeddingRequest.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/TextEmbedding/TextEmbeddingRequest.cs @@ -32,6 +32,6 @@ public sealed class OpenAITextEmbeddingRequest : TextEmbeddingRequest /// /// An Azure OpenAI embedding request /// -public sealed class AzureTextEmbeddingRequest : TextEmbeddingRequest +public sealed class AzureOpenAITextEmbeddingRequest : TextEmbeddingRequest { } diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeKernelBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeKernelBuilderExtensionsTests.cs index 4a624fb4ca..079a19bec5 100644 --- a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeKernelBuilderExtensionsTests.cs +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Pinecone/PineconeKernelBuilderExtensionsTests.cs @@ -33,7 +33,7 @@ public sealed class PineconeKernelBuilderExtensionsTests : IDisposable #pragma warning disable CS0618 // This will be removed in a future release. builder.WithPineconeMemoryStore("fake-environment", "fake-api-key", this._httpClient); #pragma warning restore CS0618 // This will be removed in a future release. - builder.WithAzureTextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-test-host/fake-path", "fake -api-key"); + builder.WithAzureOpenAITextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-test-host/fake-path", "fake -api-key"); var kernel = builder.Build(); //This call triggers the internal factory registered by WithPineconeMemoryStore method to create an instance of the PineconeMemoryStore class. //Act diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantKernelBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantKernelBuilderExtensionsTests.cs index e7d1052faa..f286824673 100644 --- a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantKernelBuilderExtensionsTests.cs +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Qdrant/QdrantKernelBuilderExtensionsTests.cs @@ -33,7 +33,7 @@ public sealed class QdrantKernelBuilderExtensionsTests : IDisposable #pragma warning disable CS0618 // This will be removed in a future release. builder.WithQdrantMemoryStore(this._httpClient, 123); #pragma warning restore CS0618 // This will be removed in a future release. - builder.WithAzureTextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-text-embedding-generation-host/fake-path", "fake-api-key"); + builder.WithAzureOpenAITextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-text-embedding-generation-host/fake-path", "fake-api-key"); var kernel = builder.Build(); //This call triggers the internal factory registered by WithQdrantMemoryStore method to create an instance of the QdrantMemoryStore class. //Act diff --git a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateKernelBuilderExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateKernelBuilderExtensionsTests.cs index 0d771ef951..687bc7873c 100644 --- a/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateKernelBuilderExtensionsTests.cs +++ b/dotnet/src/Connectors/Connectors.UnitTests/Memory/Weaviate/WeaviateKernelBuilderExtensionsTests.cs @@ -47,7 +47,7 @@ public sealed class WeaviateKernelBuilderExtensionsTests : IDisposable #pragma warning disable CS0618 // This will be removed in a future release. builder.WithWeaviateMemoryStore(this._httpClient, "https://fake-random-test-weaviate-host", "fake-api-key", apiVersion); #pragma warning restore CS0618 // This will be removed in a future release. - builder.WithAzureTextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-test-host/fake-path", "fake -api-key"); + builder.WithAzureOpenAITextEmbeddingGenerationService("fake-deployment-name", "https://fake-random-test-host/fake-path", "fake -api-key"); var kernel = builder.Build(); //This call triggers the internal factory registered by WithWeaviateMemoryStore method to create an instance of the WeaviateMemoryStore class. //Act diff --git a/dotnet/src/Connectors/Connectors.UnitTests/OpenAI/AIServicesOpenAIExtensionsTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/OpenAI/AIServicesOpenAIExtensionsTests.cs index 8ec0c712ad..aa1455d789 100644 --- a/dotnet/src/Connectors/Connectors.UnitTests/OpenAI/AIServicesOpenAIExtensionsTests.cs +++ b/dotnet/src/Connectors/Connectors.UnitTests/OpenAI/AIServicesOpenAIExtensionsTests.cs @@ -18,7 +18,7 @@ public class AIServicesOpenAIExtensionsTests { KernelBuilder targetBuilder = new(); targetBuilder.WithAzureTextCompletionService("depl", "https://url", "key", "azure"); - targetBuilder.WithAzureTextEmbeddingGenerationService("depl2", "https://url", "key", "azure"); + targetBuilder.WithAzureOpenAITextEmbeddingGenerationService("depl2", "https://url", "key", "azure"); IKernel targetKernel = targetBuilder.Build(); Assert.NotNull(targetKernel.GetService("azure")); @@ -31,7 +31,7 @@ public class AIServicesOpenAIExtensionsTests KernelBuilder targetBuilder = new(); targetBuilder.WithAzureTextCompletionService("depl", "https://url", "key", serviceId: "azure"); targetBuilder.WithOpenAITextCompletionService("model", "apikey", serviceId: "oai"); - targetBuilder.WithAzureTextEmbeddingGenerationService("depl2", "https://url2", "key", serviceId: "azure"); + targetBuilder.WithAzureOpenAITextEmbeddingGenerationService("depl2", "https://url2", "key", serviceId: "azure"); targetBuilder.WithOpenAITextEmbeddingGenerationService("model2", "apikey2", serviceId: "oai2"); // Assert @@ -55,14 +55,14 @@ public class AIServicesOpenAIExtensionsTests targetBuilder.WithOpenAITextCompletionService("model", "key", serviceId: "one"); targetBuilder.WithOpenAITextCompletionService("model", "key", serviceId: "one"); - targetBuilder.WithAzureTextEmbeddingGenerationService("dep", "https://localhost", "key", serviceId: "one"); - targetBuilder.WithAzureTextEmbeddingGenerationService("dep", "https://localhost", "key", serviceId: "one"); + targetBuilder.WithAzureOpenAITextEmbeddingGenerationService("dep", "https://localhost", "key", serviceId: "one"); + targetBuilder.WithAzureOpenAITextEmbeddingGenerationService("dep", "https://localhost", "key", serviceId: "one"); targetBuilder.WithOpenAITextEmbeddingGenerationService("model", "key", serviceId: "one"); targetBuilder.WithOpenAITextEmbeddingGenerationService("model", "key", serviceId: "one"); - targetBuilder.WithAzureChatCompletionService("dep", "https://localhost", "key", serviceId: "one"); - targetBuilder.WithAzureChatCompletionService("dep", "https://localhost", "key", serviceId: "one"); + targetBuilder.WithAzureOpenAIChatCompletionService("dep", "https://localhost", "key", serviceId: "one"); + targetBuilder.WithAzureOpenAIChatCompletionService("dep", "https://localhost", "key", serviceId: "one"); targetBuilder.WithOpenAIChatCompletionService("model", "key", serviceId: "one"); targetBuilder.WithOpenAIChatCompletionService("model", "key", serviceId: "one"); diff --git a/dotnet/src/Connectors/Connectors.UnitTests/OpenAI/ChatCompletionWithData/AzureChatCompletionWithDataTests.cs b/dotnet/src/Connectors/Connectors.UnitTests/OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithDataTests.cs similarity index 83% rename from dotnet/src/Connectors/Connectors.UnitTests/OpenAI/ChatCompletionWithData/AzureChatCompletionWithDataTests.cs rename to dotnet/src/Connectors/Connectors.UnitTests/OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithDataTests.cs index e3cdc12654..f77eac9f2f 100644 --- a/dotnet/src/Connectors/Connectors.UnitTests/OpenAI/ChatCompletionWithData/AzureChatCompletionWithDataTests.cs +++ b/dotnet/src/Connectors/Connectors.UnitTests/OpenAI/ChatCompletionWithData/AzureOpenAIChatCompletionWithDataTests.cs @@ -11,16 +11,16 @@ using Xunit; namespace SemanticKernel.Connectors.UnitTests.OpenAI.ChatCompletionWithData; /// -/// Unit tests for +/// Unit tests for /// -public sealed class AzureChatCompletionWithDataTests : IDisposable +public sealed class AzureOpenAIChatCompletionWithDataTests : IDisposable { - private readonly AzureChatCompletionWithDataConfig _config; + private readonly AzureOpenAIChatCompletionWithDataConfig _config; private readonly HttpMessageHandlerStub _messageHandlerStub; private readonly HttpClient _httpClient; - public AzureChatCompletionWithDataTests() + public AzureOpenAIChatCompletionWithDataTests() { this._config = this.GetConfig(); @@ -33,7 +33,7 @@ public sealed class AzureChatCompletionWithDataTests : IDisposable { // Arrange const string ExpectedUri = "https://fake-completion-endpoint/openai/deployments/fake-completion-model-id/extensions/chat/completions?api-version=fake-api-version"; - var chatCompletion = new AzureChatCompletionWithData(this._config, this._httpClient); + var chatCompletion = new AzureOpenAIChatCompletionWithData(this._config, this._httpClient); // Act await chatCompletion.GetChatCompletionsAsync(new ChatHistory()); @@ -58,7 +58,7 @@ public sealed class AzureChatCompletionWithDataTests : IDisposable var config = this.GetConfig(); config.CompletionApiVersion = string.Empty; - var chatCompletion = new AzureChatCompletionWithData(config, this._httpClient); + var chatCompletion = new AzureOpenAIChatCompletionWithData(config, this._httpClient); // Act await chatCompletion.GetChatCompletionsAsync(new ChatHistory()); @@ -75,9 +75,9 @@ public sealed class AzureChatCompletionWithDataTests : IDisposable this._messageHandlerStub.Dispose(); } - private AzureChatCompletionWithDataConfig GetConfig() + private AzureOpenAIChatCompletionWithDataConfig GetConfig() { - return new AzureChatCompletionWithDataConfig + return new AzureOpenAIChatCompletionWithDataConfig { CompletionModelId = "fake-completion-model-id", CompletionEndpoint = "https://fake-completion-endpoint", diff --git a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/FlowOrchestratorTests.cs b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/FlowOrchestratorTests.cs index f2532a5cb1..089a31cc93 100644 --- a/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/FlowOrchestratorTests.cs +++ b/dotnet/src/Experimental/Orchestration.Flow.IntegrationTests/FlowOrchestratorTests.cs @@ -107,7 +107,7 @@ steps: var builder = new KernelBuilder() .WithLoggerFactory(this._logger) .WithRetryBasic() - .WithAzureChatCompletionService( + .WithAzureOpenAIChatCompletionService( deploymentName: azureOpenAIConfiguration.ChatDeploymentName!, endpoint: azureOpenAIConfiguration.Endpoint, apiKey: azureOpenAIConfiguration.ApiKey, diff --git a/dotnet/src/IntegrationTests/Connectors/OpenAI/AzureOpenAICompletionTests.cs b/dotnet/src/IntegrationTests/Connectors/OpenAI/AzureOpenAICompletionTests.cs index 21eff7a0f2..ae30e1b1bc 100644 --- a/dotnet/src/IntegrationTests/Connectors/OpenAI/AzureOpenAICompletionTests.cs +++ b/dotnet/src/IntegrationTests/Connectors/OpenAI/AzureOpenAICompletionTests.cs @@ -49,7 +49,7 @@ public sealed class AzureOpenAICompletionTests : IDisposable var target = new KernelBuilder() .WithLoggerFactory(this._logger) - .WithAzureChatCompletionService(configuration.ChatDeploymentName!, configuration.Endpoint, configuration.ApiKey) + .WithAzureOpenAIChatCompletionService(configuration.ChatDeploymentName!, configuration.Endpoint, configuration.ApiKey) .WithHttpHandlerFactory(defaultHttpRetryHandlerFactory) .Build(); @@ -78,7 +78,7 @@ public sealed class AzureOpenAICompletionTests : IDisposable var target = new KernelBuilder() .WithLoggerFactory(this._logger) - .WithAzureChatCompletionService(configuration.ChatDeploymentName!, openAIClient) + .WithAzureOpenAIChatCompletionService(configuration.ChatDeploymentName!, openAIClient) .Build(); // Act diff --git a/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAICompletionTests.cs b/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAICompletionTests.cs index b10406b712..6065cef115 100644 --- a/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAICompletionTests.cs +++ b/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAICompletionTests.cs @@ -461,7 +461,7 @@ public sealed class OpenAICompletionTests : IDisposable Assert.NotNull(azureOpenAIConfiguration.Endpoint); Assert.NotNull(azureOpenAIConfiguration.ServiceId); - kernelBuilder.WithAzureChatCompletionService( + kernelBuilder.WithAzureOpenAIChatCompletionService( deploymentName: azureOpenAIConfiguration.ChatDeploymentName, endpoint: azureOpenAIConfiguration.Endpoint, apiKey: azureOpenAIConfiguration.ApiKey, diff --git a/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAITextEmbeddingTests.cs b/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAITextEmbeddingTests.cs index 83fb12cf41..050a89567f 100644 --- a/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAITextEmbeddingTests.cs +++ b/dotnet/src/IntegrationTests/Connectors/OpenAI/OpenAITextEmbeddingTests.cs @@ -58,7 +58,7 @@ public sealed class OpenAITextEmbeddingTests : IDisposable AzureOpenAIConfiguration? azureOpenAIConfiguration = this._configuration.GetSection("AzureOpenAIEmbeddings").Get(); Assert.NotNull(azureOpenAIConfiguration); - var embeddingGenerator = new AzureTextEmbeddingGeneration(azureOpenAIConfiguration.DeploymentName, + var embeddingGenerator = new AzureOpenAITextEmbeddingGeneration(azureOpenAIConfiguration.DeploymentName, azureOpenAIConfiguration.Endpoint, azureOpenAIConfiguration.ApiKey); diff --git a/dotnet/src/IntegrationTests/Planners/PlanTests.cs b/dotnet/src/IntegrationTests/Planners/PlanTests.cs index 4cbd03ab73..b5dbe04f9c 100644 --- a/dotnet/src/IntegrationTests/Planners/PlanTests.cs +++ b/dotnet/src/IntegrationTests/Planners/PlanTests.cs @@ -513,7 +513,7 @@ public sealed class PlanTests : IDisposable if (useChatModel) { - builder.WithAzureChatCompletionService( + builder.WithAzureOpenAIChatCompletionService( deploymentName: azureOpenAIConfiguration.ChatDeploymentName!, endpoint: azureOpenAIConfiguration.Endpoint, apiKey: azureOpenAIConfiguration.ApiKey); @@ -529,7 +529,7 @@ public sealed class PlanTests : IDisposable if (useEmbeddings) { builder - .WithAzureTextEmbeddingGenerationService( + .WithAzureOpenAITextEmbeddingGenerationService( deploymentName: azureOpenAIEmbeddingsConfiguration.DeploymentName, endpoint: azureOpenAIEmbeddingsConfiguration.Endpoint, apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey); diff --git a/dotnet/src/IntegrationTests/Planners/SequentialPlanner/SequentialPlannerTests.cs b/dotnet/src/IntegrationTests/Planners/SequentialPlanner/SequentialPlannerTests.cs index facf6f5cfc..1cd9c65a9d 100644 --- a/dotnet/src/IntegrationTests/Planners/SequentialPlanner/SequentialPlannerTests.cs +++ b/dotnet/src/IntegrationTests/Planners/SequentialPlanner/SequentialPlannerTests.cs @@ -122,7 +122,7 @@ public sealed class SequentialPlannerTests : IDisposable if (useChatModel) { - builder.WithAzureChatCompletionService( + builder.WithAzureOpenAIChatCompletionService( deploymentName: azureOpenAIConfiguration.ChatDeploymentName!, endpoint: azureOpenAIConfiguration.Endpoint, apiKey: azureOpenAIConfiguration.ApiKey); @@ -137,7 +137,7 @@ public sealed class SequentialPlannerTests : IDisposable if (useEmbeddings) { - builder.WithAzureTextEmbeddingGenerationService( + builder.WithAzureOpenAITextEmbeddingGenerationService( deploymentName: azureOpenAIEmbeddingsConfiguration.DeploymentName, endpoint: azureOpenAIEmbeddingsConfiguration.Endpoint, apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey); diff --git a/dotnet/src/IntegrationTests/Planners/StepwisePlanner/StepwisePlannerTests.cs b/dotnet/src/IntegrationTests/Planners/StepwisePlanner/StepwisePlannerTests.cs index 79881ed0e7..8d262e5848 100644 --- a/dotnet/src/IntegrationTests/Planners/StepwisePlanner/StepwisePlannerTests.cs +++ b/dotnet/src/IntegrationTests/Planners/StepwisePlanner/StepwisePlannerTests.cs @@ -153,7 +153,7 @@ public sealed class StepwisePlannerTests : IDisposable if (useChatModel) { - builder.WithAzureChatCompletionService( + builder.WithAzureOpenAIChatCompletionService( deploymentName: azureOpenAIConfiguration.ChatDeploymentName!, endpoint: azureOpenAIConfiguration.Endpoint, apiKey: azureOpenAIConfiguration.ApiKey); @@ -168,7 +168,7 @@ public sealed class StepwisePlannerTests : IDisposable if (useEmbeddings) { - builder.WithAzureTextEmbeddingGenerationService( + builder.WithAzureOpenAITextEmbeddingGenerationService( deploymentName: azureOpenAIEmbeddingsConfiguration.DeploymentName, endpoint: azureOpenAIEmbeddingsConfiguration.Endpoint, apiKey: azureOpenAIEmbeddingsConfiguration.ApiKey); From 730f200f6183ab7934abfe5a7ec641d963a7879d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 15:13:35 +0000 Subject: [PATCH 010/576] .Net: Bump YamlDotNet from 13.1.1 to 13.7.1 in /dotnet (#3404) Bumps [YamlDotNet](https://github.com/aaubry/YamlDotNet) from 13.1.1 to 13.7.1.
Release notes

Sourced from YamlDotNet's releases.

Release 13.7.1

  • Merge pull request #859 from EdwardCooke/ec-858-static-typeresolver-enums
    Special case on statictyperesolver for enums

Release 13.7.0

  • Merge pull request #856 from prochnowc/code-generation-object
    Added support for serialization and deserialization of 'object' to static code generation

  • Merge pull request #839 from stijnherreman/dateonly-timeonly
    Implement DateOnly and TimeOnly converters.

Release 13.5.2

  • Merge pull request #855 from prochnowc/support-collections-with-arrays
    Fix code generation for Dictionary and List which use Array values

Release 13.5.1

  • Merge pull request #853 from prochnowc/static-external-model
    Fix multiple use of YamlSerializableAttribute

Release 13.5.0

  • Merge pull request #852 from prochnowc/static-external-model
    Add support for including types defined in another assembly in static code generation

Release 13.4.0

  • Merge pull request #824 from 64J0/64J0-patch-1
    F# samples

  • Merge pull request #843 from EdwardCooke/ec-785-callbacks
    Added on onserialized/onserializing and ondeserialized/ondeserializing

Release 13.3.1

  • Merge pull request #834 from EdwardCooke/ec-810-nullyamlstreamscalars
    Support null values in YamlScalarNode for YamlStream

  • Merge pull request #835 from EdwardCooke/ec-817-keynotappliedtoquotedscalars
    Set IsKey on quoted scalar keys

  • Merge pull request #836 from EdwardCooke/ec-815-datetimeoffset
    Added a DateTimeOffsetConverter with a sample on usage

  • Merge pull request #837 from EdwardCooke/ec-792-testsinnonenglish
    Fix tests running in cultures using different cultures

  • Merge pull request #841 from EdwardCooke/ec-838-utfcharsets
    Escaped UTF-16/32 with UTF-8 surrogates

Release 13.2.0

  • Merge pull request #821 from rudolfolah/deserialize-generic-objects-error-message-and-sample
    Deserialize generic objects sample

... (truncated)

Commits
  • 8472305 Merge pull request #859 from EdwardCooke/ec-858-static-typeresolver-enums
  • dd3c3b6 Special case on statictyperesolver for enums
  • f45d1f7 Merge pull request #839 from stijnherreman/dateonly-timeonly
  • 81735e6 Merge pull request #856 from prochnowc/code-generation-object
  • 8255d17 Added test for nested untyped deserialization.
  • 63f71e2 Added support for serialization and deserialization of 'object' to static cod...
  • 7dd57d4 Merge pull request #855 from prochnowc/support-collections-with-arrays
  • 1b8d324 Add support for serializing Dictionary<TKey,TValue[]> and List<T[]>
  • 75f4010 Merge pull request #853 from prochnowc/static-external-model
  • d4d2208 Merge branch 'aaubry:master' into static-external-model
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=YamlDotNet&package-manager=nuget&previous-version=13.1.1&new-version=13.7.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 46af37f2c9..35b97063b1 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -59,7 +59,7 @@ - + From aadde96a54047de0e54576b613989cd9bbd75366 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 16:19:08 +0000 Subject: [PATCH 011/576] .Net: Bump xunit from 2.5.3 to 2.6.1 in /dotnet (#3405) Bumps [xunit](https://github.com/xunit/xunit) from 2.5.3 to 2.6.1.
Commits
  • 9f1684f v2.6.1
  • 5d9ef4b Remove unnecessary XUNIT_VALUETASK definition
  • 0266bac Latest assertions
  • fb3c3cf Remove all ValueTask support from assertions
  • 801790c Reconcile AcceptanceTestAssembly and friends with v3
  • f244cc8 More shared assertion tests that shouldn't return ValueTask
  • 262dd72 Shared assertion tests cannot return ValueTask
  • 36bbf77 Bump up to v2.6.1-pre
  • 6a07b95 v2.6.0
  • 5a7297e #2806: Performance improvements in Assert.Equal (v2)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=xunit&package-manager=nuget&previous-version=2.5.3&new-version=2.6.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 35b97063b1..99c17f5e4b 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -38,7 +38,7 @@ - + From 01086140ce48731743ac3c0f08e659d15c93fa3d Mon Sep 17 00:00:00 2001 From: Desmond Howard Date: Tue, 7 Nov 2023 09:09:39 -0800 Subject: [PATCH 012/576] Cleanup ADR folder (#3411) ### Motivation and Context - fixed the duplicated numbering - removed 0016 as it was an older version of 0017 - updated contact aliases to Github usernames - added `contact` field to the templates ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> --- docs/decisions/0004-error-handling.md | 6 +- ...open-api-dynamic-payload-and-namespaces.md | 36 ++- ...08-support-generic-llm-request-settings.md | 57 ++--- ...e-named-args-in-template-function-calls.md | 55 +++-- .../0010-dotnet-project-structure.md | 107 ++++----- .../0012-kernel-service-registration.md | 13 +- .../0014-chat-completion-roles-in-prompt.md | 223 ++++++++++-------- .../0015-completion-service-selection.md | 24 +- .../0016-custom-prompt-template-formats.md | 40 ++-- ...ing.md => 0017-openai-function-calling.md} | 51 ++-- ...emantic-function-multiple-model-support.md | 172 -------------- ...=> 0018-custom-prompt-template-formats.md} | 37 +-- ...mantic-function-multiple-model-support.md} | 51 ++-- docs/decisions/adr-short-template.md | 19 +- docs/decisions/adr-template.md | 58 +++-- 15 files changed, 420 insertions(+), 529 deletions(-) rename docs/decisions/{0010-openai-function-calling.md => 0017-openai-function-calling.md} (61%) delete mode 100644 docs/decisions/0017-semantic-function-multiple-model-support.md rename docs/decisions/{0017-custom-prompt-template-formats.md => 0018-custom-prompt-template-formats.md} (91%) rename docs/decisions/{0016-semantic-function-multiple-model-support.md => 0019-semantic-function-multiple-model-support.md} (83%) diff --git a/docs/decisions/0004-error-handling.md b/docs/decisions/0004-error-handling.md index 74be52a042..3c3f61c648 100644 --- a/docs/decisions/0004-error-handling.md +++ b/docs/decisions/0004-error-handling.md @@ -1,15 +1,17 @@ --- # These are optional elements. Feel free to remove any of them. status: accepted -contact: semenshi +contact: SergeyMenshykh date: 2023-06-23 deciders: shawncal consulted: stephentoub informed: --- + # Error handling improvements ## Disclaimer + This ADR describes problems and their solutions for improving the error handling aspect of SK. It does not address logging, resiliency, or observability aspects. ## Context and Problem Statement @@ -41,4 +43,4 @@ Currently, there are several aspects of error handling in SK that can be enhance - Identify all cases where the original exception is not preserved as an inner exception of the rethrown SK exception, and address them. - Create a new exception HttpOperationException, which includes a StatusCode property, and implement the necessary logic to map the exception from HttpStatusCode, HttpRequestException, or Azure.RequestFailedException. Update existing SK code that interacts with the HTTP stack to throw HttpOperationException in case of a failed HTTP request and assign the original exception as its inner exception. - Modify all SK components that currently store exceptions to SK context to rethrow them instead. -- Simplify the SK critical exception handling functionality by modifying the IsCriticalException extension method to exclude handling of StackOverflowException and OutOfMemoryException exceptions. This is because the former exception is not thrown, so the calling code won't be executed, while the latter exception doesn't necessarily prevent the execution of recovery code. \ No newline at end of file +- Simplify the SK critical exception handling functionality by modifying the IsCriticalException extension method to exclude handling of StackOverflowException and OutOfMemoryException exceptions. This is because the former exception is not thrown, so the calling code won't be executed, while the latter exception doesn't necessarily prevent the execution of recovery code. diff --git a/docs/decisions/0006-open-api-dynamic-payload-and-namespaces.md b/docs/decisions/0006-open-api-dynamic-payload-and-namespaces.md index f7faf5f212..5935d4ce3c 100644 --- a/docs/decisions/0006-open-api-dynamic-payload-and-namespaces.md +++ b/docs/decisions/0006-open-api-dynamic-payload-and-namespaces.md @@ -1,32 +1,39 @@ --- status: accepted -contact: semenshi +contact: SergeyMenshykh date: 2023-08-15 deciders: shawncal consulted: informed: --- + # Dynamic payload building for PUT and POST RestAPI operations and parameter namespacing ## Context and Problem Statement + Currently, the SK OpenAPI does not allow the dynamic creation of payload/body for PUT and POST RestAPI operations, even though all the required metadata is available. One of the reasons the functionality was not fully developed originally, and eventually removed is that JSON payload/body content of PUT and POST RestAPI operations might contain properties with identical names at various levels. It was not clear how to unambiguously resolve their values from the flat list of context variables. Another reason the functionality has not been added yet is that the 'payload' context variable, along with RestAPI operation data contract schema(OpenAPI, JSON schema, Typings?) should have been sufficient for LLM to provide fully fleshed-out JSON payload/body content without the need to build it dynamically. + ## Decision Drivers -* Create a mechanism that enables the dynamic construction of the payload/body for PUT and POST RestAPI operations. -* Develop a mechanism(namespacing) that allows differentiation of payload properties with identical names at various levels for PUT and POST RestAPI operations. -* Aim to minimize breaking changes and maintain backward compatibility of the code as much as possible. + +- Create a mechanism that enables the dynamic construction of the payload/body for PUT and POST RestAPI operations. +- Develop a mechanism(namespacing) that allows differentiation of payload properties with identical names at various levels for PUT and POST RestAPI operations. +- Aim to minimize breaking changes and maintain backward compatibility of the code as much as possible. ## Considered Options -* Enable the dynamic creation of payload and/or namespacing by default. -* Enable the dynamic creation of payload and/or namespacing based on configuration. + +- Enable the dynamic creation of payload and/or namespacing by default. +- Enable the dynamic creation of payload and/or namespacing based on configuration. ## Decision Outcome + Chosen option: "Enable the dynamic creation of payload and/or namespacing based on configuration". This option keeps things compatible, so the change won't affect any SK consumer code. Additionally, it lets SK consumer code easily control both mechanisms, turning them on or off based on the scenario. ## Additional details ### Enabling dynamic creation of payload + In order to enable the dynamic creation of payloads/bodies for PUT and POST RestAPI operations, please set the `EnableDynamicPayload` property of the `OpenApiSkillExecutionParameters` execution parameters to `true` when importing the AI plugin: ```csharp @@ -34,12 +41,13 @@ var plugin = await kernel.ImportPluginFunctionsAsync("", new Uri("", new Uri(""), new OpenApiSkillExecutionParameters(httpClient) { EnablePayloadNamespacing = true }); ``` + Remember that the namespacing mechanism depends on prefixing parameter names with their parent parameter name, separated by dots. So, use the 'namespaced' parameter names when adding arguments for them to the context variables. Let's consider this JSON: ```json -{ - "upn": "", +{ + "upn": "", "receiver": { "upn": "" }, @@ -70,7 +80,9 @@ Remember that the namespacing mechanism depends on prefixing parameter names wit } } ``` + It contains `upn` properties at different levels. The the argument registration for the parameters(property values) will look like: + ```csharp var contextVariables = new ContextVariables(); contextVariables.Set("upn", ""); diff --git a/docs/decisions/0008-support-generic-llm-request-settings.md b/docs/decisions/0008-support-generic-llm-request-settings.md index 43dcafe1f1..6fae2fdf3e 100644 --- a/docs/decisions/0008-support-generic-llm-request-settings.md +++ b/docs/decisions/0008-support-generic-llm-request-settings.md @@ -2,11 +2,12 @@ # These are optional elements. Feel free to remove any of them. status: accepted contact: markwallace-microsoft -date: 2023-=9-15 +date: 2023-9-15 deciders: shawncal -consulted: stoub, lemiller, dmytrostruk -informed: +consulted: stephentoub, lemillermicrosoft, dmytrostruk +informed: --- + # Refactor to support generic LLM request settings ## Context and Problem Statement @@ -25,18 +26,18 @@ Link to issue raised by the implementer of the Oobabooga AI service: -* Good, SK abstractions contain no references to OpenAI specific request settings -* Neutral, because anonymous types can be used which allows a developer to pass in properties that may be supported by multiple AI services e.g., `temperature` or combine properties for different AI services e.g., `max_tokens` (OpenAI) and `max_new_tokens` (Oobabooga). -* Bad, because it's not clear to developers what they should pass when creating a semantic function -* Bad, because it's not clear to implementors of a chat/text completion service what they should accept or how to add service specific properties. -* Bad, there is no compiler type checking for code paths where the dynamic argument has not been resolved which will impact code quality. Type issues manifest as `RuntimeBinderException`'s and may be difficult to troubleshoot. Special care needs to be taken with return types e.g., may be necessary to specify an explicit type rather than just `var` again to avoid errors such as `Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : Cannot apply indexing with [] to an expression of type 'object'` +- Good, SK abstractions contain no references to OpenAI specific request settings +- Neutral, because anonymous types can be used which allows a developer to pass in properties that may be supported by multiple AI services e.g., `temperature` or combine properties for different AI services e.g., `max_tokens` (OpenAI) and `max_new_tokens` (Oobabooga). +- Bad, because it's not clear to developers what they should pass when creating a semantic function +- Bad, because it's not clear to implementors of a chat/text completion service what they should accept or how to add service specific properties. +- Bad, there is no compiler type checking for code paths where the dynamic argument has not been resolved which will impact code quality. Type issues manifest as `RuntimeBinderException`'s and may be difficult to troubleshoot. Special care needs to be taken with return types e.g., may be necessary to specify an explicit type rather than just `var` again to avoid errors such as `Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : Cannot apply indexing with [] to an expression of type 'object'` ### Use `object` to pass request settings @@ -127,11 +128,11 @@ The calling pattern is the same as for the `dynamic` case i.e. use either an ano PR: -* Good, SK abstractions contain no references to OpenAI specific request settings -* Neutral, because anonymous types can be used which allows a developer to pass in properties that may be supported by multiple AI services e.g., `temperature` or combine properties for different AI services e.g., `max_tokens` (OpenAI) and `max_new_tokens` (Oobabooga). -* Bad, because it's not clear to developers what they should pass when creating a semantic function -* Bad, because it's not clear to implementors of a chat/text completion service what they should accept or how to add service specific properties. -* Bad, code is needed to perform type checks and explicit casts. The situation is slightly better than for the `dynamic` case. +- Good, SK abstractions contain no references to OpenAI specific request settings +- Neutral, because anonymous types can be used which allows a developer to pass in properties that may be supported by multiple AI services e.g., `temperature` or combine properties for different AI services e.g., `max_tokens` (OpenAI) and `max_new_tokens` (Oobabooga). +- Bad, because it's not clear to developers what they should pass when creating a semantic function +- Bad, because it's not clear to implementors of a chat/text completion service what they should accept or how to add service specific properties. +- Bad, code is needed to perform type checks and explicit casts. The situation is slightly better than for the `dynamic` case. ### Define a base class for AI request settings which all implementations must extend @@ -221,12 +222,12 @@ this._summarizeConversationFunction = kernel.CreateSemanticFunction( The caveat with this pattern is, assuming a more specific implementation of `AIRequestSettings` uses JSON serialization/deserialization to hydrate an instance from the base `AIRequestSettings`, this will only work if all properties are supported by the default JsonConverter e.g., -* If we have `MyAIRequestSettings` which includes a `Uri` property. The implementation of `MyAIRequestSettings` would make sure to load a URI converter so that it can serialize/deserialize the settings correctly. -* If the settings for `MyAIRequestSettings` are sent to an AI service which relies on the default JsonConverter then a `NotSupportedException` exception will be thrown. +- If we have `MyAIRequestSettings` which includes a `Uri` property. The implementation of `MyAIRequestSettings` would make sure to load a URI converter so that it can serialize/deserialize the settings correctly. +- If the settings for `MyAIRequestSettings` are sent to an AI service which relies on the default JsonConverter then a `NotSupportedException` exception will be thrown. PR: -* Good, SK abstractions contain no references to OpenAI specific request settings -* Good, because it is clear to developers what they should pass when creating a semantic function and it is easy to discover what service specific request setting implementations exist. -* Good, because it is clear to implementors of a chat/text completion service what they should accept and how to extend the base abstraction to add service specific properties. -* Neutral, because `ExtensionData` can be used which allows a developer to pass in properties that may be supported by multiple AI services e.g., `temperature` or combine properties for different AI services e.g., `max_tokens` (OpenAI) and `max_new_tokens` (Oobabooga). +- Good, SK abstractions contain no references to OpenAI specific request settings +- Good, because it is clear to developers what they should pass when creating a semantic function and it is easy to discover what service specific request setting implementations exist. +- Good, because it is clear to implementors of a chat/text completion service what they should accept and how to extend the base abstraction to add service specific properties. +- Neutral, because `ExtensionData` can be used which allows a developer to pass in properties that may be supported by multiple AI services e.g., `temperature` or combine properties for different AI services e.g., `max_tokens` (OpenAI) and `max_new_tokens` (Oobabooga). diff --git a/docs/decisions/0009-support-multiple-named-args-in-template-function-calls.md b/docs/decisions/0009-support-multiple-named-args-in-template-function-calls.md index 40251ece1a..fbf533aa4d 100644 --- a/docs/decisions/0009-support-multiple-named-args-in-template-function-calls.md +++ b/docs/decisions/0009-support-multiple-named-args-in-template-function-calls.md @@ -4,9 +4,10 @@ status: accepted contact: dmytrostruk date: 2013-06-16 deciders: shawncal, hario90 -consulted: dmytrostruk, matthewbolanos +consulted: dmytrostruk, matthewbolanos informed: lemillermicrosoft --- + # Add support for multiple named arguments in template function calls ## Context and Problem Statement @@ -15,30 +16,30 @@ Native functions now support multiple parameters, populated from context values ## Decision Drivers -* Parity with Guidance -* Readability -* Similarity to languages familiar to SK developers -* YAML compatibility +- Parity with Guidance +- Readability +- Similarity to languages familiar to SK developers +- YAML compatibility ## Considered Options ### Syntax idea 1: Using commas - + ```handlebars {{Skill.MyFunction street: "123 Main St", zip: "98123", city:"Seattle", age: 25}} ``` Pros: -* Commas could make longer function calls easier to read, especially if spaces before and after the arg separator (a colon in this case) are allowed. +- Commas could make longer function calls easier to read, especially if spaces before and after the arg separator (a colon in this case) are allowed. Cons: -* Guidance doesn't use commas -* Spaces are already used as delimiters elsewhere so the added complexity of supporting commas isn't necessary +- Guidance doesn't use commas +- Spaces are already used as delimiters elsewhere so the added complexity of supporting commas isn't necessary ### Syntax idea 2: JavaScript/C#-Style delimiter (colon) - + ```handlebars {{MyFunction street:"123 Main St" zip:"98123" city:"Seattle" age: "25"}} @@ -47,12 +48,12 @@ Cons: Pros: -* Resembles JavaScript Object syntax and C# named argument syntax +- Resembles JavaScript Object syntax and C# named argument syntax Cons: -* Doesn't align with Guidance syntax which uses equal signs as arg part delimiters -* Too similar to YAML key/value pairs if we support YAML prompts in the future. It's likely possible to support colons as delimiters but would be better to have a separator that is distinct from normal YAML syntax. +- Doesn't align with Guidance syntax which uses equal signs as arg part delimiters +- Too similar to YAML key/value pairs if we support YAML prompts in the future. It's likely possible to support colons as delimiters but would be better to have a separator that is distinct from normal YAML syntax. ### Syntax idea 3: Python/Guidance-Style delimiter @@ -62,29 +63,29 @@ Cons: Pros: -* Resembles Python's keyword argument syntax -* Resembles Guidance's named argument syntax -* Not too similar to YAML key/value pairs if we support YAML prompts in the future. +- Resembles Python's keyword argument syntax +- Resembles Guidance's named argument syntax +- Not too similar to YAML key/value pairs if we support YAML prompts in the future. Cons: -* Doesn't align with C# syntax +- Doesn't align with C# syntax ### Syntax idea 4: Allow whitespace between arg name/value delimiter ```handlebars -{{MyFunction street = "123 Main St" zip = "98123" city = "Seattle"}} +{{MyFunction street="123 Main St" zip="98123" city="Seattle"}} ``` Pros: -* Follows the convention followed by many programming languages of whitespace flexibility where spaces, tabs, and newlines within code don't impact a program's functionality +- Follows the convention followed by many programming languages of whitespace flexibility where spaces, tabs, and newlines within code don't impact a program's functionality Cons: -* Promotes code that is harder to read unless commas can be used (see [Using Commas](#syntax-idea-1-using-commas)) -* More complexity to support -* Doesn't align with Guidance which doesn't support spaces before and after the = sign. +- Promotes code that is harder to read unless commas can be used (see [Using Commas](#syntax-idea-1-using-commas)) +- More complexity to support +- Doesn't align with Guidance which doesn't support spaces before and after the = sign. ## Decision Outcome @@ -92,20 +93,18 @@ Chosen options: "Syntax idea 3: Python/Guidance-Style keyword arguments", becaus Additional decisions: -* Continue supporting up to 1 positional argument for backward compatibility. Currently, the argument passed to a function is assumed to be the `$input` context variable. +- Continue supporting up to 1 positional argument for backward compatibility. Currently, the argument passed to a function is assumed to be the `$input` context variable. Example ```handlebars - {{MyFunction "inputVal" street="123 Main St" zip="98123" city="Seattle"}} - ``` -* Allow arg values to be defined as strings or variables ONLY, e.g. - +- Allow arg values to be defined as strings or variables ONLY, e.g. + ```handlebars -{{MyFunction street=$street zip="98123" city='Seattle'}} +{{MyFunction street=$street zip="98123" city="Seattle"}} ``` If function expects a value other than a string for an argument, the SDK will use the corresponding TypeConverter to parse the string provided when evaluating the expression. diff --git a/docs/decisions/0010-dotnet-project-structure.md b/docs/decisions/0010-dotnet-project-structure.md index 21ff81f6e9..7b21e07116 100644 --- a/docs/decisions/0010-dotnet-project-structure.md +++ b/docs/decisions/0010-dotnet-project-structure.md @@ -1,13 +1,15 @@ --- - # These are optional elements. Feel free to remove any of them status: accepted contact: markwallace-microsoft date: 2023-09-29 -deciders: semenshi, dmytrostruk, rbarreto -consulted: shawncal, stoub, lemiller -informed: {list everyone who is kept up-to-date on progress; and with whom there is a one-way communication} +deciders: SergeyMenshykh, dmytrostruk, RogerBarreto +consulted: shawncal, stephentoub, lemillermicrosoft +informed: + { + list everyone who is kept up-to-date on progress; and with whom there is a one-way communication, + } --- # DotNet Project Structure for 1.0 Release @@ -49,13 +51,13 @@ Chosen option: Option #2: Folder naming matches assembly name, because: Main categories for the projects will be: -1. `Connectors`: ***A connector project allows the Semantic Kernel to connect to AI and Memory services***. Some of the existing connector projects may move to other repositories. -1. `Planners`: ***A planner project provides one or more planner implementations which take an ask and convert it into an executable plan to achieve that ask***. This category will include the current action, sequential and stepwise planners (these could be merged into a single project). Additional planning implementations e.g., planners that generate Powershell or Python code can be added as separate projects. -1. `Functions`: ***A function project that enables the Semantic Kernel to access the functions it will orchestrate***. This category will include: - 1. Semantic functions i.e., prompts executed against an LLM - 1. GRPC remote procedures i.e., procedures executed remotely using the GRPC framework - 1. Open API endpoints i.e., REST endpoints that have Open API definitions executed remotely using the HTTP protocol -1. `Plugins`: ***A plugin project contains the implementation(s) of a Semantic Kernel plugin***. A Semantic Kernel plugin is contains a concrete implementation of a function e.g., a plugin may include code for basic text operations. +1. `Connectors`: **_A connector project allows the Semantic Kernel to connect to AI and Memory services_**. Some of the existing connector projects may move to other repositories. +1. `Planners`: **_A planner project provides one or more planner implementations which take an ask and convert it into an executable plan to achieve that ask_**. This category will include the current action, sequential and stepwise planners (these could be merged into a single project). Additional planning implementations e.g., planners that generate Powershell or Python code can be added as separate projects. +1. `Functions`: **_A function project that enables the Semantic Kernel to access the functions it will orchestrate_**. This category will include: + 1. Semantic functions i.e., prompts executed against an LLM + 1. GRPC remote procedures i.e., procedures executed remotely using the GRPC framework + 1. Open API endpoints i.e., REST endpoints that have Open API definitions executed remotely using the HTTP protocol +1. `Plugins`: **_A plugin project contains the implementation(s) of a Semantic Kernel plugin_**. A Semantic Kernel plugin is contains a concrete implementation of a function e.g., a plugin may include code for basic text operations. ### Option #1: New `planning`, `functions` and `plugins` project areas @@ -97,17 +99,17 @@ SK-dotnet ### Changes -| Project | Description | -|-------------------------------------|-------------| -| `Functions.Native` | Extract native functions from Semantic Kernel core and abstractions. | -| `Functions.Semantic` | Extract semantic functions from Semantic Kernel core and abstractions. Include the prompt template engine. | -| `Functions.Planning` | Extract planning from Semantic Kernel core and abstractions. | -| `Functions.Grpc` | Old `Skills.Grpc` project | -| `Functions.OpenAPI` | Old `Skills.OpenAPI` project | -| `Plugins.Core` | Old `Skills.Core` project | -| `Plugins.Document` | Old `Skills.Document` project | -| `Plugins.MsGraph` | Old `Skills.MsGraph` project | -| `Plugins.WebSearch` | Old `Skills.WebSearch` project | +| Project | Description | +| -------------------- | ---------------------------------------------------------------------------------------------------------- | +| `Functions.Native` | Extract native functions from Semantic Kernel core and abstractions. | +| `Functions.Semantic` | Extract semantic functions from Semantic Kernel core and abstractions. Include the prompt template engine. | +| `Functions.Planning` | Extract planning from Semantic Kernel core and abstractions. | +| `Functions.Grpc` | Old `Skills.Grpc` project | +| `Functions.OpenAPI` | Old `Skills.OpenAPI` project | +| `Plugins.Core` | Old `Skills.Core` project | +| `Plugins.Document` | Old `Skills.Document` project | +| `Plugins.MsGraph` | Old `Skills.MsGraph` project | +| `Plugins.WebSearch` | Old `Skills.WebSearch` project | ### Semantic Kernel Skills and Functions @@ -125,19 +127,19 @@ SK-dotnet │ ├── Microsoft.SemanticKernel.Connectors.AI.OpenAI* │ ├── src - │ └── tests + │ └── tests │ (Not shown but all projects will have src and tests subfolders) ├── Microsoft.SemanticKernel.Connectors.AI.HuggingFace ├── Microsoft.SemanticKernel.Connectors.Memory.AzureCognitiveSearch ├── Microsoft.SemanticKernel.Connectors.Memory.Qdrant │ ├── Microsoft.SemanticKernel.Planners* - │ + │ ├── Microsoft.SemanticKernel.Reliability.Basic* ├── Microsoft.SemanticKernel.Reliability.Polly - │ + │ ├── Microsoft.SemanticKernel.TemplateEngines.Basic* - │ + │ ├── Microsoft.SemanticKernel.Functions.Semantic* ├── Microsoft.SemanticKernel.Functions.Grpc ├── Microsoft.SemanticKernel.Functions.OpenAPI @@ -156,7 +158,7 @@ SK-dotnet └── Microsoft.SemanticKernel.MetaPackage ``` -***Notes:*** +**_Notes:_** - There will only be a single solution file (initially). - Projects will be grouped in the solution i.e., connectors, planners, plugins, functions, extensions, ... @@ -197,33 +199,33 @@ SK-dotnet └── SemanticKernel.UnitTests ``` -\\* - Means the project is part of the Semantic Kernel meta package +\\\* - Means the project is part of the Semantic Kernel meta package ### Project Descriptions -| Project | Description | -|-------------------------------------|-------------| -| Connectors.AI.OpenAI | Azure OpenAI and OpenAI service connectors | -| Connectors... | Collection of other AI service connectors, some of which will move to another repository | -| Connectors.UnitTests | Connector unit tests | -| Planner.ActionPlanner | Semantic Kernel implementation of an action planner | -| Planner.SequentialPlanner | Semantic Kernel implementation of a sequential planner | -| Planner.StepwisePlanner | Semantic Kernel implementation of a stepwise planner | -| TemplateEngine.Basic | Prompt template engine basic implementations which are used by Semantic Functions only | -| Extensions.UnitTests | Extensions unit tests | -| InternalUtilities | Internal utilities which are reused by multiple NuGet packages (all internal) | -| Skills.Core | Core set of native functions which are provided to support Semantic Functions | -| Skills.Document | Native functions for interacting with Microsoft documents | -| Skills.Grpc | Semantic Kernel integration for GRPC based endpoints | -| Skills.MsGraph | Native functions for interacting with Microsoft Graph endpoints | -| Skills.OpenAPI | Semantic Kernel integration for OpenAI endpoints and reference Azure Key Vault implementation | -| Skills.Web | Native functions for interacting with Web endpoints e.g., Bing, Google, File download | -| Skills.UnitTests | Skills unit tests | -| IntegrationTests | Semantic Kernel integration tests | -| SemanticKernel | Semantic Kernel core implementation | -| SemanticKernel.Abstractions | Semantic Kernel abstractions i.e., interface, abstract classes, supporting classes, ... | -| SemanticKernel.MetaPackage | Semantic Kernel meta package i.e., a NuGet package that references other required Semantic Kernel NuGet packages | -| SemanticKernel.UnitTests | Semantic Kernel unit tests | +| Project | Description | +| --------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| Connectors.AI.OpenAI | Azure OpenAI and OpenAI service connectors | +| Connectors... | Collection of other AI service connectors, some of which will move to another repository | +| Connectors.UnitTests | Connector unit tests | +| Planner.ActionPlanner | Semantic Kernel implementation of an action planner | +| Planner.SequentialPlanner | Semantic Kernel implementation of a sequential planner | +| Planner.StepwisePlanner | Semantic Kernel implementation of a stepwise planner | +| TemplateEngine.Basic | Prompt template engine basic implementations which are used by Semantic Functions only | +| Extensions.UnitTests | Extensions unit tests | +| InternalUtilities | Internal utilities which are reused by multiple NuGet packages (all internal) | +| Skills.Core | Core set of native functions which are provided to support Semantic Functions | +| Skills.Document | Native functions for interacting with Microsoft documents | +| Skills.Grpc | Semantic Kernel integration for GRPC based endpoints | +| Skills.MsGraph | Native functions for interacting with Microsoft Graph endpoints | +| Skills.OpenAPI | Semantic Kernel integration for OpenAI endpoints and reference Azure Key Vault implementation | +| Skills.Web | Native functions for interacting with Web endpoints e.g., Bing, Google, File download | +| Skills.UnitTests | Skills unit tests | +| IntegrationTests | Semantic Kernel integration tests | +| SemanticKernel | Semantic Kernel core implementation | +| SemanticKernel.Abstractions | Semantic Kernel abstractions i.e., interface, abstract classes, supporting classes, ... | +| SemanticKernel.MetaPackage | Semantic Kernel meta package i.e., a NuGet package that references other required Semantic Kernel NuGet packages | +| SemanticKernel.UnitTests | Semantic Kernel unit tests | ### Naming Patterns @@ -283,10 +285,9 @@ dotnet/ This diagram show current skills are integrated with the Semantic Kernel core. -***Note:*** +**_Note:_** - This is not a true class hierarchy diagram. It show some class relationships and dependencies. - Namespaces are abbreviated to remove Microsoft.SemanticKernel prefix. Namespaces use `_` rather than `.`. ISKFunction class relationships - diff --git a/docs/decisions/0012-kernel-service-registration.md b/docs/decisions/0012-kernel-service-registration.md index db2e8ac144..2e69907bcc 100644 --- a/docs/decisions/0012-kernel-service-registration.md +++ b/docs/decisions/0012-kernel-service-registration.md @@ -4,9 +4,10 @@ status: accepted contact: dmytrostruk date: 2023-10-03 deciders: dmytrostruk -consulted: semenshi, rbarreto, markwallace-microsoft -informed: +consulted: SergeyMenshykh, RogerBarreto, markwallace-microsoft +informed: --- + # Kernel Service Registration ## Context and Problem Statement @@ -82,12 +83,12 @@ Custom service collection and service provider on Kernel level to simplify depen Interface `IKernel` will have its own service provider `KernelServiceProvider` with minimal functionality to get required service. ```csharp -public interface IKernelServiceProvider +public interface IKernelServiceProvider { T? GetService(string? name = null); -} +} -public interface IKernel +public interface IKernel { IKernelServiceProvider Services { get; } } @@ -174,7 +175,7 @@ Cons: - Additional dependency for Semantic Kernel package - `Microsoft.Extensions.DependencyInjection`. - No possibility to include specific list of services (lack of isolation from host application). -- Possibility of `Microsoft.Extensions.DependencyInjection` version mismatch and runtime errors (e.g. users have `Microsoft.Extensions.DependencyInjection` `--version 2.0` while Semantic Kernel uses `--version 6.0`) +- Possibility of `Microsoft.Extensions.DependencyInjection` version mismatch and runtime errors (e.g. users have `Microsoft.Extensions.DependencyInjection` `--version 2.0` while Semantic Kernel uses `--version 6.0`) ## Decision Outcome diff --git a/docs/decisions/0014-chat-completion-roles-in-prompt.md b/docs/decisions/0014-chat-completion-roles-in-prompt.md index 3f4b39b12f..354367c277 100644 --- a/docs/decisions/0014-chat-completion-roles-in-prompt.md +++ b/docs/decisions/0014-chat-completion-roles-in-prompt.md @@ -1,146 +1,165 @@ --- # These are optional elements. Feel free to remove any of them. status: accepted -contact: semenshi +contact: SergeyMenshykh date: 2023-10-23 -deciders: markwallace-microsoft, mabolan +deciders: markwallace-microsoft, matthewbolanos consulted: informed: --- + # SK prompt syntax for chat completion roles ## Context and Problem Statement + Today, SK does not have the ability to mark a block of text in a prompt as a message with a specific role, such as assistant, system, or user. As a result, SK can't chunk the prompt into the list of messages required by chat completion connectors. Additionally, prompts can be defined using a range of template syntaxes supported by various template engines, such as Handlebars, Jinja, and others. Each of these syntaxes may represent chat messages or roles in a distinct way. Consequently, the template engine syntax may leak into SK's domain if no proper abstraction is put in place, coupling SK with the template engines and making it impossible to support new ones. + ## Decision Drivers -* It should be possible to mark a block of text in a prompt as a message with a role so that it can be converted into a list of chat messages for use by chat completion connectors. -* The syntax specific to the template engine message/role should be mapped to the SK message/role syntax to abstract SK from a specific template engine syntax. + +- It should be possible to mark a block of text in a prompt as a message with a role so that it can be converted into a list of chat messages for use by chat completion connectors. +- The syntax specific to the template engine message/role should be mapped to the SK message/role syntax to abstract SK from a specific template engine syntax. ## Considered Options + **1. Message/role tags are generated by functions specified in a prompt.** This option relies on the fact that many template engines can invoke functions specified in the template. Therefore, an internal function can be registered with a template engine, and the function will create a message/model tag based on the provided arguments. The prompt template engine will execute the function and emit the function result into the prompt template, and the rendered prompt will have a section for each message/role decorated with these tags. Here's an example of how this can be done using the SK basic template engine and Handlebars: - Function: - ```csharp - internal class SystemFunctions - { - public string Message(string role) - { - return $""; - } - } - ``` - - Prompt: +Function: - ```bash - {{message role="system"}} - You are a bank manager. Be helpful, respectful, appreciate diverse language styles. - {{message role="system"}} +```csharp +internal class SystemFunctions +{ + public string Message(string role) + { + return $""; + } +} +``` - {{message role="user"}} - I want to {{$input}} - {{message role="user"}} - ``` +Prompt: - Rendered prompt: +```bash +{{message role="system"}} +You are a bank manager. Be helpful, respectful, appreciate diverse language styles. +{{message role="system"}} - ```xml - - You are a bank manager. Be helpful, respectful, appreciate diverse language styles. - - - I want to buy a house. - - ``` +{{message role="user"}} +I want to {{$input}} +{{message role="user"}} +``` -**2. Message/role tags are generated by a prompt-specific mechanism.** This option utilizes template engine syntax constructions, helpers, and handlers other than functions to inject SK message/role tags into the final prompt. - In the example below, to parse the prompt that uses the handlebars syntax we need to register a block helper (a callback that is invoked when the Handlebars engine encounters it) to emit the SK message/role tags in the resulting prompt. - - Block helpers: - ```csharp - this.handlebarsEngine.RegisterHelper("system", (EncodedTextWriter output, Context context, Arguments arguments) => { - //Emit the tags - }); - this.handlebarsEngine.RegisterHelper("user", (EncodedTextWriter output, Context context, Arguments arguments) => { - //Emit the tags - }); - ``` +Rendered prompt: - Prompt: - ```bash - {{#system~}} - You are a bank manager. Be helpful, respectful, appreciate diverse language styles. - {{~/system}} - {{#user~}} - I want to {{$input}} - {{~/user}} - ``` +```xml + +You are a bank manager. Be helpful, respectful, appreciate diverse language styles. + + +I want to buy a house. + +``` - Rendered prompt: - ```xml - - You are a bank manager. Be helpful, respectful, appreciate diverse language styles. - - - I want to buy a house. - - ``` +**2. Message/role tags are generated by a prompt-specific mechanism.** This option utilizes template engine syntax constructions, helpers, and handlers other than functions to inject SK message/role tags into the final prompt. +In the example below, to parse the prompt that uses the handlebars syntax we need to register a block helper (a callback that is invoked when the Handlebars engine encounters it) to emit the SK message/role tags in the resulting prompt. + +Block helpers: + +```csharp +this.handlebarsEngine.RegisterHelper("system", (EncodedTextWriter output, Context context, Arguments arguments) => { + //Emit the tags +}); +this.handlebarsEngine.RegisterHelper("user", (EncodedTextWriter output, Context context, Arguments arguments) => { + //Emit the tags +}); +``` + +Prompt: + +```bash +{{#system~}} +You are a bank manager. Be helpful, respectful, appreciate diverse language styles. +{{~/system}} +{{#user~}} +I want to {{$input}} +{{~/user}} +``` + +Rendered prompt: + +```xml + +You are a bank manager. Be helpful, respectful, appreciate diverse language styles. + + +I want to buy a house. + +``` **3. Message/role tags are applied on top of prompt template engine**. This option presumes specifying the SK message/role tags directly in a prompt to denote message/role blocks in way that template engine does not parse/handle them and considers them as a regular text. - In the example below, the prompt the `` tags are marking boundaries of the system and user messages and SK basic template engine consider them as regular text without processing them. - - Prompt: - ```xml - - You are a bank manager. Be helpful, respectful, appreciate diverse language styles. - - - I want to {{$input}} - - ``` +In the example below, the prompt the `` tags are marking boundaries of the system and user messages and SK basic template engine consider them as regular text without processing them. - Rendered prompt: - ```xml - - You are a bank manager. Be helpful, respectful, appreciate diverse language styles. - - - I want to buy a house. - - ``` +Prompt: + +```xml + +You are a bank manager. Be helpful, respectful, appreciate diverse language styles. + + +I want to {{$input}} + +``` + +Rendered prompt: + +```xml + +You are a bank manager. Be helpful, respectful, appreciate diverse language styles. + + +I want to buy a house. + +``` ## Pros and Cons -**1. Message/role tags are generated by functions specified in a prompt** - - Pros: - * Functions can be defined once and reused in prompt templates that support function calling. - Cons: - * Functions might not be supported by some template engines. - * The system/internal functions should be pre-registered by SK so users don't need to import them. - * Each prompt template engine will have how to discover and call the system/internal functions. +**1. Message/role tags are generated by functions specified in a prompt** + +Pros: + +- Functions can be defined once and reused in prompt templates that support function calling. + +Cons: + +- Functions might not be supported by some template engines. +- The system/internal functions should be pre-registered by SK so users don't need to import them. +- Each prompt template engine will have how to discover and call the system/internal functions. **2. Message/role tags are generated by prompt specific mechanism** - Pros: - * Enables message/role representation with the optimal template engine syntax constructions, aligning with other constructions for that specific engine. - - Cons: - * Each prompt template engine will have to register callbacks/handlers to handle template syntax constructions rendering to emit SK message/role tags. +Pros: + +- Enables message/role representation with the optimal template engine syntax constructions, aligning with other constructions for that specific engine. + +Cons: + +- Each prompt template engine will have to register callbacks/handlers to handle template syntax constructions rendering to emit SK message/role tags. **3. Message/role tags are applied on top of prompt template engine** - Pros: - * No changes are required to prompt template engines. +Pros: - Cons: - * The message/role tag syntax may not align with other syntax constructions for that template engine. - * Syntax errors in message/role tags will be detected by components parsing the prompt and not by prompt template engines. +- No changes are required to prompt template engines. + +Cons: + +- The message/role tag syntax may not align with other syntax constructions for that template engine. +- Syntax errors in message/role tags will be detected by components parsing the prompt and not by prompt template engines. ## Decision Outcome + It was agreed not to limit ourselves to only one possible option because it may not be feasible to apply that option to new template engines we might need to support in the future. Instead, each time a new template engine is added, every option should be considered, and the optimal one should be preferred for that particular template engine. -It was also agreed that, at the moment, we will go with the "3. Message/role tags are applied on top of the prompt template engine" option to support the message/role prompt syntax in SK, which currently uses the `BasicPromptTemplateEngine` engine. \ No newline at end of file +It was also agreed that, at the moment, we will go with the "3. Message/role tags are applied on top of the prompt template engine" option to support the message/role prompt syntax in SK, which currently uses the `BasicPromptTemplateEngine` engine. diff --git a/docs/decisions/0015-completion-service-selection.md b/docs/decisions/0015-completion-service-selection.md index c669d03798..624fcfd886 100644 --- a/docs/decisions/0015-completion-service-selection.md +++ b/docs/decisions/0015-completion-service-selection.md @@ -1,24 +1,31 @@ --- # These are optional elements. Feel free to remove any of them. status: accepted +contact: SergeyMenshykh date: 2023-10-25 -deciders: markwallace, mabolan +deciders: markwallace-microsoft, matthewbolanos consulted: informed: --- + # Completion service type selection strategy ## Context and Problem Statement + Today, SK runs all text prompts using the text completion service. With the addition of a new chat completion prompts and potentially other prompt types, such as image, on the horizon, we need a way to select a completion service type to run these prompts. + ## Decision Drivers -* Semantic function should be able to identify a completion service type to use when processing text, chat, or image prompts. + +- Semantic function should be able to identify a completion service type to use when processing text, chat, or image prompts. ## Considered Options + **1. Completion service type identified by the "prompt_type" property.** This option presumes adding the 'prompt_type' property to the prompt template config model class, 'PromptTemplateConfig.' The property will be specified once by a prompt developer and will be used by the 'SemanticFunction' class to decide which completion service type (not instance) to use when resolving an instance of that particular completion service type. **Prompt template** + ```json { "schema": "1", @@ -29,12 +36,13 @@ Today, SK runs all text prompts using the text completion service. With the addi ``` **Semantic function pseudocode** + ```csharp if(string.IsNullOrEmpty(promptTemplateConfig.PromptType) || promptTemplateConfig.PromptType == "text") { var service = this._serviceSelector.SelectAIService(context.ServiceProvider, this._modelSettings); //render the prompt, call the service, process and return result -} +} else (promptTemplateConfig.PromptType == "chat") { var service = this._serviceSelector.SelectAIService(context.ServiceProvider, this._modelSettings); @@ -68,12 +76,12 @@ config: { ``` Pros: - - Deterministically specifies which completion service **type** to use, so image prompts won't be rendered by a text completion service, and vice versa. + +- Deterministically specifies which completion service **type** to use, so image prompts won't be rendered by a text completion service, and vice versa. Cons: - - Another property to specify by a prompt developer. - +- Another property to specify by a prompt developer. **2. Completion service type identified by prompt content.** The idea behind this option is to analyze the rendered prompt by using regex to check for the presence of specific markers associated with the prompt type. For example, the presence of the `` tag in the rendered prompt might indicate that the prompt is a chat prompt and should be handled by the chat completion service. This approach may work reliably when we have two completion service types - text and chat - since the logic would be straightforward: if the message tag is found in the rendered prompt, handle it with the chat completion service; otherwise, use the text completion service. However, this logic becomes unreliable when we start adding new prompt types, and those prompts lack markers specific to their prompt type. For example, if we add an image prompt, we won't be able to distinguish between a text prompt and an image prompt unless the image prompt has a unique marker identifying it as such. @@ -107,11 +115,15 @@ config: { ... } ``` + Pros: + - No need for a new property to identify the prompt type. Cons: + - Unreliable unless the prompt contains unique markers specifically identifying the prompt type. ## Decision Outcome + We decided to choose the '2. Completion service type identified by prompt content' option and will reconsider it when we encounter another completion service type that cannot be supported by this option or when we have a solid set of requirements for using a different mechanism for selecting the completion service type. diff --git a/docs/decisions/0016-custom-prompt-template-formats.md b/docs/decisions/0016-custom-prompt-template-formats.md index 5ebb5a5e97..c5b39fdfa8 100644 --- a/docs/decisions/0016-custom-prompt-template-formats.md +++ b/docs/decisions/0016-custom-prompt-template-formats.md @@ -2,10 +2,11 @@ status: approved contact: markwallace-microsoft date: 2023-10-26 -deciders: mabolan, markwallace-microsoft, semenshi, rbarreto +deciders: matthewbolanos, markwallace-microsoft, SergeyMenshykh, RogerBarreto consulted: dmytrostruk -informed: +informed: --- + # Custom Prompt Template Formats ## Context and Problem Statement @@ -57,7 +58,7 @@ The `BasicPromptTemplateEngine` uses the `TemplateTokenizer` to parse the templa Then it renders the template i.e. inserts variables and executes functions. Some sample timings for these operations: | Operation | Ticks | Milliseconds | -|------------------|---------|--------------| +| ---------------- | ------- | ------------ | | Extract blocks | 1044427 | 103 | | Render variables | 168 | 0 | @@ -67,10 +68,10 @@ Sample template used was: `"{{variable1}} {{variable2}} {{variable3}} {{variable Using `HandlebarsDotNet` for the same use case results in the following timings: -| Operation | Ticks | Milliseconds | -|------------------|---------|--------------| -| Compile template | 66277 | 6 | -| Render variables | 4173 | 0 | +| Operation | Ticks | Milliseconds | +| ---------------- | ----- | ------------ | +| Compile template | 66277 | 6 | +| Render variables | 4173 | 0 | **By separating the extract blocks/compile from the render variables operation it will be possible to optimise performance by compiling templates just once.** @@ -135,7 +136,6 @@ Some issues: 1. The `IPromptTemplate` interface is not used and causes confusion. 1. There is no way to allow developers to support multiple prompt template formats at the same time. - There is one implementation of `IPromptTemplate` provided in the Semantic Kernel core package. The `RenderAsync` implementation just delegates to the `IPromptTemplateEngine`. The `Parameters` list get's populated with the parameters defined in the `PromptTemplateConfig` and any missing variables defined in the template. @@ -175,16 +175,16 @@ and then register the helpers. This means we cannot take advantage of the perfor In no particular order: -* Support creating a semantic function without a `IKernel`instance. -* Support late binding of functions i.e., having functions resolved when the prompt is rendered. -* Support allowing the prompt template to be parsed (compiled) just once to optimize performance if needed. -* Support using multiple prompt template formats with a single `Kernel` instance. -* Provide simple abstractions which allow third parties to implement support for custom prompt template formats. +- Support creating a semantic function without a `IKernel`instance. +- Support late binding of functions i.e., having functions resolved when the prompt is rendered. +- Support allowing the prompt template to be parsed (compiled) just once to optimize performance if needed. +- Support using multiple prompt template formats with a single `Kernel` instance. +- Provide simple abstractions which allow third parties to implement support for custom prompt template formats. ## Considered Options -* Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory`. -* +- Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory`. +- ### Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory` @@ -221,9 +221,9 @@ Console.WriteLine(result.GetValue()); **Notes:** -* `BasicPromptTemplateFactory` will be the default implementation and will be automatically provided in `KernelSemanticFunctionExtensions`. Developers will also be able to provide their own implementation. -* The factory uses the new `PromptTemplateConfig.TemplateFormat` to create the appropriate `IPromptTemplate` instance. -* We should look to remove `promptTemplateConfig` as a parameter to `CreateSemanticFunction`. That change is outside of the scope of this ADR. +- `BasicPromptTemplateFactory` will be the default implementation and will be automatically provided in `KernelSemanticFunctionExtensions`. Developers will also be able to provide their own implementation. +- The factory uses the new `PromptTemplateConfig.TemplateFormat` to create the appropriate `IPromptTemplate` instance. +- We should look to remove `promptTemplateConfig` as a parameter to `CreateSemanticFunction`. That change is outside of the scope of this ADR. The `BasicPromptTemplateFactory` and `BasicPromptTemplate` implementations look as follows: @@ -280,8 +280,8 @@ public sealed class BasicPromptTemplate : IPromptTemplate **Note:** -* The call to `ExtractBlocks` is called lazily once for each prompt template -* The `RenderAsync` doesn't need to extract the blocks every time +- The call to `ExtractBlocks` is called lazily once for each prompt template +- The `RenderAsync` doesn't need to extract the blocks every time ## Decision Outcome diff --git a/docs/decisions/0010-openai-function-calling.md b/docs/decisions/0017-openai-function-calling.md similarity index 61% rename from docs/decisions/0010-openai-function-calling.md rename to docs/decisions/0017-openai-function-calling.md index 63c605916c..f0035ce458 100644 --- a/docs/decisions/0010-openai-function-calling.md +++ b/docs/decisions/0017-openai-function-calling.md @@ -6,11 +6,13 @@ deciders: gitri-ms, shawncal consulted: lemillermicrosoft, awharrison-28, dmytrostruk, nacharya1 informed: eavanvalkenburg, kevdome3000 --- + # OpenAI Function Calling Support ## Context and Problem Statement -The [function calling](https://platform.openai.com/docs/guides/gpt/function-calling) capability of OpenAI's Chat Completions API allows developers to describe functions to the model, and have the model decide whether to output a JSON object specifying a function and appropriate arguments to call in response to the given prompt. This capability is enabled by two new API parameters to the `/v1/chat/completions` endpoint: +The [function calling](https://platform.openai.com/docs/guides/gpt/function-calling) capability of OpenAI's Chat Completions API allows developers to describe functions to the model, and have the model decide whether to output a JSON object specifying a function and appropriate arguments to call in response to the given prompt. This capability is enabled by two new API parameters to the `/v1/chat/completions` endpoint: + - `function_call` - auto (default), none, or a specific function to call - `functions` - JSON descriptions of the functions available to the model @@ -20,15 +22,15 @@ We have received several community requests to provide support for this capabili ## Decision Drivers -* Minimize changes to the core kernel for OpenAI-specific functionality -* Cost concerns with including a long list of function descriptions in the request -* Security and cost concerns with automatically executing functions returned by the model +- Minimize changes to the core kernel for OpenAI-specific functionality +- Cost concerns with including a long list of function descriptions in the request +- Security and cost concerns with automatically executing functions returned by the model ## Considered Options -* Support sending/receiving functions via chat completions endpoint _with_ modifications to interfaces -* Support sending/receiving functions via chat completions endpoint _without_ modifications to interfaces -* Implement a planner around the function calling capability +- Support sending/receiving functions via chat completions endpoint _with_ modifications to interfaces +- Support sending/receiving functions via chat completions endpoint _without_ modifications to interfaces +- Implement a planner around the function calling capability ## Decision Outcome @@ -38,32 +40,33 @@ With this option, we utilize the existing request settings object to send functi ### Consequences -* Good, because avoids breaking changes to the core kernel -* Good, because OpenAI-specific functionality is contained to the OpenAI connector package -* Good, because allows app to control what functions are available to the model (including non-SK functions) -* Good, because keeps the option open for integrating with planners in the future -* Neutral, because requires app developer to validate and execute resulting function -* Bad, because not as obvious how to use this capability and access the function results +- Good, because avoids breaking changes to the core kernel +- Good, because OpenAI-specific functionality is contained to the OpenAI connector package +- Good, because allows app to control what functions are available to the model (including non-SK functions) +- Good, because keeps the option open for integrating with planners in the future +- Neutral, because requires app developer to validate and execute resulting function +- Bad, because not as obvious how to use this capability and access the function results ## Pros and Cons of the Options ### Support sending/receiving functions _with_ modifications to chat completions interfaces -This option would update the `IChatCompletion` and `IChatResult` interfaces to expose parameters/methods for providing and accessing function information. +This option would update the `IChatCompletion` and `IChatResult` interfaces to expose parameters/methods for providing and accessing function information. -* Good, because provides a clear path for using the function calling capability -* Good, because allows app to control what functions are available to the model (including non-SK functions) -* Neutral, because requires app developer to validate and execute resulting function -* Bad, because introduces breaking changes to core kernel abstractions -* Bad, because OpenAI-specific functionality would be included in core kernel abstractions and would need to be ignored by other model providers +- Good, because provides a clear path for using the function calling capability +- Good, because allows app to control what functions are available to the model (including non-SK functions) +- Neutral, because requires app developer to validate and execute resulting function +- Bad, because introduces breaking changes to core kernel abstractions +- Bad, because OpenAI-specific functionality would be included in core kernel abstractions and would need to be ignored by other model providers ### Implement a planner around the function calling capability -Orchestrating external function calls fits within SK's concept of planning. With this approach, we would implement a planner that would take the function calling result and produce a plan that the app developer could execute (similar to SK's ActionPlanner). +Orchestrating external function calls fits within SK's concept of planning. With this approach, we would implement a planner that would take the function calling result and produce a plan that the app developer could execute (similar to SK's ActionPlanner). -* Good, because producing a plan result makes it easy for the app developer to execute the chosen function -* Bad, because functions would need to be registered with the kernel in order to be executed -* Bad, because would create confusion about when to use which planner +- Good, because producing a plan result makes it easy for the app developer to execute the chosen function +- Bad, because functions would need to be registered with the kernel in order to be executed +- Bad, because would create confusion about when to use which planner ## Additional notes -There has been much discussion and debate over the pros and cons of automatically invoking a function returned by the OpenAI model, if it is registered with the kernel. As there are still many open questions around this behavior and its implications, we have decided to not include this capability in the initial implementation. We will continue to explore this option and may include it in a future update. \ No newline at end of file + +There has been much discussion and debate over the pros and cons of automatically invoking a function returned by the OpenAI model, if it is registered with the kernel. As there are still many open questions around this behavior and its implications, we have decided to not include this capability in the initial implementation. We will continue to explore this option and may include it in a future update. diff --git a/docs/decisions/0017-semantic-function-multiple-model-support.md b/docs/decisions/0017-semantic-function-multiple-model-support.md deleted file mode 100644 index 318285639f..0000000000 --- a/docs/decisions/0017-semantic-function-multiple-model-support.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -# These are optional elements. Feel free to remove any of them. -status: approved -contact: markwallace-microsoft -date: 2023-10-26 -deciders: markwallace-microsoft, semenshi, rogerbarreto -consulted: mabolan, dmytrostruk -informed: ---- -# Multiple Model Support for Semantic Functions - -## Context and Problem Statement - -Developers need to be able to use multiple models e.g., using chat completion together with embeddings. - -## Use Cases - -In scope for Semantic Kernel V1.0 - -* Select Model Request Settings by Service Id. - * A Service Id uniquely identifies a registered AI Service and is typically defined in the scope of an application. -* Select AI Service and Model Request Settings By Developer Defined Strategy. - * A Developer Defined Strategy is a code first approach where a developer provides the logic. - -Out of scope for V1.0 - -* Select Model Request Settings by Model Id. - * A Model Id uniquely identifies a Large Language Model. Multiple AI service providers can support the same LLM. -* Select Model Request Settings by Provider Id and Model Id - * A Provider Id uniquely identifies an AI provider e.g. "Azure OpenAI", "OpenAI", "Hugging Face" - -## Decision Outcome - -Support just use cases listed in this ADR. - -## Descriptions of the Use Cases - -**Note: All code is pseudo code and does not accurately reflect what the final implementations will look like.** - -### Select Model Request Settings by Service Id - -_As a developer using the Semantic Kernel I can configure multiple request settings for a semantic function and associate each one with a service id so that the correct request settings are used when different services are used to execute my semantic function._ - -The semantic function template configuration allows multiple model request settings to be configured. In this case the developer configures different settings based on the service id that is used to execute the semantic function. -In the example below the semantic function is executed with "AzureText" using `max_tokens=60` because "AzureText" is the first service id in the list of models configured for the prompt. - -```csharp -// Configure a Kernel with multiple LLM's -IKernel kernel = Kernel.Builder - .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureTextCompletionService(deploymentName: aoai.DeploymentName, - endpoint: aoai.Endpoint, serviceId: "AzureText", apiKey: aoai.ApiKey) - .WithAzureChatCompletionService(deploymentName: aoai.ChatDeploymentName, - endpoint: aoai.Endpoint, serviceId: "AzureChat", apiKey: aoai.ApiKey) - .WithOpenAITextCompletionService(modelId: oai.ModelId, - serviceId: "OpenAIText", apiKey: oai.ApiKey) - .WithOpenAIChatCompletionService(modelId: oai.ChatModelId, - serviceId: "OpenAIChat", apiKey: oai.ApiKey, setAsDefault: true) - .Build(); - -// Configure semantic function with multiple LLM request settings -string configPayload = @"{ - ""schema"": 1, - ""description"": ""Hello AI, what can you do for me?"", - ""models"": [ - { ""service_id"": ""AzureText"", ""max_tokens"": 60 }, - { ""service_id"": ""AzureChat"", ""max_tokens"": 120 }, - { ""service_id"": ""OpenAIText"", ""max_tokens"": 180 }, - { ""service_id"": ""OpenAIChat"", ""max_tokens"": 240 } - ] -}"; -var templateConfig = JsonSerializer.Deserialize(configPayload); -var func = kernel.CreateSemanticFunction(prompt, config: templateConfig!, "HelloAI"); - -// Semantic function is executed with OpenAIChat using max_tokens=240 -result = await kernel.RunAsync(func); -``` - -This works by using the `IAIServiceSelector` interface as the strategy for selecting the AI service and request settings to user when invoking a semantic function. -The interface is defined as follows: - -```csharp -public interface IAIServiceSelector -{ - (T?, AIRequestSettings?) SelectAIService(IAIServiceProvider serviceProvider, IReadOnlyList? modelSettings) where T : IAIService; -} -``` - -A default `OrderedIAIServiceSelector` implementation is used which selects the AI service based on the order of the model request settings defined for the semantic function. -The implementation checks if a service exists which the corresponding service id and if it does it and the associated model request settings will be used. -In no model request settings are defined then the default text completion service is used. -A default set of request settings can be specified by leaving the service id undefined or empty, the first such default will be used. -If no default if specified and none of the specified services are available the operation will fail. - -### Select AI Service and Model Request Settings By Developer Defined Strategy - -_As a developer using the Semantic Kernel I can provide factories which select the AI service and request settings used to execute my function so that I can dynamically control which AI service is used to execute my semantic function._ - -In this case the developer configures different settings based on the model id and provides an AI Service factory which determines which AI Service will be used when the semantic function is executed. -In the example below the semantic function is executed with whatever AI Service `myServiceFactory` returns. - -```csharp -// Configure a Kernel with multiple LLM's -IKernel kernel = Kernel.Builder - .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureTextCompletionService(deploymentName: aoai.DeploymentName, // text-davinci-003 - endpoint: aoai.Endpoint, serviceId: "AzureText", apiKey: aoai.ApiKey) - .WithAzureChatCompletionService(deploymentName: aoai.ChatDeploymentName, // gpt-35-turbo - endpoint: aoai.Endpoint, serviceId: "AzureChat", apiKey: aoai.ApiKey) - .WithOpenAITextCompletionService(modelId: oai.ModelId, // text-davinci-003 - serviceId: "OpenAIText", apiKey: oai.ApiKey, setAsDefault: true) - .WithOpenAIChatCompletionService(modelId: oai.ChatModelId, // gpt-3.5-turbo - serviceId: "OpenAIChat", apiKey: oai.ApiKey) - .Build(); - -// Configure semantic function with multiple LLM request settings -string configPayload = @"{ - ""schema"": 1, - ""description"": ""Hello AI, what can you do for me?"", - ""models"": [ - { ""max_tokens"": 60 }, - { ""max_tokens"": 120 }, - { ""max_tokens"": 180 } - ] -}"; -var templateConfig = JsonSerializer.Deserialize(configPayload); -var func = kernel.CreateSemanticFunction(prompt, config: templateConfig!, "HelloAI"); - -// Semantic function is executed with AI Service and AI request Settings dynamically determined -result = await kernel.RunAsync(func, funcVariables); -``` - -## More Information - -### Select AI Service by Service Id - -The following use case is supported. Developers can create a `Kernel`` instance with multiple named AI services. When invoking a semantic function the service id (and optionally request settings to be used) can be specified. The named AI service will be used to execute the prompt. - -```csharp -var aoai = TestConfiguration.AzureOpenAI; -var oai = TestConfiguration.OpenAI; - -// Configure a Kernel with multiple LLM's -IKernel kernel = Kernel.Builder - .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureTextCompletionService(deploymentName: aoai.DeploymentName, - endpoint: aoai.Endpoint, serviceId: "AzureText", apiKey: aoai.ApiKey) - .WithAzureChatCompletionService(deploymentName: aoai.ChatDeploymentName, - endpoint: aoai.Endpoint, serviceId: "AzureChat", apiKey: aoai.ApiKey) - .WithOpenAITextCompletionService(modelId: oai.ModelId, - serviceId: "OpenAIText", apiKey: oai.ApiKey) - .WithOpenAIChatCompletionService(modelId: oai.ChatModelId, - serviceId: "OpenAIChat", apiKey: oai.ApiKey) - .Build(); - -// Invoke the semantic function and service and request settings to use -result = await kernel.InvokeSemanticFunctionAsync(prompt, - requestSettings: new OpenAIRequestSettings() - { ServiceId = "AzureText", MaxTokens = 60 }); - -result = await kernel.InvokeSemanticFunctionAsync(prompt, - requestSettings: new OpenAIRequestSettings() - { ServiceId = "AzureChat", MaxTokens = 120 }); - -result = await kernel.InvokeSemanticFunctionAsync(prompt, - requestSettings: new OpenAIRequestSettings() - { ServiceId = "OpenAIText", MaxTokens = 180 }); - -result = await kernel.InvokeSemanticFunctionAsync(prompt, - requestSettings: new OpenAIRequestSettings() - { ServiceId = "OpenAIChat", MaxTokens = 240 }); -``` diff --git a/docs/decisions/0017-custom-prompt-template-formats.md b/docs/decisions/0018-custom-prompt-template-formats.md similarity index 91% rename from docs/decisions/0017-custom-prompt-template-formats.md rename to docs/decisions/0018-custom-prompt-template-formats.md index 755d19a754..5cd1f7f90c 100644 --- a/docs/decisions/0017-custom-prompt-template-formats.md +++ b/docs/decisions/0018-custom-prompt-template-formats.md @@ -2,10 +2,11 @@ status: approved contact: markwallace-microsoft date: 2023-10-26 -deciders: mabolan, markwallace-microsoft, semenshi, rbarreto +deciders: matthewbolanos, markwallace-microsoft, SergeyMenshykh, RogerBarreto consulted: dmytrostruk -informed: +informed: --- + # Custom Prompt Template Formats ## Context and Problem Statement @@ -58,7 +59,7 @@ The `BasicPromptTemplateEngine` uses the `TemplateTokenizer` to parse the templa Then it renders the template i.e. inserts variables and executes functions. Some sample timings for these operations: | Operation | Ticks | Milliseconds | -|------------------|---------|--------------| +| ---------------- | ------- | ------------ | | Extract blocks | 1044427 | 103 | | Render variables | 168 | 0 | @@ -68,10 +69,10 @@ Sample template used was: `"{{variable1}} {{variable2}} {{variable3}} {{variable Using `HandlebarsDotNet` for the same use case results in the following timings: -| Operation | Ticks | Milliseconds | -|------------------|---------|--------------| -| Compile template | 66277 | 6 | -| Render variables | 4173 | 0 | +| Operation | Ticks | Milliseconds | +| ---------------- | ----- | ------------ | +| Compile template | 66277 | 6 | +| Render variables | 4173 | 0 | **By separating the extract blocks/compile from the render variables operation it will be possible to optimise performance by compiling templates just once.** @@ -175,15 +176,15 @@ and then register the helpers. This means we cannot take advantage of the perfor In no particular order: -* Support creating a semantic function without a `IKernel`instance. -* Support late binding of functions i.e., having functions resolved when the prompt is rendered. -* Support allowing the prompt template to be parsed (compiled) just once to optimize performance if needed. -* Support using multiple prompt template formats with a single `Kernel` instance. -* Provide simple abstractions which allow third parties to implement support for custom prompt template formats. +- Support creating a semantic function without a `IKernel`instance. +- Support late binding of functions i.e., having functions resolved when the prompt is rendered. +- Support allowing the prompt template to be parsed (compiled) just once to optimize performance if needed. +- Support using multiple prompt template formats with a single `Kernel` instance. +- Provide simple abstractions which allow third parties to implement support for custom prompt template formats. ## Considered Options -* Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory`. +- Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory`. ### Obsolete `IPromptTemplateEngine` and replace with `IPromptTemplateFactory` @@ -216,9 +217,9 @@ Console.WriteLine(result.GetValue()); **Notes:** -* `BasicPromptTemplateFactory` will be the default implementation and will be automatically provided in `KernelSemanticFunctionExtensions`. Developers will also be able to provide their own implementation. -* The factory uses the new `PromptTemplateConfig.TemplateFormat` to create the appropriate `IPromptTemplate` instance. -* We should look to remove `promptTemplateConfig` as a parameter to `CreateSemanticFunction`. That change is outside of the scope of this ADR. +- `BasicPromptTemplateFactory` will be the default implementation and will be automatically provided in `KernelSemanticFunctionExtensions`. Developers will also be able to provide their own implementation. +- The factory uses the new `PromptTemplateConfig.TemplateFormat` to create the appropriate `IPromptTemplate` instance. +- We should look to remove `promptTemplateConfig` as a parameter to `CreateSemanticFunction`. That change is outside of the scope of this ADR. The `BasicPromptTemplateFactory` and `BasicPromptTemplate` implementations look as follows: @@ -275,8 +276,8 @@ public sealed class BasicPromptTemplate : IPromptTemplate **Note:** -* The call to `ExtractBlocks` is called lazily once for each prompt template -* The `RenderAsync` doesn't need to extract the blocks every time +- The call to `ExtractBlocks` is called lazily once for each prompt template +- The `RenderAsync` doesn't need to extract the blocks every time ## Decision Outcome diff --git a/docs/decisions/0016-semantic-function-multiple-model-support.md b/docs/decisions/0019-semantic-function-multiple-model-support.md similarity index 83% rename from docs/decisions/0016-semantic-function-multiple-model-support.md rename to docs/decisions/0019-semantic-function-multiple-model-support.md index bb2a3a72ae..569bc6b293 100644 --- a/docs/decisions/0016-semantic-function-multiple-model-support.md +++ b/docs/decisions/0019-semantic-function-multiple-model-support.md @@ -3,10 +3,11 @@ status: approved contact: markwallace-microsoft date: 2023-10-26 -deciders: markwallace-microsoft, semenshi, rogerbarreto -consulted: mabolan, dmytrostruk -informed: +deciders: markwallace-microsoft, SergeyMenshykh, rogerbarreto +consulted: matthewbolanos, dmytrostruk +informed: --- + # Multiple Model Support for Semantic Functions ## Context and Problem Statement @@ -18,13 +19,13 @@ Developers need to be able to use multiple models simultaneously e.g., using GPT In scope for Semantic Kernel V1.0 is the ability to select AI Service and Model Request Settings: 1. By service id. - * A Service id uniquely identifies a registered AI Service and is typically defined in the scope of an application. + - A Service id uniquely identifies a registered AI Service and is typically defined in the scope of an application. 1. By developer defined strategy. - * A _developer defined strategy_ is a code first approach where a developer provides the logic. + - A _developer defined strategy_ is a code first approach where a developer provides the logic. 1. By model id. - * A model id uniquely identifies a Large Language Model. Multiple AI service providers can support the same LLM. + - A model id uniquely identifies a Large Language Model. Multiple AI service providers can support the same LLM. 1. By arbitrary AI service attributes - * E.g. an AI service can define a provider id which uniquely identifies an AI provider e.g. "Azure OpenAI", "OpenAI", "Hugging Face" + - E.g. an AI service can define a provider id which uniquely identifies an AI provider e.g. "Azure OpenAI", "OpenAI", "Hugging Face" **This ADR focuses on items 1 & 2 in the above list. To implement 3 & 4 we need to provide the ability to store `AIService` metadata.** @@ -80,18 +81,18 @@ The interface is defined as follows: public interface IAIServiceSelector { (T?, AIRequestSettings?) SelectAIService( - string renderedPrompt, - IAIServiceProvider serviceProvider, + string renderedPrompt, + IAIServiceProvider serviceProvider, IReadOnlyList? modelSettings) where T : IAIService; } ``` A default `OrderedIAIServiceSelector` implementation is provided which selects the AI service based on the order of the model request settings defined for the semantic function. -* The implementation checks if a service exists which the corresponding service id and if it does it and the associated model request settings will be used. -* In no model request settings are defined then the default text completion service is used. -* A default set of request settings can be specified by leaving the service id undefined or empty, the first such default will be used. -* If no default if specified and none of the specified services are available the operation will fail. +- The implementation checks if a service exists which the corresponding service id and if it does it and the associated model request settings will be used. +- In no model request settings are defined then the default text completion service is used. +- A default set of request settings can be specified by leaving the service id undefined or empty, the first such default will be used. +- If no default if specified and none of the specified services are available the operation will fail. ### Select AI Service and Model Request Settings By Developer Defined Strategy @@ -144,30 +145,30 @@ var oai = TestConfiguration.OpenAI; // Configure a Kernel with multiple LLM's IKernel kernel = Kernel.Builder .WithLoggerFactory(ConsoleLogger.LoggerFactory) - .WithAzureTextCompletionService(deploymentName: aoai.DeploymentName, + .WithAzureTextCompletionService(deploymentName: aoai.DeploymentName, endpoint: aoai.Endpoint, serviceId: "AzureText", apiKey: aoai.ApiKey) - .WithAzureChatCompletionService(deploymentName: aoai.ChatDeploymentName, + .WithAzureChatCompletionService(deploymentName: aoai.ChatDeploymentName, endpoint: aoai.Endpoint, serviceId: "AzureChat", apiKey: aoai.ApiKey) - .WithOpenAITextCompletionService(modelId: oai.ModelId, + .WithOpenAITextCompletionService(modelId: oai.ModelId, serviceId: "OpenAIText", apiKey: oai.ApiKey) - .WithOpenAIChatCompletionService(modelId: oai.ChatModelId, + .WithOpenAIChatCompletionService(modelId: oai.ChatModelId, serviceId: "OpenAIChat", apiKey: oai.ApiKey) .Build(); // Invoke the semantic function and service and request settings to use -result = await kernel.InvokeSemanticFunctionAsync(prompt, - requestSettings: new OpenAIRequestSettings() +result = await kernel.InvokeSemanticFunctionAsync(prompt, + requestSettings: new OpenAIRequestSettings() { ServiceId = "AzureText", MaxTokens = 60 }); -result = await kernel.InvokeSemanticFunctionAsync(prompt, - requestSettings: new OpenAIRequestSettings() +result = await kernel.InvokeSemanticFunctionAsync(prompt, + requestSettings: new OpenAIRequestSettings() { ServiceId = "AzureChat", MaxTokens = 120 }); -result = await kernel.InvokeSemanticFunctionAsync(prompt, - requestSettings: new OpenAIRequestSettings() +result = await kernel.InvokeSemanticFunctionAsync(prompt, + requestSettings: new OpenAIRequestSettings() { ServiceId = "OpenAIText", MaxTokens = 180 }); -result = await kernel.InvokeSemanticFunctionAsync(prompt, - requestSettings: new OpenAIRequestSettings() +result = await kernel.InvokeSemanticFunctionAsync(prompt, + requestSettings: new OpenAIRequestSettings() { ServiceId = "OpenAIChat", MaxTokens = 240 }); ``` diff --git a/docs/decisions/adr-short-template.md b/docs/decisions/adr-short-template.md index 9b88da98e7..bd8b10491f 100644 --- a/docs/decisions/adr-short-template.md +++ b/docs/decisions/adr-short-template.md @@ -1,31 +1,34 @@ --- # These are optional elements. Feel free to remove any of them. status: {proposed | rejected | accepted | deprecated | â€Ļ | superseded by [ADR-0001](0001-madr-architecture-decisions.md)} +contact: {person proposing the ADR} date: {YYYY-MM-DD when the decision was last updated} deciders: {list everyone involved in the decision} consulted: {list everyone whose opinions are sought (typically subject-matter experts); and with whom there is a two-way communication} informed: {list everyone who is kept up-to-date on progress; and with whom there is a one-way communication} --- + # {short title of solved problem and solution} ## Context and Problem Statement {Describe the context and problem statement, e.g., in free form using two to three sentences or in the form of an illustrative story. - You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.} +You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.} + ## Decision Drivers -* {decision driver 1, e.g., a force, facing concern, â€Ļ} -* {decision driver 2, e.g., a force, facing concern, â€Ļ} -* â€Ļ +- {decision driver 1, e.g., a force, facing concern, â€Ļ} +- {decision driver 2, e.g., a force, facing concern, â€Ļ} +- â€Ļ ## Considered Options -* {title of option 1} -* {title of option 2} -* {title of option 3} -* â€Ļ +- {title of option 1} +- {title of option 2} +- {title of option 3} +- â€Ļ ## Decision Outcome diff --git a/docs/decisions/adr-template.md b/docs/decisions/adr-template.md index 0ab8c17b58..a96551338a 100644 --- a/docs/decisions/adr-template.md +++ b/docs/decisions/adr-template.md @@ -1,31 +1,34 @@ --- # These are optional elements. Feel free to remove any of them. status: {proposed | rejected | accepted | deprecated | â€Ļ | superseded by [ADR-0001](0001-madr-architecture-decisions.md)} +contact: {person proposing the ADR} date: {YYYY-MM-DD when the decision was last updated} deciders: {list everyone involved in the decision} consulted: {list everyone whose opinions are sought (typically subject-matter experts); and with whom there is a two-way communication} informed: {list everyone who is kept up-to-date on progress; and with whom there is a one-way communication} --- + # {short title of solved problem and solution} ## Context and Problem Statement {Describe the context and problem statement, e.g., in free form using two to three sentences or in the form of an illustrative story. - You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.} +You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.} + ## Decision Drivers -* {decision driver 1, e.g., a force, facing concern, â€Ļ} -* {decision driver 2, e.g., a force, facing concern, â€Ļ} -* â€Ļ +- {decision driver 1, e.g., a force, facing concern, â€Ļ} +- {decision driver 2, e.g., a force, facing concern, â€Ļ} +- â€Ļ ## Considered Options -* {title of option 1} -* {title of option 2} -* {title of option 3} -* â€Ļ +- {title of option 1} +- {title of option 2} +- {title of option 3} +- â€Ļ ## Decision Outcome @@ -33,47 +36,52 @@ Chosen option: "{title of option 1}", because {justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force {force} | â€Ļ | comes out best (see below)}. + ### Consequences -* Good, because {positive consequence, e.g., improvement of one or more desired qualities, â€Ļ} -* Bad, because {negative consequence, e.g., compromising one or more desired qualities, â€Ļ} -* â€Ļ +- Good, because {positive consequence, e.g., improvement of one or more desired qualities, â€Ļ} +- Bad, because {negative consequence, e.g., compromising one or more desired qualities, â€Ļ} +- â€Ļ + ## Validation {describe how the implementation of/compliance with the ADR is validated. E.g., by a review or an ArchUnit test} + ## Pros and Cons of the Options ### {title of option 1} + {example | description | pointer to more information | â€Ļ} -* Good, because {argument a} -* Good, because {argument b} +- Good, because {argument a} +- Good, because {argument b} -* Neutral, because {argument c} -* Bad, because {argument d} -* â€Ļ +- Neutral, because {argument c} +- Bad, because {argument d} +- â€Ļ ### {title of other option} {example | description | pointer to more information | â€Ļ} -* Good, because {argument a} -* Good, because {argument b} -* Neutral, because {argument c} -* Bad, because {argument d} -* â€Ļ +- Good, because {argument a} +- Good, because {argument b} +- Neutral, because {argument c} +- Bad, because {argument d} +- â€Ļ + ## More Information {You might want to provide additional evidence/confidence for the decision outcome here and/or - document the team agreement on the decision and/or - define when this decision when and how the decision should be realized and if/when it should be re-visited and/or - how the decision is validated. - Links to other decisions and resources might appear here as well.} +document the team agreement on the decision and/or +define when this decision when and how the decision should be realized and if/when it should be re-visited and/or +how the decision is validated. +Links to other decisions and resources might appear here as well.} From f381fab227dff4425789dd8ad6da3824c81cc4fc Mon Sep 17 00:00:00 2001 From: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:23:15 +0000 Subject: [PATCH 013/576] ADR for mapping of prompt syntax to completion service model (#3338) --- ...tax-mapping-to-completion-service-model.md | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 docs/decisions/0020-prompt-syntax-mapping-to-completion-service-model.md diff --git a/docs/decisions/0020-prompt-syntax-mapping-to-completion-service-model.md b/docs/decisions/0020-prompt-syntax-mapping-to-completion-service-model.md new file mode 100644 index 0000000000..5c3b7f4b5a --- /dev/null +++ b/docs/decisions/0020-prompt-syntax-mapping-to-completion-service-model.md @@ -0,0 +1,57 @@ +--- +# These are optional elements. Feel free to remove any of them. +status: accepted +date: 2023-10-27 +contact: SergeyMenshykh +deciders: markwallace, mabolan +consulted: +informed: +--- +# Mapping of prompt syntax to completion service model + +## Context and Problem Statement +Today, SK runs all prompts using the text completion service by simply passing the rendered prompt as is, without any modifications, directly to a configured text completion service/connector. With the addition of new chat completion prompt and potentially other prompt types, such as image, on the horizon, we need a way to map completion-specific prompt syntax to the corresponding completion service data model. + +For example, [the chat completion syntax](https://github.com/microsoft/semantic-kernel/blob/main/docs/decisions/0014-chat-completion-roles-in-prompt.md) in chat completion prompts: +```xml + + You are a creative assistant helping individuals and businesses with their innovative projects. + + + I want to brainstorm the idea of {{$input}} + +``` +should be mapped to an instance of the [ChatHistory](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatHistory.cs) class with two chat messages: + +```csharp +var messages = new ChatHistory(); +messages.Add(new ChatMessage(new AuthorRole("system"), "You are a creative assistant helping individuals and businesses with their innovative projects.")); +messages.Add(new ChatMessage(new AuthorRole("user"), "I want to brainstorm the idea of {{$input}}")); +``` + +This ADR outlines potential options for the location of the prompt syntax mapping functionality. + +## Considered Options +**1. Completion connector classes.** This option proposes to have the completion connector classes responsible for the `prompt syntax -> completion service data model` mapping. The decision regarding whether this mapping functionality will be implemented in the connector classes themselves or delegated to mapper classes should be made during the implementation phase and is out of the scope of this ADR. + +Pros: + - The `SemanticFunction` won't need to change to support the mapping of a new prompt syntax when new completion type connectors (audio, video, etc.) are added. + + - Prompts can be run by + - Kernel.RunAsync + - Completion connectors + +Cons: + - Every new completion connector, whether of an existing type or a new type, will have to implement the mapping functionality + +**2. The SemanticFunction class.** This option proposes that the `SemanticFunction` class be responsible for the mapping. Similar to the previous option, the exact location of this functionality (whether in the `SemanticFunction` class or in the mapper classes) should be decided during the implementation phase. + +Pros: + - New connectors of a new type or existing ones don't have to implement the mapping functionality + +Cons: + - The `SemanticFunction` class has to be changed every time a new completion type needs to be supported by SK + - Prompts can be run by Kernel.RunAsync method only. + +## Decision Outcome +It was agreed to go with the option 1 - `1. Completion connector classes` since it a more flexible solution and allows adding new connectors without modifying the `SemanticFunction` class. \ No newline at end of file From 2f010f385efbfc10d125751973cdfb6b01cecacc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:24:40 +0000 Subject: [PATCH 014/576] .Net: Bump Polly from 8.0.0 to 8.1.0 in /dotnet (#3400) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [Polly](https://github.com/App-vNext/Polly) from 8.0.0 to 8.1.0.
Release notes

Sourced from Polly's releases.

8.1.0

Highlights

What's Changed

... (truncated)

Changelog

Sourced from Polly's changelog.

8.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Polly&package-manager=nuget&previous-version=8.0.0&new-version=8.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 99c17f5e4b..f5c8250e51 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -14,7 +14,7 @@ - + From 617a3775e5cefd8ebfa5068f690dd9faa9c6a0e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:25:02 +0000 Subject: [PATCH 015/576] .Net: Bump Microsoft.Azure.Kusto.Data from 11.3.4 to 11.3.5 in /dotnet (#3403) Bumps Microsoft.Azure.Kusto.Data from 11.3.4 to 11.3.5. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.Azure.Kusto.Data&package-manager=nuget&previous-version=11.3.4&new-version=11.3.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index f5c8250e51..779fbc4a6c 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -9,7 +9,7 @@ - + From d1c27210922a1a3dda393791c660d02f9ee343d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:26:17 +0000 Subject: [PATCH 016/576] .Net: Bump Microsoft.ML.Tokenizers from 0.21.0-preview.23266.6 to 0.21.0-preview.23511.1 in /dotnet (#3402) Bumps [Microsoft.ML.Tokenizers](https://github.com/dotnet/machinelearning) from 0.21.0-preview.23266.6 to 0.21.0-preview.23511.1.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.ML.Tokenizers&package-manager=nuget&previous-version=0.21.0-preview.23266.6&new-version=0.21.0-preview.23511.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 779fbc4a6c..8b86287747 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -20,7 +20,7 @@ - + From 1c6bcb7d3ac483fb7aa103b5c959c3de4d2a4d92 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:26:47 +0000 Subject: [PATCH 017/576] .Net: Bump Microsoft.Data.Sqlite from 7.0.12 to 7.0.13 in /dotnet (#3401) Bumps [Microsoft.Data.Sqlite](https://github.com/dotnet/efcore) from 7.0.12 to 7.0.13.
Release notes

Sourced from Microsoft.Data.Sqlite's releases.

.NET 7.0.13

Release

Commits
  • f64d1aa Revert "Fix to #30996 - Incorrect translation of comparison of current value ...
  • e1c894f Merge tag 'v7.0.12' into internal/release/7.0-10D
  • e629bc8 Merge in 'release/7.0' changes
  • 748bfee Fix to #30996 - Incorrect translation of comparison of current value with own...
  • 8166e14 Update branding to 7.0.13 (#31954)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.Data.Sqlite&package-manager=nuget&previous-version=7.0.12&new-version=7.0.13)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 8b86287747..2730b2847b 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -45,7 +45,7 @@ - + From 2a9f9274dc90b652c099126dc371af4b07ba459d Mon Sep 17 00:00:00 2001 From: Ben Thomas Date: Tue, 7 Nov 2023 10:09:26 -0800 Subject: [PATCH 018/576] .Net: Deleting all deprecated samples. (#3260) ### Motivation and Context ### Description ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: --------- Co-authored-by: Ben Thomas --- .github/workflows/node-pr.yml | 72 - .gitignore | 1 - .vscode/tasks.json | 64 - dotnet/SK-dotnet.sln | 24 - .../notebooks/06-memory-and-embeddings.ipynb | 4 - dotnet/notebooks/09-memory-with-chroma.ipynb | 4 - .../Example14_SemanticMemory.cs | 4 - .../Example23_OpenApiPlugin_Github.cs | 85 - .../notebooks/06-memory-and-embeddings.ipynb | 6 +- .../weaviate-persistent-memory.ipynb | 8 +- samples/apps/.eslintrc.js | 37 - samples/apps/README.md | 2 - .../apps/auth-api-webapp-react/.env.example | 8 - samples/apps/auth-api-webapp-react/.env.local | 2 - samples/apps/auth-api-webapp-react/README.md | 61 - .../apps/auth-api-webapp-react/package.json | 45 - .../auth-api-webapp-react/public/favicon.ico | Bin 17174 -> 0 bytes .../auth-api-webapp-react/public/index.html | 37 - .../apps/auth-api-webapp-react/src/App.css | 45 - .../apps/auth-api-webapp-react/src/App.tsx | 212 - .../src/components/FunctionProbe.tsx | 60 - .../src/components/InteractWithGraph.tsx | 157 - .../src/components/InteractionButton.tsx | 40 - .../src/components/QuickTipGroup.tsx | 36 - .../src/components/QuickTips.tsx | 50 - .../src/components/ServiceConfig.tsx | 168 - .../src/components/TaskButton.tsx | 82 - .../src/components/YourInfo.tsx | 39 - .../src/hooks/SemanticKernel.ts | 109 - .../src/hooks/useSemanticKernel.ts | 9 - .../apps/auth-api-webapp-react/src/index.tsx | 54 - .../auth-api-webapp-react/src/model/Ask.ts | 12 - .../src/model/AskResult.ts | 7 - .../src/model/KeyConfig.ts | 28 - .../src/ms-symbollockup_signin_light.svg | 1 - .../src/react-app-env.d.ts | 1 - .../apps/auth-api-webapp-react/src/word.png | Bin 822 -> 0 bytes .../apps/auth-api-webapp-react/tsconfig.json | 26 - samples/apps/auth-api-webapp-react/yarn.lock | 10177 --------------- .../book-creator-webapp-react/.env.example | 6 - .../apps/book-creator-webapp-react/.env.local | 2 - .../apps/book-creator-webapp-react/README.md | 53 - .../book-creator-webapp-react/package.json | 42 - .../public/favicon.ico | Bin 17174 -> 0 bytes .../public/index.html | 37 - .../book-creator-webapp-react/src/App.css | 45 - .../book-creator-webapp-react/src/App.tsx | 201 - .../src/components/CreateBook.tsx | 473 - .../src/components/CreateBookWithPlanner.tsx | 328 - .../src/components/FunctionProbe.tsx | 60 - .../src/components/QuickTipGroup.tsx | 36 - .../src/components/QuickTips.tsx | 50 - .../src/components/ServiceConfig.tsx | 168 - .../src/components/TaskButton.tsx | 80 - .../src/components/TopicCard.tsx | 29 - .../src/components/TopicSelection.tsx | 151 - .../src/hooks/SemanticKernel.ts | 109 - .../src/hooks/TaskRunner.ts | 50 - .../src/hooks/useSemanticKernel.ts | 9 - .../src/hooks/useTaskRunner.ts | 11 - .../book-creator-webapp-react/src/index.tsx | 40 - .../src/model/Ask.ts | 12 - .../src/model/AskResult.ts | 9 - .../src/model/KeyConfig.ts | 28 - .../src/model/Page.ts | 12 - .../src/react-app-env.d.ts | 1 - .../book-creator-webapp-react/tsconfig.json | 26 - .../apps/book-creator-webapp-react/yarn.lock | 10153 --------------- .../chat-summary-webapp-react/.env.example | 6 - .../apps/chat-summary-webapp-react/.env.local | 2 - .../apps/chat-summary-webapp-react/README.md | 64 - .../chat-summary-webapp-react/package.json | 42 - .../public/favicon.ico | Bin 17174 -> 0 bytes .../public/index.html | 37 - .../chat-summary-webapp-react/src/App.css | 45 - .../chat-summary-webapp-react/src/App.tsx | 177 - .../src/components/AISummary.tsx | 184 - .../src/components/FunctionProbe.tsx | 60 - .../src/components/QuickTipGroup.tsx | 36 - .../src/components/QuickTips.tsx | 50 - .../src/components/ServiceConfig.tsx | 168 - .../src/components/chat/ChatHistoryItem.tsx | 37 - .../src/components/chat/ChatInput.tsx | 44 - .../src/components/chat/ChatInteraction.tsx | 81 - .../src/components/chat/ChatThread.ts | 149 - .../src/hooks/SemanticKernel.ts | 109 - .../src/hooks/useSemanticKernel.ts | 9 - .../chat-summary-webapp-react/src/index.tsx | 40 - .../src/model/Ask.ts | 11 - .../src/model/AskResult.ts | 5 - .../src/model/KeyConfig.ts | 28 - .../src/react-app-env.d.ts | 1 - .../chat-summary-webapp-react/tsconfig.json | 26 - .../apps/chat-summary-webapp-react/yarn.lock | 10153 --------------- samples/apps/copilot-chat-app/README.md | 3 - .../apps/github-qna-webapp-react/.env.example | 17 - .../apps/github-qna-webapp-react/.env.local | 2 - .../apps/github-qna-webapp-react/README.md | 59 - .../contents-read-access.png | Bin 80754 -> 0 bytes .../apps/github-qna-webapp-react/package.json | 42 - .../public/favicon.ico | Bin 17174 -> 0 bytes .../github-qna-webapp-react/public/index.html | 37 - .../apps/github-qna-webapp-react/src/App.css | 45 - .../apps/github-qna-webapp-react/src/App.tsx | 230 - .../src/assets/icons8-github-512.png | Bin 11553 -> 0 bytes .../src/components/FunctionProbe.tsx | 41 - .../src/components/GitHubRepoSelection.tsx | 216 - .../src/components/QnA.tsx | 182 - .../src/components/QuickTipGroup.tsx | 31 - .../src/components/QuickTips.tsx | 38 - .../src/components/ServiceConfig.tsx | 226 - .../src/components/chat/ChatHistoryItem.tsx | 87 - .../src/components/chat/ChatInput.tsx | 53 - .../src/components/setup/ModelConfig.tsx | 407 - .../src/hooks/SemanticKernel.ts | 111 - .../src/hooks/useSemanticKernel.ts | 10 - .../github-qna-webapp-react/src/index.tsx | 42 - .../github-qna-webapp-react/src/model/Ask.ts | 11 - .../src/model/AskResult.ts | 5 - .../src/model/KeyConfig.ts | 28 - .../src/react-app-env.d.ts | 1 - .../github-qna-webapp-react/tsconfig.json | 26 - .../apps/github-qna-webapp-react/yarn.lock | 10340 ---------------- .../apps/hugging-face-http-server/Dockerfile | 19 - .../apps/hugging-face-http-server/README.md | 56 - .../hugging-face-http-server/inference_app.py | 178 - .../hugging-face-http-server/requirements.txt | 36 - .../static/css/styles.css | 11 - .../templates/completions.html | 24 - .../templates/documentation.html | 27 - .../templates/embeddings.html | 21 - .../templates/home.html | 14 - .../templates/images.html | 21 - .../utils/CompletionGenerator.py | 38 - .../utils/EmbeddingGenerator.py | 34 - .../utils/ImageGenerator.py | 39 - .../utils/InferenceGenerator.py | 15 - .../utils/create_responses.py | 41 - samples/apps/prettier.config.js | 8 - samples/dotnet/Directory.Build.props | 16 - samples/dotnet/Directory.Build.targets | 17 - samples/dotnet/Directory.Packages.props | 38 - .../KernelHttpServer/.vscode/extensions.json | 6 - .../KernelHttpServer/Config/AIService.cs | 10 - .../Config/AIServiceConfig.cs | 36 - .../KernelHttpServer/Config/ApiKeyConfig.cs | 10 - .../KernelHttpServer/Config/Constants.cs | 21 - samples/dotnet/KernelHttpServer/Extensions.cs | 199 - .../KernelHttpServer/KernelHttpServer.csproj | 39 - samples/dotnet/KernelHttpServer/Model/Ask.cs | 25 - .../KernelHttpServer/Model/AskResult.cs | 13 - .../dotnet/KernelHttpServer/PingEndpoint.cs | 21 - .../KernelHttpServer/Plugins/GitHubPlugin.cs | 235 - samples/dotnet/KernelHttpServer/Program.cs | 39 - samples/dotnet/KernelHttpServer/README.md | 53 - .../SemanticKernelEndpoint.cs | 179 - .../KernelHttpServer/SemanticKernelFactory.cs | 104 - .../TokenAuthenticationProvider.cs | 25 - .../KernelHttpServer/Utils/RepoFiles.cs | 41 - .../Utils/YourAppException.cs | 20 - samples/dotnet/KernelHttpServer/host.json | 11 - .../KernelHttpServer/local.settings.json | 9 - .../AzureOpenAIConfiguration.cs | 25 - .../MsGraphPluginsExample.csproj | 42 - .../OpenAIConfiguration.cs | 21 - .../dotnet/MsGraphPluginsExample/Program.cs | 213 - .../Properties/launchSettings.json | 10 - .../dotnet/MsGraphPluginsExample/README.md | 47 - .../dotnet/MsGraphPluginsExample/RepoFiles.cs | 41 - .../MsGraphPluginsExample/YourAppException.cs | 20 - .../MsGraphPluginsExample/appsettings.json | 34 - .../OpenApiPluginsExample/AIServiceOptions.cs | 71 - .../GitHubPlugin/Model/PullRequest.cs | 66 - .../GitHubPlugin/Model/User.cs | 23 - .../GitHubPlugin/openapi.json | 5935 --------- .../GitHubPluginOptions.cs | 31 - .../NotEmptyOrWhitespaceAttribute.cs | 33 - .../OpenApiPluginsExample.csproj | 43 - .../dotnet/OpenApiPluginsExample/Program.cs | 233 - .../dotnet/OpenApiPluginsExample/README.md | 32 - .../RequiredOnPropertyValueAttribute.cs | 80 - .../OpenApiPluginsExample/appsettings.json | 42 - .../dotnet/kernel-syntax-examples/README.md | 3 - samples/dotnet/nuget.config | 15 - .../python/kernel-syntax-examples/README.md | 3 - samples/python/kernel_http_server/.funcignore | 8 - samples/python/kernel_http_server/README.md | 96 - .../python/kernel_http_server/function_app.py | 33 - samples/python/kernel_http_server/host.json | 15 - .../kernel_http_server/local.settings.json | 10 - .../kernel_http_server/requirements.txt | 7 - .../python/kernel_http_server/utils/ask.py | 26 - .../python/kernel_http_server/utils/config.py | 72 - .../kernel_http_server/utils/kernel_server.py | 159 - .../kernel_http_server/utils/kernel_utils.py | 120 - 195 files changed, 2 insertions(+), 57208 deletions(-) delete mode 100644 .github/workflows/node-pr.yml delete mode 100644 dotnet/samples/KernelSyntaxExamples/Example23_OpenApiPlugin_Github.cs delete mode 100644 samples/apps/.eslintrc.js delete mode 100644 samples/apps/README.md delete mode 100644 samples/apps/auth-api-webapp-react/.env.example delete mode 100644 samples/apps/auth-api-webapp-react/.env.local delete mode 100644 samples/apps/auth-api-webapp-react/README.md delete mode 100644 samples/apps/auth-api-webapp-react/package.json delete mode 100644 samples/apps/auth-api-webapp-react/public/favicon.ico delete mode 100644 samples/apps/auth-api-webapp-react/public/index.html delete mode 100644 samples/apps/auth-api-webapp-react/src/App.css delete mode 100644 samples/apps/auth-api-webapp-react/src/App.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/components/FunctionProbe.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/components/InteractWithGraph.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/components/InteractionButton.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/components/QuickTipGroup.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/components/QuickTips.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/components/ServiceConfig.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/components/TaskButton.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/components/YourInfo.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/hooks/SemanticKernel.ts delete mode 100644 samples/apps/auth-api-webapp-react/src/hooks/useSemanticKernel.ts delete mode 100644 samples/apps/auth-api-webapp-react/src/index.tsx delete mode 100644 samples/apps/auth-api-webapp-react/src/model/Ask.ts delete mode 100644 samples/apps/auth-api-webapp-react/src/model/AskResult.ts delete mode 100644 samples/apps/auth-api-webapp-react/src/model/KeyConfig.ts delete mode 100644 samples/apps/auth-api-webapp-react/src/ms-symbollockup_signin_light.svg delete mode 100644 samples/apps/auth-api-webapp-react/src/react-app-env.d.ts delete mode 100644 samples/apps/auth-api-webapp-react/src/word.png delete mode 100644 samples/apps/auth-api-webapp-react/tsconfig.json delete mode 100644 samples/apps/auth-api-webapp-react/yarn.lock delete mode 100644 samples/apps/book-creator-webapp-react/.env.example delete mode 100644 samples/apps/book-creator-webapp-react/.env.local delete mode 100644 samples/apps/book-creator-webapp-react/README.md delete mode 100644 samples/apps/book-creator-webapp-react/package.json delete mode 100644 samples/apps/book-creator-webapp-react/public/favicon.ico delete mode 100644 samples/apps/book-creator-webapp-react/public/index.html delete mode 100644 samples/apps/book-creator-webapp-react/src/App.css delete mode 100644 samples/apps/book-creator-webapp-react/src/App.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/CreateBook.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/CreateBookWithPlanner.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/FunctionProbe.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/QuickTipGroup.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/QuickTips.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/ServiceConfig.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/TaskButton.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/TopicCard.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/components/TopicSelection.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/hooks/SemanticKernel.ts delete mode 100644 samples/apps/book-creator-webapp-react/src/hooks/TaskRunner.ts delete mode 100644 samples/apps/book-creator-webapp-react/src/hooks/useSemanticKernel.ts delete mode 100644 samples/apps/book-creator-webapp-react/src/hooks/useTaskRunner.ts delete mode 100644 samples/apps/book-creator-webapp-react/src/index.tsx delete mode 100644 samples/apps/book-creator-webapp-react/src/model/Ask.ts delete mode 100644 samples/apps/book-creator-webapp-react/src/model/AskResult.ts delete mode 100644 samples/apps/book-creator-webapp-react/src/model/KeyConfig.ts delete mode 100644 samples/apps/book-creator-webapp-react/src/model/Page.ts delete mode 100644 samples/apps/book-creator-webapp-react/src/react-app-env.d.ts delete mode 100644 samples/apps/book-creator-webapp-react/tsconfig.json delete mode 100644 samples/apps/book-creator-webapp-react/yarn.lock delete mode 100644 samples/apps/chat-summary-webapp-react/.env.example delete mode 100644 samples/apps/chat-summary-webapp-react/.env.local delete mode 100644 samples/apps/chat-summary-webapp-react/README.md delete mode 100644 samples/apps/chat-summary-webapp-react/package.json delete mode 100644 samples/apps/chat-summary-webapp-react/public/favicon.ico delete mode 100644 samples/apps/chat-summary-webapp-react/public/index.html delete mode 100644 samples/apps/chat-summary-webapp-react/src/App.css delete mode 100644 samples/apps/chat-summary-webapp-react/src/App.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/AISummary.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/FunctionProbe.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/QuickTipGroup.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/QuickTips.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/ServiceConfig.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/chat/ChatHistoryItem.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/chat/ChatInput.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/chat/ChatInteraction.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/components/chat/ChatThread.ts delete mode 100644 samples/apps/chat-summary-webapp-react/src/hooks/SemanticKernel.ts delete mode 100644 samples/apps/chat-summary-webapp-react/src/hooks/useSemanticKernel.ts delete mode 100644 samples/apps/chat-summary-webapp-react/src/index.tsx delete mode 100644 samples/apps/chat-summary-webapp-react/src/model/Ask.ts delete mode 100644 samples/apps/chat-summary-webapp-react/src/model/AskResult.ts delete mode 100644 samples/apps/chat-summary-webapp-react/src/model/KeyConfig.ts delete mode 100644 samples/apps/chat-summary-webapp-react/src/react-app-env.d.ts delete mode 100644 samples/apps/chat-summary-webapp-react/tsconfig.json delete mode 100644 samples/apps/chat-summary-webapp-react/yarn.lock delete mode 100644 samples/apps/copilot-chat-app/README.md delete mode 100644 samples/apps/github-qna-webapp-react/.env.example delete mode 100644 samples/apps/github-qna-webapp-react/.env.local delete mode 100644 samples/apps/github-qna-webapp-react/README.md delete mode 100644 samples/apps/github-qna-webapp-react/contents-read-access.png delete mode 100644 samples/apps/github-qna-webapp-react/package.json delete mode 100644 samples/apps/github-qna-webapp-react/public/favicon.ico delete mode 100644 samples/apps/github-qna-webapp-react/public/index.html delete mode 100644 samples/apps/github-qna-webapp-react/src/App.css delete mode 100644 samples/apps/github-qna-webapp-react/src/App.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/assets/icons8-github-512.png delete mode 100644 samples/apps/github-qna-webapp-react/src/components/FunctionProbe.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/components/GitHubRepoSelection.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/components/QnA.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/components/QuickTipGroup.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/components/QuickTips.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/components/ServiceConfig.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/components/chat/ChatHistoryItem.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/components/chat/ChatInput.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/components/setup/ModelConfig.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/hooks/SemanticKernel.ts delete mode 100644 samples/apps/github-qna-webapp-react/src/hooks/useSemanticKernel.ts delete mode 100644 samples/apps/github-qna-webapp-react/src/index.tsx delete mode 100644 samples/apps/github-qna-webapp-react/src/model/Ask.ts delete mode 100644 samples/apps/github-qna-webapp-react/src/model/AskResult.ts delete mode 100644 samples/apps/github-qna-webapp-react/src/model/KeyConfig.ts delete mode 100644 samples/apps/github-qna-webapp-react/src/react-app-env.d.ts delete mode 100644 samples/apps/github-qna-webapp-react/tsconfig.json delete mode 100644 samples/apps/github-qna-webapp-react/yarn.lock delete mode 100644 samples/apps/hugging-face-http-server/Dockerfile delete mode 100644 samples/apps/hugging-face-http-server/README.md delete mode 100644 samples/apps/hugging-face-http-server/inference_app.py delete mode 100644 samples/apps/hugging-face-http-server/requirements.txt delete mode 100644 samples/apps/hugging-face-http-server/static/css/styles.css delete mode 100644 samples/apps/hugging-face-http-server/templates/completions.html delete mode 100644 samples/apps/hugging-face-http-server/templates/documentation.html delete mode 100644 samples/apps/hugging-face-http-server/templates/embeddings.html delete mode 100644 samples/apps/hugging-face-http-server/templates/home.html delete mode 100644 samples/apps/hugging-face-http-server/templates/images.html delete mode 100644 samples/apps/hugging-face-http-server/utils/CompletionGenerator.py delete mode 100644 samples/apps/hugging-face-http-server/utils/EmbeddingGenerator.py delete mode 100644 samples/apps/hugging-face-http-server/utils/ImageGenerator.py delete mode 100644 samples/apps/hugging-face-http-server/utils/InferenceGenerator.py delete mode 100644 samples/apps/hugging-face-http-server/utils/create_responses.py delete mode 100644 samples/apps/prettier.config.js delete mode 100644 samples/dotnet/Directory.Build.props delete mode 100644 samples/dotnet/Directory.Build.targets delete mode 100644 samples/dotnet/Directory.Packages.props delete mode 100644 samples/dotnet/KernelHttpServer/.vscode/extensions.json delete mode 100644 samples/dotnet/KernelHttpServer/Config/AIService.cs delete mode 100644 samples/dotnet/KernelHttpServer/Config/AIServiceConfig.cs delete mode 100644 samples/dotnet/KernelHttpServer/Config/ApiKeyConfig.cs delete mode 100644 samples/dotnet/KernelHttpServer/Config/Constants.cs delete mode 100644 samples/dotnet/KernelHttpServer/Extensions.cs delete mode 100644 samples/dotnet/KernelHttpServer/KernelHttpServer.csproj delete mode 100644 samples/dotnet/KernelHttpServer/Model/Ask.cs delete mode 100644 samples/dotnet/KernelHttpServer/Model/AskResult.cs delete mode 100644 samples/dotnet/KernelHttpServer/PingEndpoint.cs delete mode 100644 samples/dotnet/KernelHttpServer/Plugins/GitHubPlugin.cs delete mode 100644 samples/dotnet/KernelHttpServer/Program.cs delete mode 100644 samples/dotnet/KernelHttpServer/README.md delete mode 100644 samples/dotnet/KernelHttpServer/SemanticKernelEndpoint.cs delete mode 100644 samples/dotnet/KernelHttpServer/SemanticKernelFactory.cs delete mode 100644 samples/dotnet/KernelHttpServer/TokenAuthenticationProvider.cs delete mode 100644 samples/dotnet/KernelHttpServer/Utils/RepoFiles.cs delete mode 100644 samples/dotnet/KernelHttpServer/Utils/YourAppException.cs delete mode 100644 samples/dotnet/KernelHttpServer/host.json delete mode 100644 samples/dotnet/KernelHttpServer/local.settings.json delete mode 100644 samples/dotnet/MsGraphPluginsExample/AzureOpenAIConfiguration.cs delete mode 100644 samples/dotnet/MsGraphPluginsExample/MsGraphPluginsExample.csproj delete mode 100644 samples/dotnet/MsGraphPluginsExample/OpenAIConfiguration.cs delete mode 100644 samples/dotnet/MsGraphPluginsExample/Program.cs delete mode 100644 samples/dotnet/MsGraphPluginsExample/Properties/launchSettings.json delete mode 100644 samples/dotnet/MsGraphPluginsExample/README.md delete mode 100644 samples/dotnet/MsGraphPluginsExample/RepoFiles.cs delete mode 100644 samples/dotnet/MsGraphPluginsExample/YourAppException.cs delete mode 100644 samples/dotnet/MsGraphPluginsExample/appsettings.json delete mode 100644 samples/dotnet/OpenApiPluginsExample/AIServiceOptions.cs delete mode 100644 samples/dotnet/OpenApiPluginsExample/GitHubPlugin/Model/PullRequest.cs delete mode 100644 samples/dotnet/OpenApiPluginsExample/GitHubPlugin/Model/User.cs delete mode 100644 samples/dotnet/OpenApiPluginsExample/GitHubPlugin/openapi.json delete mode 100644 samples/dotnet/OpenApiPluginsExample/GitHubPluginOptions.cs delete mode 100644 samples/dotnet/OpenApiPluginsExample/NotEmptyOrWhitespaceAttribute.cs delete mode 100644 samples/dotnet/OpenApiPluginsExample/OpenApiPluginsExample.csproj delete mode 100644 samples/dotnet/OpenApiPluginsExample/Program.cs delete mode 100644 samples/dotnet/OpenApiPluginsExample/README.md delete mode 100644 samples/dotnet/OpenApiPluginsExample/RequiredOnPropertyValueAttribute.cs delete mode 100644 samples/dotnet/OpenApiPluginsExample/appsettings.json delete mode 100644 samples/dotnet/kernel-syntax-examples/README.md delete mode 100644 samples/dotnet/nuget.config delete mode 100644 samples/python/kernel-syntax-examples/README.md delete mode 100644 samples/python/kernel_http_server/.funcignore delete mode 100644 samples/python/kernel_http_server/README.md delete mode 100644 samples/python/kernel_http_server/function_app.py delete mode 100644 samples/python/kernel_http_server/host.json delete mode 100644 samples/python/kernel_http_server/local.settings.json delete mode 100644 samples/python/kernel_http_server/requirements.txt delete mode 100644 samples/python/kernel_http_server/utils/ask.py delete mode 100644 samples/python/kernel_http_server/utils/config.py delete mode 100644 samples/python/kernel_http_server/utils/kernel_server.py delete mode 100644 samples/python/kernel_http_server/utils/kernel_utils.py diff --git a/.github/workflows/node-pr.yml b/.github/workflows/node-pr.yml deleted file mode 100644 index dda61b7489..0000000000 --- a/.github/workflows/node-pr.yml +++ /dev/null @@ -1,72 +0,0 @@ -# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs - -name: node-pr - -on: - workflow_dispatch: - pull_request: - branches: ["main"] - paths: - - "samples/apps/**" - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - find-yarn-projects: - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.set-yarn-folders.outputs.matrix }} - - steps: - - uses: actions/checkout@v4 - - - name: Find yarn projects - id: set-yarn-folders - # This step uses a bash script to find all subfolders of /samples that contain a yarn.lock file - run: | - #!/bin/bash - set -e # exit with nonzero exit code if anything fails - shopt -s globstar # enable globstar option to use ** for recursive matching - yarndirs=() - for lockfile in samples/apps/**/yarn.lock; do # loop over all yarn.lock files - dir=$(dirname "$lockfile") # get the directory of the lock file - echo "Found yarn project in $dir" - yarndirs+=("$dir") # add the directory to the yarndirs array - done - - echo "All yarn projects found: '${yarndirs[*]}'" - yarndirs_json=$(echo -n "${yarndirs[*]%\n}" | jq -R -s -j --compact-output 'split(" ")') - matrix_json="{\"node_version\":[18], \"yarn_folder\":$yarndirs_json}" - echo "Setting output matrix to $matrix_json" - echo "matrix=$matrix_json" >> $GITHUB_OUTPUT - - build: - runs-on: ubuntu-latest - needs: find-yarn-projects - - strategy: - matrix: ${{ fromJson(needs.find-yarn-projects.outputs.matrix) }} - - steps: - - uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node_version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node_version }} - cache: "yarn" - cache-dependency-path: "samples/apps/**/yarn.lock" - - - name: Run yarn install & yarn build - # This step runs yarn install and yarn build for each project. - # The --frozen-lockfile option ensures that the dependencies are installed exactly as specified in the lock file. - # The -cwd option sets the current working directory to the folder where the yarn.lock file is located. - run: | - #!/bin/bash - set -e # exit with nonzero exit code if anything fails - dir=${{ matrix.yarn_folder }} # get the directory of the lock file - echo "Running yarn install and yarn build for $dir" - yarn --cwd "$dir" install --frozen-lockfile # install dependencies - yarn --cwd "$dir" build # run build script diff --git a/.gitignore b/.gitignore index ce57c294ee..4d2ef3c569 100644 --- a/.gitignore +++ b/.gitignore @@ -412,7 +412,6 @@ FodyWeavers.xsd .env certs/ launchSettings.json -!samples/dotnet/MsGraphPluginsExample/Properties/launchSettings.json config.development.yaml *.development.config *.development.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ec84e76218..7993d68920 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -371,70 +371,6 @@ "group": "PR-Validate" } }, - // KernelHttpServer - { - "label": "run (KernelHttpServer)", - "command": "func", - "type": "shell", - "args": ["start", "--csharp"], - "group": "test", - "options": { - "cwd": "${workspaceFolder}/samples/dotnet/KernelHttpServer" - }, - "presentation": { - "reveal": "always", - "panel": "shared", - "group": "Run-Samples" - } - }, - // chat-summary-webapp-react - { - "label": "run (Starter Chat WebApp React)", - "command": "yarn", - "type": "shell", - "args": ["start"], - "group": "test", - "options": { - "cwd": "${workspaceFolder}/samples/apps/chat-summary-webapp-react" - }, - "presentation": { - "reveal": "always", - "panel": "shared", - "group": "Run-Samples" - } - }, - // book-creator-webapp-react - { - "label": "run (Book Creator WebApp React)", - "command": "yarn", - "type": "shell", - "args": ["start"], - "group": "test", - "options": { - "cwd": "${workspaceFolder}/samples/apps/book-creator-webapp-react" - }, - "presentation": { - "reveal": "always", - "panel": "shared", - "group": "Run-Samples" - } - }, - // auth-api-webapp-react - { - "label": "run (Auth API WebApp React)", - "command": "yarn", - "type": "shell", - "args": ["start"], - "group": "test", - "options": { - "cwd": "${workspaceFolder}/samples/apps/auth-api-webapp-react" - }, - "presentation": { - "reveal": "always", - "panel": "shared", - "group": "Run-Samples" - } - } ], "inputs": [ { diff --git a/dotnet/SK-dotnet.sln b/dotnet/SK-dotnet.sln index fa0837075e..d595ce4cec 100644 --- a/dotnet/SK-dotnet.sln +++ b/dotnet/SK-dotnet.sln @@ -16,10 +16,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{FA37 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KernelSyntaxExamples", "samples\KernelSyntaxExamples\KernelSyntaxExamples.csproj", "{47C6F821-5103-431F-B3B8-A2868A68BB78}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MsGraphPluginsExample", "..\samples\dotnet\MsGraphPluginsExample\MsGraphPluginsExample.csproj", "{3EB61E99-C39B-4620-9482-F8DA18E48525}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KernelHttpServer", "..\samples\dotnet\KernelHttpServer\KernelHttpServer.csproj", "{34A7F1EF-D243-4160-A413-D713FEABCD94}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTests", "src\IntegrationTests\IntegrationTests.csproj", "{E4B777A1-28E1-41BE-96AE-7F3EC61FD5D4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugins.Document", "src\Plugins\Plugins.Document\Plugins.Document.csproj", "{F94D1938-9DB7-4B24-9FF3-166DDFD96330}" @@ -90,8 +86,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "InternalUtilities", "Intern EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.Memory.Weaviate", "src\Connectors\Connectors.Memory.Weaviate\Connectors.Memory.Weaviate.csproj", "{6AAB0620-33A1-4A98-A63B-6560B9BA47A4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiPluginsExample", "..\samples\dotnet\OpenApiPluginsExample\OpenApiPluginsExample.csproj", "{4D91A3E0-C404-495B-AD4A-411C4E83CF54}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.Memory.DuckDB", "src\Connectors\Connectors.Memory.DuckDB\Connectors.Memory.DuckDB.csproj", "{50FAE231-6F24-4779-9D02-12ABBC9A49E2}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{5C246969-D794-4EC3-8E8F-F90D4D166420}" @@ -191,16 +185,6 @@ Global {47C6F821-5103-431F-B3B8-A2868A68BB78}.Publish|Any CPU.ActiveCfg = Release|Any CPU {47C6F821-5103-431F-B3B8-A2868A68BB78}.Release|Any CPU.ActiveCfg = Release|Any CPU {47C6F821-5103-431F-B3B8-A2868A68BB78}.Release|Any CPU.Build.0 = Release|Any CPU - {3EB61E99-C39B-4620-9482-F8DA18E48525}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3EB61E99-C39B-4620-9482-F8DA18E48525}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3EB61E99-C39B-4620-9482-F8DA18E48525}.Publish|Any CPU.ActiveCfg = Release|Any CPU - {3EB61E99-C39B-4620-9482-F8DA18E48525}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3EB61E99-C39B-4620-9482-F8DA18E48525}.Release|Any CPU.Build.0 = Release|Any CPU - {34A7F1EF-D243-4160-A413-D713FEABCD94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {34A7F1EF-D243-4160-A413-D713FEABCD94}.Debug|Any CPU.Build.0 = Debug|Any CPU - {34A7F1EF-D243-4160-A413-D713FEABCD94}.Publish|Any CPU.ActiveCfg = Release|Any CPU - {34A7F1EF-D243-4160-A413-D713FEABCD94}.Release|Any CPU.ActiveCfg = Release|Any CPU - {34A7F1EF-D243-4160-A413-D713FEABCD94}.Release|Any CPU.Build.0 = Release|Any CPU {E4B777A1-28E1-41BE-96AE-7F3EC61FD5D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E4B777A1-28E1-41BE-96AE-7F3EC61FD5D4}.Debug|Any CPU.Build.0 = Debug|Any CPU {E4B777A1-28E1-41BE-96AE-7F3EC61FD5D4}.Publish|Any CPU.ActiveCfg = Release|Any CPU @@ -333,11 +317,6 @@ Global {6AAB0620-33A1-4A98-A63B-6560B9BA47A4}.Publish|Any CPU.Build.0 = Publish|Any CPU {6AAB0620-33A1-4A98-A63B-6560B9BA47A4}.Release|Any CPU.ActiveCfg = Release|Any CPU {6AAB0620-33A1-4A98-A63B-6560B9BA47A4}.Release|Any CPU.Build.0 = Release|Any CPU - {4D91A3E0-C404-495B-AD4A-411C4E83CF54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D91A3E0-C404-495B-AD4A-411C4E83CF54}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D91A3E0-C404-495B-AD4A-411C4E83CF54}.Publish|Any CPU.ActiveCfg = Release|Any CPU - {4D91A3E0-C404-495B-AD4A-411C4E83CF54}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D91A3E0-C404-495B-AD4A-411C4E83CF54}.Release|Any CPU.Build.0 = Release|Any CPU {50FAE231-6F24-4779-9D02-12ABBC9A49E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {50FAE231-6F24-4779-9D02-12ABBC9A49E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {50FAE231-6F24-4779-9D02-12ABBC9A49E2}.Publish|Any CPU.ActiveCfg = Publish|Any CPU @@ -439,8 +418,6 @@ Global GlobalSection(NestedProjects) = preSolution {A284C7EB-2248-4A75-B112-F5DCDE65410D} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0} {47C6F821-5103-431F-B3B8-A2868A68BB78} = {FA3720F1-C99A-49B2-9577-A940257098BF} - {3EB61E99-C39B-4620-9482-F8DA18E48525} = {FA3720F1-C99A-49B2-9577-A940257098BF} - {34A7F1EF-D243-4160-A413-D713FEABCD94} = {FA3720F1-C99A-49B2-9577-A940257098BF} {E4B777A1-28E1-41BE-96AE-7F3EC61FD5D4} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0} {F94D1938-9DB7-4B24-9FF3-166DDFD96330} = {D6D598DF-C17C-46F4-B2B9-CDE82E2DE132} {689A5041-BAE7-448F-9BDC-4672E96249AA} = {D6D598DF-C17C-46F4-B2B9-CDE82E2DE132} @@ -468,7 +445,6 @@ Global {136823BE-8665-4D57-87E0-EF41535539E2} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C} {4D3DAE63-41C6-4E1C-A35A-E77BDFC40675} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0} {6AAB0620-33A1-4A98-A63B-6560B9BA47A4} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C} - {4D91A3E0-C404-495B-AD4A-411C4E83CF54} = {FA3720F1-C99A-49B2-9577-A940257098BF} {50FAE231-6F24-4779-9D02-12ABBC9A49E2} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C} {5C246969-D794-4EC3-8E8F-F90D4D166420} = {4D3DAE63-41C6-4E1C-A35A-E77BDFC40675} {958AD708-F048-4FAF-94ED-D2F2B92748B9} = {4D3DAE63-41C6-4E1C-A35A-E77BDFC40675} diff --git a/dotnet/notebooks/06-memory-and-embeddings.ipynb b/dotnet/notebooks/06-memory-and-embeddings.ipynb index 69be621eb6..87f957165d 100644 --- a/dotnet/notebooks/06-memory-and-embeddings.ipynb +++ b/dotnet/notebooks/06-memory-and-embeddings.ipynb @@ -419,10 +419,6 @@ " = \"Sample demonstrating how to create a chat plugin interfacing with ChatGPT\",\n", " [\"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/Plugins/Plugins.Memory/VolatileMemoryStore.cs\"]\n", " = \"C# class that defines a volatile embedding store\",\n", - " [\"https://github.com/microsoft/semantic-kernel/tree/main/samples/dotnet/KernelHttpServer/README.md\"]\n", - " = \"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4\",\n", - " [\"https://github.com/microsoft/semantic-kernel/tree/main/samples/apps/chat-summary-webapp-react/README.md\"]\n", - " = \"README: README associated with a sample starter react-based chat summary webapp\",\n", "};" ] }, diff --git a/dotnet/notebooks/09-memory-with-chroma.ipynb b/dotnet/notebooks/09-memory-with-chroma.ipynb index 9e1257fd31..b2de3f713f 100644 --- a/dotnet/notebooks/09-memory-with-chroma.ipynb +++ b/dotnet/notebooks/09-memory-with-chroma.ipynb @@ -437,10 +437,6 @@ " = \"Sample demonstrating how to create a chat plugin interfacing with ChatGPT\",\n", " [\"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/Plugins/Plugins.Memory/VolatileMemoryStore.cs\"]\n", " = \"C# class that defines a volatile embedding store\",\n", - " [\"https://github.com/microsoft/semantic-kernel/tree/main/samples/dotnet/KernelHttpServer/README.md\"]\n", - " = \"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4\",\n", - " [\"https://github.com/microsoft/semantic-kernel/tree/main/samples/apps/chat-summary-webapp-react/README.md\"]\n", - " = \"README: README associated with a sample starter react-based chat summary webapp\",\n", "};" ] }, diff --git a/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs b/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs index e47ab6e5ce..57fa1838ee 100644 --- a/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs +++ b/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs @@ -166,10 +166,6 @@ public static class Example14_SemanticMemory = "Sample demonstrating how to create a chat plugin interfacing with ChatGPT", ["https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/VolatileMemoryStore.cs"] = "C# class that defines a volatile embedding store", - ["https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet/KernelHttpServer/README.md"] - = "README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4", - ["https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md"] - = "README: README associated with a sample chat summary react-based webapp", }; } } diff --git a/dotnet/samples/KernelSyntaxExamples/Example23_OpenApiPlugin_Github.cs b/dotnet/samples/KernelSyntaxExamples/Example23_OpenApiPlugin_Github.cs deleted file mode 100644 index f7872ce320..0000000000 --- a/dotnet/samples/KernelSyntaxExamples/Example23_OpenApiPlugin_Github.cs +++ /dev/null @@ -1,85 +0,0 @@ -īģŋ// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.Threading.Tasks; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Functions.OpenAPI.Authentication; -using Microsoft.SemanticKernel.Functions.OpenAPI.Extensions; -using Microsoft.SemanticKernel.Functions.OpenAPI.Model; -using Microsoft.SemanticKernel.Orchestration; -using Newtonsoft.Json.Linq; -using RepoUtils; - -/// -/// Import and run GitHub Functions using OpenAPI Plugin. -/// To use this example, run: -/// dotnet user-secrets set "Github.PAT" "github_pat_..." -/// Make sure your GitHub PAT has read permissions set for Pull Requests. -/// Creating a PAT: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token -/// -// ReSharper disable once InconsistentNaming -public static class Example23_OpenApiPlugin_GitHub -{ - public static async Task RunAsync() - { - var authenticationProvider = new BearerAuthenticationProvider(() => { return Task.FromResult(TestConfiguration.Github.PAT); }); - Console.WriteLine("== Example23_OpenApiPlugin_GitHub =="); - var firstPRNumber = await ListPullRequestsFromGitHubAsync(authenticationProvider); - await GetPullRequestFromGitHubAsync(authenticationProvider, firstPRNumber); - } - - public static async Task ListPullRequestsFromGitHubAsync(BearerAuthenticationProvider authenticationProvider) - { - var kernel = new KernelBuilder().WithLoggerFactory(ConsoleLogger.LoggerFactory).Build(); - - var plugin = await kernel.ImportPluginFunctionsAsync( - "GitHubPlugin", - "../../../../../../samples/dotnet/OpenApiPluginsExample/GitHubPlugin/openapi.json", - new OpenApiFunctionExecutionParameters { AuthCallback = authenticationProvider.AuthenticateRequestAsync }); - - // Add arguments for required parameters, arguments for optional ones can be skipped. - var contextVariables = new ContextVariables(); - contextVariables.Set("owner", "microsoft"); - contextVariables.Set("repo", "semantic-kernel"); - - // Run - var kernelResult = await kernel.RunAsync(contextVariables, plugin["PullList"]); - - Console.WriteLine("Successful GitHub List Pull Requests plugin response."); - var response = kernelResult.GetValue(); - if (response != null) - { - var pullRequests = JArray.Parse(response.Content?.ToString() ?? "null"); - - if (pullRequests != null && pullRequests.First != null) - { - var number = pullRequests.First["number"]; - return number?.ToString() ?? string.Empty; - } - } - Console.WriteLine("No pull requests found."); - - return string.Empty; - } - - public static async Task GetPullRequestFromGitHubAsync(BearerAuthenticationProvider authenticationProvider, string pullNumber) - { - var kernel = new KernelBuilder().WithLoggerFactory(ConsoleLogger.LoggerFactory).Build(); - - var plugin = await kernel.ImportPluginFunctionsAsync( - "GitHubPlugin", - "../../../../../../samples/dotnet/OpenApiPluginsExample/GitHubPlugin/openapi.json", - new OpenApiFunctionExecutionParameters { AuthCallback = authenticationProvider.AuthenticateRequestAsync }); - - // Add arguments for required parameters, arguments for optional ones can be skipped. - var contextVariables = new ContextVariables(); - contextVariables.Set("owner", "microsoft"); - contextVariables.Set("repo", "semantic-kernel"); - contextVariables.Set("pull_number", pullNumber); - - // Run - var kernelResult = await kernel.RunAsync(contextVariables, plugin["PullsGet"]); - - Console.WriteLine("Successful GitHub Get Pull Request plugin response: {0}", kernelResult.GetValue()?.Content); - } -} diff --git a/python/notebooks/06-memory-and-embeddings.ipynb b/python/notebooks/06-memory-and-embeddings.ipynb index 4e43e925be..540127ef8f 100644 --- a/python/notebooks/06-memory-and-embeddings.ipynb +++ b/python/notebooks/06-memory-and-embeddings.ipynb @@ -328,11 +328,7 @@ "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT\"] = \\\n", " \"Sample demonstrating how to create a chat skill interfacing with ChatGPT\"\n", "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/Volatile/VolatileMemoryStore.cs\"] = \\\n", - " \"C# class that defines a volatile embedding store\"\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/dotnet/KernelHttpServer/README.md\"] = \\\n", - " \"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4\"\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/apps/chat-summary-webapp-react/README.md\"] = \\\n", - " \"README: README associated with a sample starter react-based chat summary webapp\"" + " \"C# class that defines a volatile embedding store\"" ] }, { diff --git a/python/notebooks/third_party/weaviate-persistent-memory.ipynb b/python/notebooks/third_party/weaviate-persistent-memory.ipynb index 58a3fcfd1f..90ef285bb7 100644 --- a/python/notebooks/third_party/weaviate-persistent-memory.ipynb +++ b/python/notebooks/third_party/weaviate-persistent-memory.ipynb @@ -441,13 +441,7 @@ "] = \"Sample demonstrating how to create a chat skill interfacing with ChatGPT\"\n", "github_files[\n", " \"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/Volatile/VolatileMemoryStore.cs\"\n", - "] = \"C# class that defines a volatile embedding store\"\n", - "github_files[\n", - " \"https://github.com/microsoft/semantic-kernel/tree/main/samples/dotnet/KernelHttpServer/README.md\"\n", - "] = \"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4\"\n", - "github_files[\n", - " \"https://github.com/microsoft/semantic-kernel/tree/main/samples/apps/chat-summary-webapp-react/README.md\"\n", - "] = \"README: README associated with a sample starter react-based chat summary webapp\"" + "] = \"C# class that defines a volatile embedding store\"" ] }, { diff --git a/samples/apps/.eslintrc.js b/samples/apps/.eslintrc.js deleted file mode 100644 index 3755ebea6f..0000000000 --- a/samples/apps/.eslintrc.js +++ /dev/null @@ -1,37 +0,0 @@ -module.exports = { - env: { - es2021: true, - }, - extends: [ - 'eslint:recommended', - 'plugin:react/recommended', - 'plugin:react-hooks/recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:@typescript-eslint/recommended-requiring-type-checking', - 'plugin:@typescript-eslint/strict', - ], - ignorePatterns: ['build', '.*.js', 'node_modules'], - parserOptions: { - project: './tsconfig.json', - ecmaVersion: 'latest', - sourceType: 'module', - }, - rules: { - '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], - '@typescript-eslint/triple-slash-reference': ['error', { types: 'prefer-import' }], - '@typescript-eslint/non-nullable-type-assertion-style': 'off', - '@typescript-eslint/strict-boolean-expressions': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/consistent-type-imports': 'off', - '@typescript-eslint/no-empty-function': 'off', - '@typescript-eslint/no-explicit-any': 'off', - 'react/react-in-jsx-scope': 'off', - 'react/prop-types': 'off', - 'react/jsx-props-no-spreading': 'off', - }, - settings: { - react: { - version: 'detect', - }, - }, -}; diff --git a/samples/apps/README.md b/samples/apps/README.md deleted file mode 100644 index fd8675a27c..0000000000 --- a/samples/apps/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Sample Applications -This folder contains a set of end-to-end applications leveraging various features of the Semantic Kernel orchestrator. \ No newline at end of file diff --git a/samples/apps/auth-api-webapp-react/.env.example b/samples/apps/auth-api-webapp-react/.env.example deleted file mode 100644 index dc1fffca82..0000000000 --- a/samples/apps/auth-api-webapp-react/.env.example +++ /dev/null @@ -1,8 +0,0 @@ -REACT_APP_GRAPH_CLIENT_ID= -REACT_APP_GRAPH_SCOPES=User.Read,Files.ReadWrite,Tasks.ReadWrite,Mail.Send -REACT_APP_FUNCTION_URI=http://localhost:7071 -REACT_APP_OPEN_AI_KEY= -REACT_APP_OPEN_AI_MODEL= -REACT_APP_AZURE_OPEN_AI_KEY= -REACT_APP_AZURE_OPEN_AI_DEPLOYMENT= -REACT_APP_AZURE_OPEN_AI_ENDPOINT= diff --git a/samples/apps/auth-api-webapp-react/.env.local b/samples/apps/auth-api-webapp-react/.env.local deleted file mode 100644 index 1460107535..0000000000 --- a/samples/apps/auth-api-webapp-react/.env.local +++ /dev/null @@ -1,2 +0,0 @@ -# Disable ESLint in all environments -DISABLE_ESLINT_PLUGIN=true \ No newline at end of file diff --git a/samples/apps/auth-api-webapp-react/README.md b/samples/apps/auth-api-webapp-react/README.md deleted file mode 100644 index 8e3f546388..0000000000 --- a/samples/apps/auth-api-webapp-react/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Authenticated API’s Sample Learning App - -> [!IMPORTANT] -> This sample will be removed in a future release. If you are looking for samples that demonstrate -> how to use Semantic Kernel, please refer to the sample folders in the root [python](../../../python/samples/) -> and [dotnet](../../../dotnet/samples/) folders. - -> [!IMPORTANT] -> This learning sample is for educational purposes only and should not be used in any production -> use case. It is intended to highlight concepts of Semantic Kernel and not any -> architectural / security design practices to be used. - -### Watch the Authenticated API’s Sample Quick Start [Video](https://aka.ms/SK-Samples-AuthAPI-Video) - -## Running the sample - -1. You will need an [OpenAI Key](https://openai.com/product/) or - [Azure OpenAI Service key](https://learn.microsoft.com/azure/cognitive-services/openai/quickstart) - for this sample -2. Ensure the KernelHttpServer sample is already running at `http://localhost:7071`. If not, follow the steps - to start it [here](../../dotnet/KernelHttpServer/README.md). -3. You will also need to - [register your application](https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app) - in the Azure Portal. Follow the steps to register your app - [here](https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app). - - Select **`Single-page application (SPA)`** as platform type, and the Redirect URI will be **`http://localhost:3000`** - - Select **`Personal Microsoft accounts only`** as supported account types for this sample -4. Copy **[.env.example](.env.example)** into a new file with name "**.env**". - > **Note**: Samples are configured to use chat completion AI models (e.g., gpt-3.5-turbo, gpt-4, etc.). See https://platform.openai.com/docs/models/model-endpoint-compatibility for chat completion model options. -5. Once registered, copy the **Application (client) ID** from the Azure Portal and paste - the GUID into the **.env** file next to `REACT_APP_GRAPH_CLIENT_ID=` (first line of the .env file). -6. **Run** the following command `yarn install` (if you have never run the sample before) - and/or `yarn start` from the command line. -7. A browser will automatically open, otherwise you can navigate to `http://localhost:3000` to use the sample. - -> Working with Secrets: [KernelHttpServer's Readme](../../dotnet/KernelHttpServer/README.md#Working-with-Secrets) has a note on safely working with keys and other secrets. - -## About the Authenticated API’s Sample - -The Authenticated API’s sample allows you to use authentication to connect to the -Microsoft Graph using your personal account. - -If you don’t have a Microsoft account or do not want to connect to it, -you can review the code to see the patterns needed to call out to APIs. - -The sample highlights connecting to Microsoft Graph and calling APIs for Outlook, OneDrive, and ToDo. -Each function will call Microsoft Graph and/or Open AI to perform the tasks. - -> [!CAUTION] -> Each function will call Open AI which will use tokens that you will be billed for. - -## Troubleshooting - -### unauthorized_client: The client does not exist or is not enabled for consumers. - -1. Ensure in your Application Manifest that **`Personal Microsoft accounts`** are allowed to sign in. - - - `"signInAudience": "PersonalMicrosoftAccount"` or - - `"signInAudience": "AzureADandPersonalMicrosoftAccount"` - -2. If you are not able to change the manifest, create a new Application following the instructions in [Running the sample](#running-the-sample), step 3. diff --git a/samples/apps/auth-api-webapp-react/package.json b/samples/apps/auth-api-webapp-react/package.json deleted file mode 100644 index cdfe0bbe35..0000000000 --- a/samples/apps/auth-api-webapp-react/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "starter-identity-webapp-react", - "version": "0.1.0", - "private": true, - "dependencies": { - "@azure/msal-browser": "^2.33.0", - "@azure/msal-react": "^1.5.3", - "@fluentui/react-components": "^9.15.6", - "msal": "^1.4.17", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^14.0.0", - "@testing-library/user-event": "^14.4.3", - "@types/jest": "^29.4.0", - "@types/node": "^18.14.0", - "@types/react": "^18.0.28", - "@types/react-dom": "^18.0.11", - "eslint": "^8.42.0", - "react-scripts": "5.0.1", - "typescript": "^4.9.5" - }, - "scripts": { - "lint": "eslint src", - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/samples/apps/auth-api-webapp-react/public/favicon.ico b/samples/apps/auth-api-webapp-react/public/favicon.ico deleted file mode 100644 index bfe873eb228f98720fe0ed18c638daa13906958f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17174 zcmeHOJ#Q015PgP|sUltJ%A8D-(o!TUkc{NQ1+uPjPZg!4M<`cP($XUeDk>yUiu?k8 z10_|E2qK~~GdH`@9=;55lyHgjMj7wN?OyiY%vw?RV_+}{(X$}` zkiRp}d#2#VM9RE@(KQaI zUnaWs7TXteX8N); ON)^VQz<8Ga>-ryC<7BY_ diff --git a/samples/apps/auth-api-webapp-react/public/index.html b/samples/apps/auth-api-webapp-react/public/index.html deleted file mode 100644 index ba8b8c4393..0000000000 --- a/samples/apps/auth-api-webapp-react/public/index.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - Authentication and API's App - - - - -
- - - - \ No newline at end of file diff --git a/samples/apps/auth-api-webapp-react/src/App.css b/samples/apps/auth-api-webapp-react/src/App.css deleted file mode 100644 index 2bd4b20d46..0000000000 --- a/samples/apps/auth-api-webapp-react/src/App.css +++ /dev/null @@ -1,45 +0,0 @@ -body { - padding: 0px; - margin: 0px; -} - -#container { - display: flex; - flex-direction: column; - align-items: stretch; - justify-content: space-between; -} - -#header { - background-color: #9c2153; - width: 100%; - height: 40px; - color: #FFF; - display: flex; -} - -#header h1 { - padding-left: 20px; - align-items: center; - display: flex; -} - -#content { - display: flex; - align-items: stretch; - flex-direction: row; - padding-top: 12px; - gap: 80px; -} - -#main { - display: flex; - align-items: stretch; - flex-direction: column; - gap: 10px; -} - -#tipbar { - background-color: #FAF9F8; - width: 360px; -} \ No newline at end of file diff --git a/samples/apps/auth-api-webapp-react/src/App.tsx b/samples/apps/auth-api-webapp-react/src/App.tsx deleted file mode 100644 index ca4d0d67d7..0000000000 --- a/samples/apps/auth-api-webapp-react/src/App.tsx +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -import { AuthenticatedTemplate, useAccount, useIsAuthenticated, useMsal } from '@azure/msal-react'; -import { Subtitle1, Tab, TabList } from '@fluentui/react-components'; -import { FC, useEffect, useState } from 'react'; -import FunctionProbe from './components/FunctionProbe'; -import InteractWithGraph from './components/InteractWithGraph'; -import QuickTips, { ITipGroup } from './components/QuickTips'; -import ServiceConfig from './components/ServiceConfig'; -import YourInfo from './components/YourInfo'; -import { IKeyConfig } from './model/KeyConfig'; - -const App: FC = () => { - enum AppState { - ProbeForFunction = 0, - YourInfo = 1, - Setup = 2, - InteractWithGraph = 3, - } - - const isAuthenticated = useIsAuthenticated(); - const { instance, accounts } = useMsal(); - const account = useAccount(accounts[0] || {}); - const [appState, setAppState] = useState(AppState.ProbeForFunction); - const [selectedTabValue, setSelectedTabValue] = useState(isAuthenticated ? 'setup' : 'yourinfo'); - const [config, setConfig] = useState(); - - const appStateToTabValueMap = new Map([ - [AppState.Setup, 'setup'], - [AppState.InteractWithGraph, 'interact'], - [AppState.YourInfo, 'yourinfo'], - ]); - const tabValueToAppStateMap = new Map([ - ['setup', AppState.Setup], - ['yourinfo', AppState.YourInfo], - ['interact', AppState.InteractWithGraph], - ]); - - useEffect(() => { - changeAppState(appState); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [appState]); - - useEffect(() => { - if (isAuthenticated) { - setAppState(AppState.Setup); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isAuthenticated]); - - const changeAppState = function (newAppState: AppState) { - setAppState(newAppState); - setSelectedTabValue(appStateToTabValueMap.get(newAppState) ?? 'setup'); - }; - const changeTabValue = function (newTabValue: string) { - setSelectedTabValue(newTabValue); - setAppState(tabValueToAppStateMap.get(newTabValue) ?? AppState.Setup); - }; - - useEffect(() => { - const fetchAsync = async () => { - if (config === undefined || config === null) { - return; - } - - var result = await instance.acquireTokenSilent({ - account: account !== null ? account : undefined, - scopes: (process.env.REACT_APP_GRAPH_SCOPES as string).split(','), - forceRefresh: false, - }); - - config.graphToken = result.accessToken; - setConfig(config); - }; - - fetchAsync(); - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [config]); - - const tips: ITipGroup[] = [ - { - header: 'Useful Resources', - items: [ - { - title: 'Read Documentation', - uri: 'https://aka.ms/SKDoc-Auth-API', - }, - ], - }, - { - header: 'Functions used in this sample', - items: [ - { - title: 'Summarize', - uri: 'https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/SummarizeSkill/Summarize', - }, - { - title: 'AppendTextAsync', - uri: 'https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel.Skills/Skills.Document/DocumentSkill.cs#L86', - }, - { - title: 'UploadFileAsync', - uri: 'https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel.Skills/Skills.MsGraph/CloudDriveSkill.cs#L61', - }, - { - title: 'CreateLinkAsync', - uri: 'https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel.Skills/Skills.MsGraph/CloudDriveSkill.cs#L88', - }, - { - title: 'GetMyEmailAddressAsync', - uri: 'https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel.Skills/Skills.MsGraph/EmailSkill.cs#L55', - }, - { - title: 'SendEmailAsync', - uri: 'https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel.Skills/Skills.MsGraph/EmailSkill.cs#L65', - }, - { - title: 'AddTaskAsync', - uri: 'https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel.Skills/Skills.MsGraph/TaskListSkill.cs#L71', - }, - ], - }, - { - header: 'Local SK URL', - items: [ - { - title: process.env.REACT_APP_FUNCTION_URI as string, - uri: process.env.REACT_APP_FUNCTION_URI as string, - }, - ], - }, - ]; - - return ( -
- - - {appState === AppState.ProbeForFunction ? ( - setAppState(isAuthenticated ? AppState.Setup : AppState.YourInfo)} - /> - ) : null} -
-
- {appState === AppState.ProbeForFunction ? null : ( - changeTabValue(data.value as string)} - > - Your Info - - Setup - - - Interact - - - )} -
- {appState === AppState.YourInfo ? : null} - - {appState === AppState.Setup ? ( - { - setConfig(config); - setAppState(AppState.InteractWithGraph); - }} - /> - ) : null} - - {appState === AppState.InteractWithGraph ? ( - - { - changeAppState(appState - 1); - }} - /> - - ) : null} -
-
- {appState === AppState.ProbeForFunction ? null : ( -
- -
- )} -
-
- ); -}; - -export default App; diff --git a/samples/apps/auth-api-webapp-react/src/components/FunctionProbe.tsx b/samples/apps/auth-api-webapp-react/src/components/FunctionProbe.tsx deleted file mode 100644 index b2d7b635c5..0000000000 --- a/samples/apps/auth-api-webapp-react/src/components/FunctionProbe.tsx +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -import { Body1, Spinner, Title3 } from '@fluentui/react-components'; -import { FC, useEffect } from 'react'; - -interface IData { - uri: string; - onFunctionFound: () => void; -} - -const FunctionProbe: FC = ({ uri, onFunctionFound }) => { - useEffect(() => { - const fetchAsync = async () => { - try { - var result = await fetch(`${uri}/api/ping`); - - if (result.ok) { - onFunctionFound(); - } - } catch {} - }; - - fetchAsync(); - }); - - return ( -
- Looking for your function - - - This sample expects to find the Azure Function from samples/dotnet/KernelHttpServer{' '} - running at {uri} - - - Run your Azure Function locally using{' '} - - Visual Studio - - ,{' '} - - Visual Studio Code - {' '} - or from the command line using the{' '} - - Azure Functions Core Tools - - -
- ); -}; - -export default FunctionProbe; diff --git a/samples/apps/auth-api-webapp-react/src/components/InteractWithGraph.tsx b/samples/apps/auth-api-webapp-react/src/components/InteractWithGraph.tsx deleted file mode 100644 index 9f0d7255d8..0000000000 --- a/samples/apps/auth-api-webapp-react/src/components/InteractWithGraph.tsx +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -import { Body1, Button, Image, Textarea, Title3 } from '@fluentui/react-components'; -import React, { FC } from 'react'; -import wordLogo from '../../src/word.png'; -import { useSemanticKernel } from '../hooks/useSemanticKernel'; -import { IKeyConfig } from '../model/KeyConfig'; -import InteractionButton from './InteractionButton'; - -interface IData { - uri: string; - config: IKeyConfig; - onBack: () => void; -} - -const InteractWithGraph: FC = ({ uri, config, onBack }) => { - const sk = useSemanticKernel(uri); - const defaultText = `A glacier is a persistent body of dense ice that is constantly moving under its own weight. A glacier forms where the accumulation of snow exceeds its ablation over many years, often centuries. It acquires distinguishing features, such as crevasses and seracs, as it slowly flows and deforms under stresses induced by its weight. As it moves, it abrades rock and debris from its substrate to create landforms such as cirques, moraines, or fjords. Although a glacier may flow into a body of water, it forms only on land and is distinct from the much thinner sea ice and lake ice that form on the surface of bodies of water.`; - const filename = 'AuthenticationSampleSummary.docx'; - const path = '%temp%\\' + filename; - const destinationPath = '/' + filename; - - const [text, setText] = React.useState(defaultText); - - const runTask1 = async () => { - try { - //get summary - var summary = await sk.invokeAsync(config, { value: text }, 'summarizeskill', 'summarize'); - - //write document - await sk.invokeAsync( - config, - { - value: summary.value, - inputs: [{ key: 'filePath', value: path }], - }, - 'documentskill', - 'appendtext', - ); - - //upload to onedrive - await sk.invokeAsync( - config, - { - value: path, - inputs: [{ key: 'destinationPath', value: destinationPath }], - }, - 'clouddriveskill', - 'uploadfile', - ); - } catch (e) { - alert('Something went wrong.\n\nDetails:\n' + e); - } - }; - - const runTask2 = async () => { - try { - var shareLink = await sk.invokeAsync( - config, - { value: destinationPath }, - 'clouddriveskill', - 'createlink', - ); - var myEmail = await sk.invokeAsync(config, { value: '' }, 'emailskill', 'getmyemailaddress'); - - await sk.invokeAsync( - config, - { - value: `Here's the link: ${shareLink.value}\n\nReminder: Please delete the document on your OneDrive after you finish with this sample app.`, - inputs: [ - { - key: 'recipients', - value: myEmail.value, - }, - { - key: 'subject', - value: 'Semantic Kernel Authentication Sample Project Document Link', - }, - ], - }, - 'emailskill', - 'sendemail', - ); - } catch (e) { - alert('Something went wrong.\n\nDetails:\n' + e); - } - }; - - const runTask3 = async () => { - try { - var reminderDate = new Date(); - reminderDate.setDate(reminderDate.getDate() + 3); - - await sk.invokeAsync( - config, - { - value: 'Remind me to follow up re the authentication sample email', - inputs: [ - { - key: 'reminder', - value: reminderDate.toISOString(), - }, - ], - }, - 'tasklistskill', - 'addtask', - ); - } catch (e) { - alert('Something went wrong.\n\nDetails:\n' + e); - } - }; - - return ( -
- Interact with data and services - - You can interact with data and Microsoft services for your account. Ask questions about your data or ask - for help to complete a task. - - -
-
- - Sample Doc: {filename} -
- -